/* 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); }
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); }
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; }
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); } }
// 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; }
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; }
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; }
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; }
// 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; }
// 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; }
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; }
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; }
/* 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; }
// 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; }
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"); } }