示例#1
0
/* Function to write a byte at a specific address */
bool eeprom_write_byte(uint16_t address, uint8_t data)
{
	bool success = true;

	/* send START and wait for completion */
	i2c_send_start(I2C1);
	while ((I2C_SR1(I2C1) & I2C_SR1_SB) == 0);

	/* send device address, r/w request and wait for completion */
	i2c_send_7bit_address(I2C1, ADDRESS_BYTE, I2C_WRITE);
	while ((I2C_SR1(I2C1) & I2C_SR1_ADDR) == 0);

	/* check SR2 and go on if OK */
	if ((I2C_SR2(I2C1) & I2C_SR2_MSL)		/* master mode */
	&&	(I2C_SR2(I2C1) & I2C_SR2_BUSY)) {	/* communication ongoing  */

		/* send memory address MSB */
		i2c_send_data(I2C1, ((uint8_t)(address >> 8)));
		while ((I2C_SR1(I2C1) & I2C_SR1_TxE) == 0);

		/* send memory address LSB */
		i2c_send_data(I2C1, ((uint8_t)address));
		while ((I2C_SR1(I2C1) & I2C_SR1_TxE) == 0);

		/* send data byte */
		i2c_send_data(I2C1, data);
		while ((I2C_SR1(I2C1) & I2C_SR1_TxE) == 0);

		/* send stop */
		i2c_send_stop(I2C1);

		/* ATTENTION: consider to wait for a while */
	} else {
int tda18219_write_reg(uint8_t reg, uint8_t value)
{
	uint32_t __attribute__((unused)) reg32;

	/* Send START condition. */
	i2c_send_start(I2C1);

	/* Waiting for START is send and switched to master mode. */
	while (!((I2C_SR1(I2C1) & I2C_SR1_SB)
		& (I2C_SR2(I2C1) & (I2C_SR2_MSL | I2C_SR2_BUSY))));

	/* Say to what address we want to talk to. */
	/* Yes, WRITE is correct - for selecting register in STTS75. */
	i2c_send_7bit_address(I2C1, TDA18219_I2C_ADDR, I2C_WRITE);

	/* Waiting for address is transferred. */
	while (!(I2C_SR1(I2C1) & I2C_SR1_ADDR));

	/* Cleaning ADDR condition sequence. */
	reg32 = I2C_SR2(I2C1);

	i2c_send_data(I2C1, reg);
	while (!(I2C_SR1(I2C1) & I2C_SR1_TxE));

	i2c_send_data(I2C1, value);
	while (!(I2C_SR1(I2C1) & (I2C_SR1_BTF | I2C_SR1_TxE)));

	i2c_send_stop(I2C1);

	return 0;
}
void stts75_write_config(uint32_t i2c, uint8_t sensor)
{
	uint32_t reg32 __attribute__((unused));

	/* Send START condition. */
	i2c_send_start(i2c);

	/* Waiting for START is send and switched to master mode. */
	while (!((I2C_SR1(i2c) & I2C_SR1_SB)
		& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));

	/* Send destination address. */
	i2c_send_7bit_address(i2c, sensor, I2C_WRITE);

	/* Waiting for address is transferred. */
	while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));

	/* Cleaning ADDR condition sequence. */
	reg32 = I2C_SR2(i2c);

	/* Sending the data. */
	i2c_send_data(i2c, 0x1); /* stts75 config register */
	while (!(I2C_SR1(i2c) & I2C_SR1_BTF)); /* Await ByteTransferedFlag. */
	/* Polarity reverse - LED glows if temp is below Tos/Thyst. */
	i2c_send_data(i2c, 0x4);
	while (!(I2C_SR1(i2c) & (I2C_SR1_BTF | I2C_SR1_TxE)));

	/* Send STOP condition. */
	i2c_send_stop(i2c);
}
void stts75_write_temp_hyst(uint32_t i2c, uint8_t sensor, uint16_t temp_hyst)
{
	uint32_t reg32 __attribute__((unused));

	/* Send START condition. */
	i2c_send_start(i2c);

	/* Waiting for START is send and therefore switched to master mode. */
	while (!((I2C_SR1(i2c) & I2C_SR1_SB)
		& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));

	/* Say to what address we want to talk to. */
	i2c_send_7bit_address(i2c, sensor, I2C_WRITE);

	/* Waiting for address is transferred. */
	while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));

	/* Cleaning ADDR condition sequence. */
	reg32 = I2C_SR2(i2c);

	/* Sending the data. */
	i2c_send_data(i2c, 0x2); /* TemperatureHysteresis register */
	while (!(I2C_SR1(i2c) & I2C_SR1_BTF));
	i2c_send_data(i2c, (uint8_t)(temp_hyst >> 8)); /* MSB */
	while (!(I2C_SR1(i2c) & I2C_SR1_BTF));
	i2c_send_data(i2c, (uint8_t)(temp_hyst & 0xff00)); /* LSB */
	/* After the last byte we have to wait for TxE too. */
	while (!(I2C_SR1(i2c) & (I2C_SR1_BTF | I2C_SR1_TxE)));

	/* Send STOP condition. */
	i2c_send_stop(i2c);
}
示例#5
0
static int i2c_write(uint8_t reg, uint8_t val)
{
    while ((I2C_SR2(I2C_PORT) & I2C_SR2_BUSY)) {
    }
    gpio_set(GPIOG, GPIO13);
    i2c_send_start(I2C_PORT);

    /* Wait for master mode selected */
    while (!((I2C_SR1(I2C_PORT) & I2C_SR1_SB)
           & (I2C_SR2(I2C_PORT) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
    gpio_set(GPIOG, GPIO14);
    i2c_send_7bit_address(I2C_PORT, SLAVE_ADDRESS, I2C_WRITE);

    /* Waiting for address is transferred. */
    while (!(I2C_SR1(I2C_PORT) & I2C_SR1_ADDR));

    /* Cleaning ADDR condition sequence. */
    uint32_t reg32 = I2C_SR2(I2C_PORT);
    (void) reg32; /* unused */

    /* Common above here */

    /* Sending the data. */
    i2c_send_data(I2C_PORT, reg);
    while (!(I2C_SR1(I2C_PORT) & (I2C_SR1_BTF)));
    i2c_send_data(I2C_PORT, val);
    while (!(I2C_SR1(I2C_PORT) & (I2C_SR1_BTF | I2C_SR1_TxE)));

    /* Send STOP condition. */
    i2c_send_stop(I2C_PORT);
    return 0;
}
void stts75_write_temp_os(uint32_t i2c, uint8_t sensor, uint16_t temp_os)
{
	uint32_t reg32 __attribute__((unused));

	/* Send START condition. */
	i2c_send_start(i2c);

	/* Waiting for START is send and switched to master mode. */
	while (!((I2C_SR1(i2c) & I2C_SR1_SB)
		& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));

	/* Send destination address. */
	i2c_send_7bit_address(i2c, sensor, I2C_WRITE);

	/* Waiting for address is transferred. */
	while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));

	/* Cleaning ADDR condition sequence. */
	reg32 = I2C_SR2(i2c);

	/* Sending the data. */
	i2c_send_data(i2c, 0x3); /* OvertemperatureShutdown register */
	while (!(I2C_SR1(i2c) & I2C_SR1_BTF));
	i2c_send_data(i2c, (uint8_t)(temp_os >> 8)); /* MSB */
	while (!(I2C_SR1(i2c) & I2C_SR1_BTF));
	i2c_send_data(i2c, (uint8_t)(temp_os & 0xff00)); /* LSB */
	/* After the last byte we have to wait for TxE too. */
	while (!(I2C_SR1(i2c) & (I2C_SR1_BTF | I2C_SR1_TxE)));

	/* Send STOP condition. */
	i2c_send_stop(i2c);
}
示例#7
0
static uint32_t i2c_read(uint8_t reg)
{
    //    while ((I2C_SR2(i2c) & I2C_SR2_BUSY)) {
    //    }

    i2c_send_start(I2C_PORT);

    /* Wait for master mode selected */
    while (!((I2C_SR1(I2C_PORT) & I2C_SR1_SB)
           & (I2C_SR2(I2C_PORT) & (I2C_SR2_MSL | I2C_SR2_BUSY))));

    i2c_send_7bit_address(I2C_PORT, SLAVE_ADDRESS, I2C_WRITE);

    /* Waiting for address is transferred. */
    while (!(I2C_SR1(I2C_PORT) & I2C_SR1_ADDR));

    /* Cleaning ADDR condition sequence. */
    uint32_t reg32 = I2C_SR2(I2C_PORT);
    (void) reg32; /* unused */

    /*  Common stuff ABOVE HERE     */

    i2c_send_data(I2C_PORT, reg);
    while (!(I2C_SR1(I2C_PORT) & (I2C_SR1_BTF)));

    i2c_send_start(I2C_PORT);

    /* Wait for master mode selected */
    while (!((I2C_SR1(I2C_PORT) & I2C_SR1_SB)
           & (I2C_SR2(I2C_PORT) & (I2C_SR2_MSL | I2C_SR2_BUSY))));

    i2c_send_7bit_address(I2C_PORT, SLAVE_ADDRESS, I2C_READ);

    /* Waiting for address is transferred. */
    while (!(I2C_SR1(I2C_PORT) & I2C_SR1_ADDR));

    i2c_disable_ack(I2C_PORT);

    /* Cleaning ADDR condition sequence. */
    reg32 = I2C_SR2(I2C_PORT);
    (void) reg32; /* unused */

    i2c_send_stop(I2C_PORT);

    while (!(I2C_SR1(I2C_PORT) & I2C_SR1_RxNE));
    uint32_t result = i2c_get_data(I2C_PORT);

    i2c_enable_ack(I2C_PORT);
    I2C_SR1(I2C_PORT) &= ~I2C_SR1_AF;
    return result;
}
示例#8
0
static inline void stmi2c_clear_pending_interrupts(uint32_t i2c)
{
  uint16_t SR1 = I2C_SR1(i2c);

  // Certainly do not wait for buffer interrupts:
  // -------------------------------------------
  i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);			// Disable TXE, RXNE

  // Error interrupts are handled separately:
  // ---------------------------------------

  // Clear Event interrupt conditions:
  // --------------------------------

  // Start Condition Was Generated
  if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) )
  {
    // SB: cleared by software when reading SR1 and writing to DR
    i2c_send_data(i2c, 0x00);
  }
  // Address Was Sent
  if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) )
  {
    // ADDR: Cleared by software when reading SR1 and then SR2
    uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c);
  }
  // Byte Transfer Finished
  if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) )
  {
    // SB: cleared by software when reading SR1 and reading/writing to DR
    uint8_t dummy __attribute__ ((unused)) = i2c_get_data(i2c);
    i2c_send_data(i2c, 0x00);
  }

}
示例#9
0
// Doc ID 13902 Rev 11 p 714/1072
// Transfer Sequence Diagram for Master Receiver for N=1
static inline enum STMI2CSubTransactionStatus stmi2c_read1(uint32_t i2c, struct i2c_periph *periph, struct i2c_transaction *trans)
{
  uint16_t SR1 = I2C_SR1(i2c);

  // Start Condition Was Just Generated
  if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) )
  {
    i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
    i2c_send_data(i2c, trans->slave_addr | 0x01);

    // Document the current Status
    periph->status = I2CAddrRdSent;
  }
  // Address Was Sent
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) )
  {
    // First Clear the ACK bit: after the next byte we do not want new bytes
    i2c_nack_current(i2c);
    i2c_disable_ack(i2c);

    // --- next to steps MUST be executed together to avoid missing the stop
    __I2C_REG_CRITICAL_ZONE_START;

    // Only after setting ACK, read SR2 to clear the ADDR (next byte will start arriving)
    uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c);

    // Schedule a Stop
    PPRZ_I2C_SEND_STOP(i2c);

    __I2C_REG_CRITICAL_ZONE_STOP;
    // --- end of critical zone -----------

    // Enable the RXNE: it will trigger as soon as the 1 byte is received to get the result
    i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);

    // Document the current Status
    periph->status = I2CReadingLastByte;
  }
  // As soon as there is 1 byte ready to read, we have our byte
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_RxNE, SR1) )
  {
    i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
    trans->buf[0] = I2C_DR(i2c);

    // We got all the results (stop condition might still be in progress but this is the last interrupt)
    trans->status = I2CTransSuccess;

    // Document the current Status:
    // -the stop was actually already requested in the previous step
    periph->status = I2CStopRequested;

    return STMI2C_SubTra_Ready_StopRequested;
  }
  else // Event Logic Error
  {
    return STMI2C_SubTra_Error;
  }

  return STMI2C_SubTra_Busy;
}
示例#10
0
static void
com_send_start()
{
	/* send start */
	i2c_send_start(I2C1);
	while (!((I2C_SR1(I2C1) & I2C_SR1_SB)
	        & (I2C_SR2(I2C1) & (I2C_SR2_MSL | I2C_SR2_BUSY))))
	        ;

	/* send address */
	i2c_send_7bit_address(I2C1, current_address, I2C_WRITE);
	while (!(I2C_SR1(I2C1) & I2C_SR1_ADDR))
		;
	(void)I2C_SR2(I2C1);

	selected = true;
}
示例#11
0
void i2c_transmit(const i2c_channel *cp, const uint8_t *data, size_t count)
{
    uint32_t base = cp->i_base_address;

    if (cp->i_is_master) {

        // Send start condition.
        I2C_CR1(base) |= I2C_CR1_START;
        uint32_t t0 = system_millis;
        while (!(I2C_SR1(base) & I2C_SR1_SB)) {
            if (system_millis >= t0 + TIMEOUT_MSEC) {
                fprintf(stderr, "i2c: timeout on SB\n");
                return;
            }
        }

        // Send slave address.
        I2C_DR(base) = cp->i_address & ~0x01;
        t0 = system_millis;
        while (!(I2C_SR1(base) & I2C_SR1_ADDR)) {
            if (I2C_SR1(base) & I2C_SR1_AF) {
                I2C_CR1(base) |= I2C_CR1_STOP;
                I2C_SR1(base) = ~I2C_SR1_AF;
                fprintf(stderr,
                        "i2c @ %ld: ack failure on addr\n",
                        system_millis / 1000);
                return;
            }
            if (system_millis >= t0 + TIMEOUT_MSEC) {
                fprintf(stderr, "i2c: timeout on ADDR\n");
                return;
            }
        }

        // Clear ADDR flag by reading SR1 and SR2 registers.
        uint16_t unused;
        unused = I2C_SR1(base);
        unused = I2C_SR2(base);
        unused = unused;

        // Write each data byte; wait for BTF.
        for (size_t i = 0; i < count; i++) {
            I2C_DR(base) = data[i];
            t0 = system_millis;
            while (!(I2C_SR1(base) & I2C_SR1_BTF)) {
                if (system_millis >= t0 + TIMEOUT_MSEC) {
                    fprintf(stderr, "i2c: timeout on BTF\n");
                    return;
                }
            }
        }
        I2C_CR1(base) |= I2C_CR1_STOP;
        fprintf(stderr, "i2c @ %lu: transmit complete\n", system_millis / 1000);
    } else {
        assert(false && "slave transmission not implemented");
    }
}
static uint8_t i2c_start(uint32_t i2c, uint8_t address, uint8_t mode)
{
	i2c_send_start(i2c);

	/* Wait for master mode selected */
	while (!((I2C_SR1(i2c) & I2C_SR1_SB)
		& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));

	i2c_send_7bit_address(i2c, address, mode);

	/* Waiting for address is transferred. */
	while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));

	/* Cleaning ADDR condition sequence. */
	uint32_t reg32 = I2C_SR2(i2c);
	(void) reg32; /* unused */

	return 0;
}
static uint32_t i2c_read(uint32_t i2c, uint8_t address, uint8_t reg)
{
	while ((I2C_SR2(i2c) & I2C_SR2_BUSY));

	i2c_start(i2c, address, I2C_WRITE);
	i2c_send_data(i2c, reg);

	while (!(I2C_SR1(i2c) & (I2C_SR1_BTF)));

	i2c_start(i2c, address, I2C_READ);

	i2c_send_stop(i2c);

	while (!(I2C_SR1(i2c) & I2C_SR1_RxNE));

	uint32_t result = i2c_get_data(i2c);

	I2C_SR1(i2c) &= ~I2C_SR1_AF;

	return result;
}
示例#14
0
bool_t i2c_idle(struct i2c_periph* periph)
{
  // This is actually a difficult function:
  // -simply reading the status flags can clear bits and corrupt the transaction

  uint32_t i2c = (uint32_t) periph->reg_addr;

#ifdef I2C_DEBUG_LED
#if USE_I2C1
  if (periph == &i2c1)
  {
    return TRUE;
  }
#endif
#endif

  // First we check if the software thinks it is ready
  if (periph->status == I2CIdle)
    return ! (BIT_X_IS_SET_IN_REG( I2C_SR2_BUSY, I2C_SR2(i2c) ) );
  else
    return FALSE;
}
uint16_t stts75_read_temperature(uint32_t i2c, uint8_t sensor)
{
	uint32_t reg32 __attribute__((unused));
	uint16_t temperature;

	/* Send START condition. */
	i2c_send_start(i2c);

	/* Waiting for START is send and switched to master mode. */
	while (!((I2C_SR1(i2c) & I2C_SR1_SB)
		& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));

	/* Say to what address we want to talk to. */
	/* Yes, WRITE is correct - for selecting register in STTS75. */
	i2c_send_7bit_address(i2c, sensor, I2C_WRITE);

	/* Waiting for address is transferred. */
	while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));

	/* Cleaning ADDR condition sequence. */
	reg32 = I2C_SR2(i2c);

	i2c_send_data(i2c, 0x0); /* temperature register */
	while (!(I2C_SR1(i2c) & (I2C_SR1_BTF | I2C_SR1_TxE)));

	/*
	 * Now we transferred that we want to ACCESS the temperature register.
	 * Now we send another START condition (repeated START) and then
	 * transfer the destination but with flag READ.
	 */

	/* Send START condition. */
	i2c_send_start(i2c);

	/* Waiting for START is send and switched to master mode. */
	while (!((I2C_SR1(i2c) & I2C_SR1_SB)
		& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));

	/* Say to what address we want to talk to. */
	i2c_send_7bit_address(i2c, sensor, I2C_READ);

	/* 2-byte receive is a special case. See datasheet POS bit. */
	I2C_CR1(i2c) |= (I2C_CR1_POS | I2C_CR1_ACK);

	/* Waiting for address is transferred. */
	while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));

	/* Cleaning ADDR condition sequence. */
	reg32 = I2C_SR2(i2c);

	/* Cleaning I2C_SR1_ACK. */
	I2C_CR1(i2c) &= ~I2C_CR1_ACK;

	/* Now the slave should begin to send us the first byte. Await BTF. */
	while (!(I2C_SR1(i2c) & I2C_SR1_BTF));
	temperature = (uint16_t)(I2C_DR(i2c) << 8); /* MSB */

	/*
	 * Yes they mean it: we have to generate the STOP condition before
	 * saving the 1st byte.
	 */
	I2C_CR1(i2c) |= I2C_CR1_STOP;

	temperature |= I2C_DR(i2c); /* LSB */

	/* Original state. */
	I2C_CR1(i2c) &= ~I2C_CR1_POS;

	return temperature;
}
示例#16
0
// Doc ID 13902 Rev 11 p 712/1072
// Transfer Sequence Diagram for Master Receiver for N>2
static inline enum STMI2CSubTransactionStatus stmi2c_readmany(uint32_t i2c, struct i2c_periph *periph, struct i2c_transaction *trans)
{
  uint16_t SR1 = I2C_SR1(i2c);

  // Start Condition Was Just Generated
  if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) )
  {
    i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
    // The first data byte will be acked in read many so the slave knows it should send more
    i2c_nack_current(i2c);
    i2c_enable_ack(i2c);
    // Clear the SB flag
    i2c_send_data(i2c, trans->slave_addr | 0x01);

    // Document the current Status
    periph->status = I2CAddrRdSent;
  }
  // Address Was Sent
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) )
  {
    periph->idx_buf = 0;

    // Enable RXNE: receive an interrupt any time a byte is available
    // only enable if MORE than 3 bytes need to be read
    if (periph->idx_buf < (trans->len_r - 3))
    {
      i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
    }

    // ACK is still on to get more DATA
    // Read SR2 to clear the ADDR (next byte will start arriving)
    uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c);

    // Document the current Status
    periph->status = I2CReadingByte;
  }
  // one or more bytes are available AND we were interested in Buffer interrupts
  else if ( (BIT_X_IS_SET_IN_REG(I2C_SR1_RxNE, SR1) ) && (BIT_X_IS_SET_IN_REG(I2C_CR2_ITBUFEN, I2C_CR2(i2c)))  )
  {
    // read byte until 3 bytes remain to be read (e.g. len_r = 6, -> idx=3 means idx 3,4,5 = 3 remain to be read
    if (periph->idx_buf < (trans->len_r - 3))
    {
      trans->buf[periph->idx_buf] = I2C_DR(i2c);
      periph->idx_buf ++;
    }
    // from : 3bytes -> last byte: do nothing
    //
    // finally: this was the last byte
    else if (periph->idx_buf >= (trans->len_r - 1))
    {
      i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);

      // Last Value
      trans->buf[periph->idx_buf] = i2c_get_data(i2c);
      periph->idx_buf ++;

      // We got all the results
      trans->status = I2CTransSuccess;

      return STMI2C_SubTra_Ready_StopRequested;
    }

    // Check for end of transaction: start waiting for BTF instead of RXNE
    if (periph->idx_buf < (trans->len_r - 3))
    {
      i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
    }
    else // idx >= len-3: there are 3 bytes to be read
    {
      // We want to halt I2C to have sufficient time to clear ACK, so:
      // Stop listening to RXNE as it will be triggered infinitely since we did not empty the buffer
      // on the next (second in buffer) received byte BTF will be set (buffer full and I2C halted)
      i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
    }
  }
  // Buffer is full while this was not a RXNE interrupt
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) )
  {
    // Now the shift register and data register contain data(n-2) and data(n-1)
    // And I2C is halted so we have time

    // --- Make absolutely sure the next 2 I2C actions are performed with no delay
    __I2C_REG_CRITICAL_ZONE_START;

    // First we clear the ACK while the SCL is held low by BTF
    i2c_disable_ack(i2c);

    // Now that ACK is cleared we read one byte: instantly the last byte is being clocked in...
    trans->buf[periph->idx_buf] = i2c_get_data(i2c);
    periph->idx_buf ++;

    // Now the last byte is being clocked. Stop in MUST be set BEFORE the transfer of the last byte is complete
    PPRZ_I2C_SEND_STOP(i2c);

    __I2C_REG_CRITICAL_ZONE_STOP;


    // --- end of critical zone -----------

    // Document the current Status
    periph->status = I2CStopRequested;

    // read the byte2 we had in the buffer (BTF means 2 bytes available)
    trans->buf[periph->idx_buf] = i2c_get_data(i2c);
    periph->idx_buf ++;

    // Ask for an interrupt to read the last byte (which is normally still busy now)
    // The last byte will be received with RXNE
    i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
  }
  else // Event Logic Error
  {
    return STMI2C_SubTra_Error;
  }

  return STMI2C_SubTra_Busy;
}
示例#17
0
// Doc ID 13902 Rev 11 p 713/1072
// Transfer Sequence Diagram for Master Receiver for N=2
static inline enum STMI2CSubTransactionStatus stmi2c_read2(uint32_t i2c, struct i2c_periph *periph, struct i2c_transaction *trans)
{
  uint16_t SR1 = I2C_SR1(i2c);

  // Start Condition Was Just Generated
  if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) )
  {
    // according to the datasheet: instantly shedule a NAK on the second received byte:
    i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
    i2c_enable_ack(i2c);
    i2c_nack_next(i2c);
    i2c_send_data(i2c, trans->slave_addr | 0x01);

    // Document the current Status
    periph->status = I2CAddrRdSent;
  }
  // Address Was Sent
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) )
  {
    // --- make absolutely sure this command is not delayed too much after the previous:
    // --- the NAK bits must be set before the first byte arrived: allow other interrupts here
    __I2C_REG_CRITICAL_ZONE_START;

    //       if transfer of DR was finished already then we will get too many bytes
    // BEFORE clearing ACK, read SR2 to clear the ADDR (next byte will start arriving)
    // clearing ACK after the byte transfer has already started will NACK the next (2nd)
    uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c);

    // NOT First Clear the ACK bit but only AFTER clearing ADDR
    i2c_disable_ack(i2c);

    // Disable the RXNE and wait for BTF
    i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);

    __I2C_REG_CRITICAL_ZONE_STOP;
    // --- end of critical zone -----------

    // We do not set the RxE but wait for both bytes to arrive using BTF

    // Document the current Status
    periph->status = I2CReadingByte;
  }
  // Receive buffer if full, master is halted: BTF
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) )
  {
    // Stop condition MUST be set BEFORE reading the DR
    // otherwise since there is new buffer space a new byte will be read
    PPRZ_I2C_SEND_STOP(i2c);

    // Document the current Status
    periph->status = I2CStopRequested;

    trans->buf[0] = I2C_DR(i2c);
    trans->buf[1] = I2C_DR(i2c);

    // We got all the results
    trans->status = I2CTransSuccess;

    return STMI2C_SubTra_Ready_StopRequested;
  }
  else // Event Logic Error
  {
    return STMI2C_SubTra_Error;
  }

  return STMI2C_SubTra_Busy;
}
示例#18
0
文件: i2c.c 项目: DuinoPilot/F4OS
int i2c_read(struct i2c_dev *i2c, uint8_t addr, uint8_t *data, uint32_t num) {
    if (!i2c || !i2c->ready || i2c->port < 1 || i2c->port > 3 || !data || !num) {
        return -1;
    }

    /* Check for bus error */
    if (*I2C_SR1(i2c->port) & I2C_SR1_BERR) {
        printk("I2C: Bus error, reseting.\r\n");
        /* Clear the error and reset I2C */
        *I2C_SR1(i2c->port) &= ~(I2C_SR1_BERR);

        if (i2c_reset(i2c)) {
            /* Failed to reset */
            return -1;
        }
    }

    /* Wait until BUSY is reset and previous transaction STOP is complete */
    int count = 10000;
    while ((*I2C_SR2(i2c->port) & I2C_SR2_BUSY) || (*I2C_CR1(i2c->port) & I2C_CR1_STOP)) {
        if (--count == 0) {
            printk("I2C: Stalled, reseting.\r\n");

            if (i2c_reset(i2c)) {
                /* Failed to reset */
                return -1;
            }
        }
        else if (count < 0) {
            printk("I2C: Stalled, reset failed, force clearing busy.\r\n");

            if (i2c_force_clear_busy(i2c)) {
                /* Failed to clear */
                return -1;
            }
        }
    }

    int total = 0;

    *I2C_CR1(i2c->port) |= I2C_CR1_START;

    count = 10000;
    while (!(*I2C_SR1(i2c->port) & I2C_SR1_SB)) {
        if (!count--) {
            i2c_stop(i2c->port);
            return -1;
        }
    }

    *I2C_DR(i2c->port) = (addr << 1) | 1;

    count = 10000;
    while (!(*I2C_SR1(i2c->port) & I2C_SR1_ADDR)) {
        if (*I2C_SR1(i2c->port) & I2C_SR1_AF || !count--) {
            i2c_stop(i2c->port);
            return -1;
        }
    }

    uint8_t single_byte = num == 1;

    if (!single_byte) {
        *I2C_CR1(i2c->port) |= I2C_CR1_ACK;
    }
    else {  /* In single byte receive, never ACK */
        *I2C_CR1(i2c->port) &= ~(I2C_CR1_ACK);
    }

    while (num--) {
        count = 10000;
        while (!(*I2C_SR2(i2c->port) & I2C_SR2_MSL)) {
            if (!count--) {
                i2c_stop(i2c->port);
                return -1;
            }
        }

        /* In single byte receive, stop after ADDR clear (SR1 and SR2 read) */
        if (single_byte) {
            i2c_stop(i2c->port);
        }

        count = 10000;
        while (!(*I2C_SR1(i2c->port) & I2C_SR1_RXNE)) {
            if (!count--) {
                i2c_stop(i2c->port);
                return -1;
            }
        }

        *data++ = *I2C_DR(i2c->port);
        total++;

        /* NACK and STOP after second last receive */
        if (num == 1) {
            *I2C_CR1(i2c->port) &= ~(I2C_CR1_ACK);
            i2c_stop(i2c->port);
        }
    }

    return total;
}
示例#19
0
文件: i2c.c 项目: DuinoPilot/F4OS
int8_t i2c_write(struct i2c_dev *i2c, uint8_t addr, uint8_t *data, uint32_t num) {
    if (!i2c || !i2c->ready || i2c->port < 1 || i2c->port > 3 || !data || !num) {
        return -1;
    }

    /* Check for bus error */
    if (*I2C_SR1(i2c->port) & I2C_SR1_BERR) {
        printk("I2C: Bus error, reseting.\r\n");
        /* Clear the error and reset I2C */
        *I2C_SR1(i2c->port) &= ~(I2C_SR1_BERR);

        if (i2c_reset(i2c)) {
            /* Failed to reset */
            return -1;
        }
    }

    /* Wait until BUSY is reset and previous transaction STOP is complete */
    int count = 10000;
    while ((*I2C_SR2(i2c->port) & I2C_SR2_BUSY) || (*I2C_CR1(i2c->port) & I2C_CR1_STOP)) {
        if (--count == 0) {
            printk("I2C: Stalled, reseting.\r\n");

            if (i2c_reset(i2c)) {
                /* Failed to reset */
                return -1;
            }
        }
        else if (count < 0) {
            printk("I2C: Stalled, reset failed, force clearing busy.\r\n");

            if (i2c_force_clear_busy(i2c)) {
                /* Failed to clear */
                return -1;
            }
        }
    }

    *I2C_CR1(i2c->port) |= I2C_CR1_START;

    count = 10000;
    while (!(*I2C_SR1(i2c->port) & I2C_SR1_SB)) {
        if (!count--) {
            i2c_stop(i2c->port);
            return -1;
        }
    }

    *I2C_DR(i2c->port) = addr << 1;

    count = 10000;
    while (!(*I2C_SR1(i2c->port) & I2C_SR1_ADDR)) {
        if ((*I2C_SR1(i2c->port) & I2C_SR1_AF) || !count--) {
            i2c_stop(i2c->port);
            return -1;
        }
    }

    count = 10000;
    while (!(*I2C_SR2(i2c->port) & I2C_SR2_MSL)) {
        if (!count--) {
            i2c_stop(i2c->port);
            return -1;
        }
    }

    int total = 0;

    while (num--) {
        /* Make sure shift register is empty */
        count = 10000;
        while (!(*I2C_SR1(i2c->port) & I2C_SR1_TXE)) {
            if (!count--) {
                i2c_stop(i2c->port);
                return -1;
            }
        }

        *I2C_DR(i2c->port) = *data++;

        count = 10000;
        while (!(*I2C_SR1(i2c->port) & I2C_SR1_TXE)) {
            if (!count--) {
                i2c_stop(i2c->port);
                return -1;
            }
        }

        total += 1;
    }

    i2c_stop(i2c->port);

    return total;
}
示例#20
0
文件: i2c.c 项目: DuinoPilot/F4OS
/* On rare occassions, the I2C device will get confused, either because we missed
 * a timing requirement, or it is just stupid.  Regardless, it holds SDA low waiting
 * for some unknown action from the master.  This keeps the bus BUSY and prevents
 * any further communication.  This condition is fixed by manually clocking SCL
 * until SDA is released by the slave.  As far as it is concerned, we just completed
 * a normal transaction. */
static int i2c_force_clear_busy(struct i2c_dev *i2c) {
    if (!i2c) {
        return -1;
    }

    int count = 10000;

    switch (i2c->port) {
    case 1:
        /* Set pins to output/input */
        gpio_moder(GPIOB, I2C1_SCL, GPIO_MODER_OUT);
        gpio_moder(GPIOB, I2C1_SDA, GPIO_MODER_IN);

        /* Toggle clock until bus no longer busy */
        while (!(*GPIO_IDR(GPIOB) & GPIO_IDR_PIN(I2C1_SDA))) {
            if (!count--) {
                /* Out of time, perhaps the last ditch effort will save us. */
                break;
            }

            /* Toggle clock */
            *GPIO_ODR(GPIOB) ^= GPIO_ODR_PIN(I2C1_SCL);
            for (volatile int delay = 100; delay > 0; delay--);
        }

        gpio_moder(GPIOB, I2C1_SCL, GPIO_MODER_ALT);
        gpio_moder(GPIOB, I2C1_SDA, GPIO_MODER_ALT);
        for (volatile int delay = 100; delay > 0; delay--);

        break;
    case 2:
        /* Set pins to output/input */
        gpio_moder(GPIOB, I2C2_SCL, GPIO_MODER_OUT);
        gpio_moder(GPIOB, I2C2_SDA, GPIO_MODER_IN);

        /* Toggle clock until SDA raised */
        while (!(*GPIO_IDR(GPIOB) & GPIO_IDR_PIN(I2C2_SDA))) {
            if (!count--) {
                /* Out of time, perhaps the last ditch effort will save us. */
                break;
            }

            /* Toggle clock */
            *GPIO_ODR(GPIOB) ^= GPIO_ODR_PIN(I2C2_SCL);
            for (volatile int delay = 100; delay > 0; delay--);
        }

        gpio_moder(GPIOB, I2C2_SCL, GPIO_MODER_ALT);
        gpio_moder(GPIOB, I2C2_SDA, GPIO_MODER_ALT);
        for (volatile int delay = 100; delay > 0; delay--);

        break;
    default:
        return -1;
    }

    /* Make sure the peripheral recognizes that the bus is now free */
    if (*I2C_SR2(i2c->port) & I2C_SR2_BUSY) {
        /* Last ditch effort */
        if (i2c_reset(i2c) || (*I2C_SR2(i2c->port) & I2C_SR2_BUSY)) {
            /* Failed to reset */
            printk("I2C: BUSY flag failed to clear.\r\nI2C: I have tried everything I know :(. At this point, reset is your best option.\r\n");
            return -1;
        }
    }

    return 0;
}
示例#21
0
// Doc ID 13902 Rev 11 p 710/1072
// Transfer Sequence Diagram for Master Transmitter
static inline enum STMI2CSubTransactionStatus stmi2c_send(uint32_t i2c, struct i2c_periph *periph, struct i2c_transaction *trans)
{
  uint16_t SR1 = I2C_SR1(i2c);

  // Start Condition Was Just Generated
  if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) )
  {
    // Disable buffer interrupt
    i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
    // Send Slave address and wait for ADDR interrupt
    i2c_send_data(i2c, trans->slave_addr);
    // Document the current Status
    periph->status = I2CAddrWrSent;
  }
  // Address Was Sent
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) )
  {
    // Now read SR2 to clear the ADDR status Bit
    uint16_t SR2  __attribute__ ((unused)) = I2C_SR2(i2c);

    // Maybe check we are transmitting (did not loose arbitration for instance)
    // if (! BIT_X_IS_SET_IN_REG(I2C_SR2_TRA, SR2)) { }
    // update: this should be caught by the ARLO error: so we will not arrive here

    // Send First max 2 bytes
    i2c_send_data(i2c, trans->buf[0]);
    if (trans->len_w > 1)
    {
      i2c_send_data(i2c, trans->buf[1]);
      periph->idx_buf = 2;
    }
    else
    {
      periph->idx_buf = 1;
    }

    // Enable buffer-space available interrupt
    // only if there is more to send: wait for TXE, no more to send: wait for BTF
    if ( periph->idx_buf < trans->len_w)
      i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);

    // Document the current Status
    periph->status = I2CSendingByte;
  }
  // The buffer is not full anymore AND we were not waiting for BTF
  else if ((BIT_X_IS_SET_IN_REG(I2C_SR1_TxE, SR1) ) && (BIT_X_IS_SET_IN_REG(I2C_CR2_ITBUFEN, I2C_CR2(i2c)))  )
  {
    // Send the next byte
    i2c_send_data(i2c, trans->buf[periph->idx_buf]);
    periph->idx_buf++;

    // All bytes Sent? Then wait for BTF instead
    if ( periph->idx_buf >= trans->len_w)
    {
      // Not interested anymore to know the buffer has space left
      i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
      // Next interrupt will be BTF (or error)
    }
  }
  // BTF: means last byte was sent
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) )
  {
    if (trans->type == I2CTransTx)
    {
      // Tell the driver we are ready
      trans->status = I2CTransSuccess;
    }
    // Otherwise we still need to do the receiving part

    return STMI2C_SubTra_Ready;
  }
  else // Event Logic Error
  {
    return STMI2C_SubTra_Error;
  }

  return STMI2C_SubTra_Busy;
}
示例#22
0
void i2c_receive(const i2c_channel *cp, uint8_t *data, size_t count)
{
    uint32_t base = cp->i_base_address;

    if (cp->i_is_master) {

        I2C_CR1(base) |= I2C_CR1_ACK;

        // Send start condition.
        I2C_CR1(base) |= I2C_CR1_START;
        uint32_t t0 = system_millis;
        while (!(I2C_SR1(base) & I2C_SR1_SB)) {
            if (system_millis >= t0 + TIMEOUT_MSEC) {
                fprintf(stderr, "i2c: timeout on SB\n");
                printf("SR1 = %#lx\n", I2C_SR1(base));
                return;
            }
        }

        // Send slave address.
        I2C_DR(base) = cp->i_address | 0x01;
        t0 = system_millis;
        while (!(I2C_SR1(base) & I2C_SR1_ADDR)) {
            if (I2C_SR1(base) & I2C_SR1_AF) {
                I2C_CR1(base) |= I2C_CR1_STOP;
                I2C_SR1(base) = ~I2C_SR1_AF;
                fprintf(stderr,
                        "i2c @ %ld: ack failure on addr\n",
                        system_millis / 1000);
                return;
            }
            if (system_millis >= t0 + TIMEOUT_MSEC) {
                fprintf(stderr, "i2c: timeout on ADDR\n");
                return;
            }
        }

        // Clear ADDR flag by reading SR1 and SR2 registers.
        uint16_t unused;
        unused = I2C_SR1(base);
        unused = I2C_SR2(base);
        unused = unused;

        // Read each data byte; wait for BTF.
        for (size_t i = 0; i < count; i++) {
            if (i + 1 == count)
                I2C_CR1(base) &= ~I2C_CR1_ACK;
            t0 = system_millis;
            while (true) {
                uint32_t sr1 = I2C_SR1(base);
                if (sr1 & (I2C_SR1_OVR | I2C_SR1_BERR)) {
                    fprintf(stderr, "i2c: receive error\n");
                    break;
                }
                if (sr1 & I2C_SR1_RxNE)
                    break;
                if (system_millis >= t0 + TIMEOUT_MSEC) {
                    fprintf(stderr, "i2c: timeout on receive\n");
                }
            }
            data[i] = I2C_DR(base);
            I2C_DR(base) = data[i];
        }
        printf("%lu: I2C receive complete\n", system_millis / 1000);
    } else {
        assert(false && "slave reception not implemented");
    }
}