void i2c_handle_er_interrupt(_i2c_t *_i2c) { uint16_t sr1 = *i2c_get_SR1(_i2c); uint16_t sr2 = *i2c_get_SR2(_i2c); log_error("I2C ERROR, CR1: %x, CR2: %x, SR1: %x, SR2: %x, state: %x", *i2c_get_CR1(_i2c), *i2c_get_CR2(_i2c), sr1, sr2, state); if (sr1 & I2C_SR1__BERR) { log_error("Bus Error"); *i2c_get_SR1(_i2c) &= ~I2C_SR1__BERR; } if (sr1 & I2C_SR1__ARLO) { log_error("Arbitration Lost"); *i2c_get_SR1(_i2c) &= ~I2C_SR1__ARLO; } if (sr1 & I2C_SR1__AF) { log_error("Acknowledge Failure"); *i2c_get_SR1(_i2c) &= ~I2C_SR1__AF; } if (sr1 & I2C_SR1__OVR) { log_error("Overrun"); *i2c_get_SR1(_i2c) &= ~I2C_SR1__OVR; } if (sr1 & I2C_SR1__PECERR) { log_error("PEC error"); *i2c_get_SR1(_i2c) &= ~I2C_SR1__PECERR; } if (sr1 & I2C_SR1__TIMEOUT) { log_error("Timeout"); *i2c_get_SR1(_i2c) &= ~I2C_SR1__TIMEOUT; } if (sr1 & I2C_SR1__SMBALERT) { log_error("SMBAlert"); *i2c_get_SR1(_i2c) &= ~I2C_SR1__SMBALERT; } // Set stop bit to stop transfer *i2c_get_CR1(_i2c) |= I2C_CR1__STOP; // Update State state = I2C_ERROR; }
void i2c_enable(i2c_t i2c, i2c_clock_mode_t mode) { uint32_t pclk, freq; const _i2c_t *_i2c = i2c; // Disable the I2C EV and ERR interrupt lines in the NVIC nvic_disable_interrupt_line(_i2c->irq_line_ev); nvic_disable_interrupt_line(_i2c->irq_line_er); // Enable the clock for this peripheral rcc_apb_enable(_i2c->apb_bus, _i2c->apb_bit); // Reset the peripheral *i2c_get_CR1(_i2c) = I2C_CR1__SWRST; // Clear all registers *i2c_get_CR2(_i2c) = 0; *i2c_get_CCR(_i2c) = 0; *i2c_get_TRISE(_i2c) = 0; *i2c_get_SR1(_i2c) = 0; *i2c_get_SR2(_i2c) = 0; *i2c_get_OAR1(_i2c) = 0; *i2c_get_OAR2(_i2c) = 0; // Release SWRST *i2c_get_CR1(_i2c) = 0; /* Step 1: program the peripheral input clock in CR2 */ // Compute clock frequency pclk = rcc_sysclk_get_clock_frequency( _i2c->apb_bus == 1 ? RCC_SYSCLK_CLOCK_PCLK1 : RCC_SYSCLK_CLOCK_PCLK2); freq = pclk / 1000000; *i2c_get_CR2(_i2c) = freq & I2C_CR2__FREQ_MASK; /* Step 2: configure the clock control registers */ if (mode == I2C_CLOCK_MODE_FAST) { // Set Fast Speed mode and bitrate: ~400kHz uint32_t ccr = freq * 10; ccr = ccr / 12 + (ccr % 12 ? 1 : 0); *i2c_get_CCR(_i2c) = I2C_CCR__FS | ccr; } else { // Set Standard Speed mode and bitrate: 100kHz *i2c_get_CCR(_i2c) = (freq * 5) & I2C_CCR__CCR_MASK; } /* Step 3: configure the rise time registers */ if (mode == I2C_CLOCK_MODE_FAST) { // Configure maximum rise time *i2c_get_TRISE(_i2c) = (freq * 3 / 10 + 1) & I2C_TRISE__TRISE_MASK; } else { // Configure maximum rise time *i2c_get_TRISE(_i2c) = (freq + 1) & I2C_TRISE__TRISE_MASK; } /* Step 4: program the CR1 register to enable the peripheral */ // Enable I2C *i2c_get_CR1(_i2c) = I2C_CR1__PE; // Enable EVT and ERR interrupt // Note: do not enable BUF to avoid stm32f problem *i2c_get_CR2(_i2c) |= I2C_CR2__ITEVTEN | I2C_CR2__ITERREN; // Initialize I2C state _i2c->data->state = I2C_IDLE; _i2c->data->len_send = 0; _i2c->data->len_recv = 0; _i2c->data->cpt_send = 0; _i2c->data->cpt_recv = 0; _i2c->data->transfer_handler = NULL; // Enable I2C EV and ERR interrupt line in the NVIC nvic_enable_interrupt_line(_i2c->irq_line_ev); nvic_enable_interrupt_line(_i2c->irq_line_er); }
void i2c_handle_er_interrupt(const _i2c_t *_i2c) { uint16_t sr1 = *i2c_get_SR1(_i2c); uint16_t sr2 = *i2c_get_SR2(_i2c); (void) sr2; // clear defined but not used warning warning if (sr1 & I2C_SR1__BERR) { log_error("Bus Error"); *i2c_get_SR1(_i2c) &= ~I2C_SR1__BERR; } if (sr1 & I2C_SR1__ARLO) { log_error("Arbitration Lost"); *i2c_get_SR1(_i2c) &= ~I2C_SR1__ARLO; } if (sr1 & I2C_SR1__AF) { #ifdef I2C__SLAVE_SUPPORT if (_i2c->data->state == I2C_SL_TX) { *i2c_get_SR1(_i2c) &= ~I2C_SR1__AF; _i2c->data->state = I2C_IDLE; if (_i2c->data->slave_handler) { _i2c->data->slave_handler(I2C_SLAVE_EV_STOP, NULL); } return; } #endif log_error("Acknowledge Failure"); *i2c_get_SR1(_i2c) &= ~I2C_SR1__AF; } if (sr1 & I2C_SR1__OVR) { log_error("Overrun"); *i2c_get_SR1(_i2c) &= ~I2C_SR1__OVR; } if (sr1 & I2C_SR1__PECERR) { log_error("PEC error"); *i2c_get_SR1(_i2c) &= ~I2C_SR1__PECERR; } if (sr1 & I2C_SR1__TIMEOUT) { log_error("Timeout"); *i2c_get_SR1(_i2c) &= ~I2C_SR1__TIMEOUT; } if (sr1 & I2C_SR1__SMBALERT) { log_error("SMBAlert"); *i2c_get_SR1(_i2c) &= ~I2C_SR1__SMBALERT; } log_error("I2C ERROR, CR1: %x, CR2: %x, SR1: %x, SR2: %x, state: %x", *i2c_get_CR1(_i2c), *i2c_get_CR1(_i2c), sr1, sr2, _i2c->data->state); // Set stop bit to stop transfer *i2c_get_CR1(_i2c) |= I2C_CR1__STOP; // Update State tx_rx_end(_i2c, I2C_ERROR); }
void i2c_handle_ev_interrupt(const _i2c_t *_i2c) { _i2c_data_t *const data = _i2c->data; uint32_t sr1 = *i2c_get_SR1(_i2c); uint32_t sr2 = 0; (void) sr2; // clear defined but not used warning warning I2C_DEBUG_LOG(sr1, data->state, data->state == I2C_RECEIVING_DATA ? data->len_recv - data->cpt_recv : data->len_send - data->cpt_send); /* * EVxxx refer to the STM32 I2C datasheet's events * * STM32F1xx errata tells EV6_1 EV6_3 EV7 EV7_1 EV8 (and slave ones EV2 EV3) * should be handled before the current byte is transferred. * + EV6_1, EV6_3 must be un-interrupted * + EV8 must be done early enough * In consequence we mask TXBUFEN (RXNE and TXNE interrupt) */ if (sr1 & I2C_SR1__SB) { // ** EV5 ** // Start bit has been issued. // The flag is cleared after reading SR1 (already done at the // beginning of the function) and writing DR (done right now) // If there there is nothing to send, set the lower bit // of address to 1 as we are in receiving mode if (data->len_send == 0) { // Send address in order to receive data *i2c_get_DR(_i2c) = data->address | 1; // In the case of a 2-byte reception we need to set POS bit if (data->len_recv == 2) { *i2c_get_CR1(_i2c) |= I2C_CR1__POS; } } else { // Send address in order to send data *i2c_get_DR(_i2c) = data->address; } // Disable Buffer Interrupt *i2c_get_CR2(_i2c) &= ~I2C_CR2__ITBUFEN; // Enable ACK *i2c_get_CR1(_i2c) |= I2C_CR1__ACK; data->state = I2C_SENDING_ADDRESS; } if (sr1 & I2C_SR1__ADDR && data->state == I2C_SENDING_ADDRESS) { // ** EV6 ** // Master mode: Address byte has been sent. // The flag is cleared after reading both SR1 and SR2 // Send the first byte if any if (data->len_send > 0) { // Clear the flag by reading SR2. This must be done before sending data sr2 = *i2c_get_SR2(_i2c); // ** EV8_1 ** // Send data *i2c_get_DR(_i2c) = data->buf_send[data->cpt_send]; data->cpt_send++; if (data->cpt_send == data->len_send) { // ** EV8_2 ** // The only byte to send has already been sent so we need to issue // a STOP condition if there is nothing to receive or // a RESTART condition otherwise if (data->len_recv == 0) { // There is nothing to receive *i2c_get_CR1(_i2c) |= I2C_CR1__STOP; // The transfer is complete tx_rx_end(_i2c, I2C_IDLE); } else { // We need to read something *i2c_get_CR1(_i2c) |= I2C_CR1__START; // Wait for the new start condition to be issued data->state = I2C_SENDING_RESTART; } // Indicate that there is nothing else to send data->len_send = 0; data->cpt_send = 0; } else { // There is something else to send // Wait for the first byte to be sent data->state = I2C_SENDING_DATA; // STMF: do not enable ITBUFEN since we can not ensure // to handle EV8 before current byte transfer after TXNE // instead, we'll wait for BTF (which lower the transfer speed) } } else { switch (data->len_recv) { case 1: // ** EV6_3 ** // STM32F_errata: // + the sequence read_SR2 STOP should be fast enough // + or SCL must be tied low in during it // In this case we need to clear ACK bit right now *i2c_get_CR1(_i2c) &= ~I2C_CR1__ACK; // Clear the flag by reading SR2 sr2 = *i2c_get_SR2(_i2c); // We also need to program the STOP condition *i2c_get_CR1(_i2c) |= I2C_CR1__STOP; //activate ITBUFEN since we'll only receive a single byte *i2c_get_CR2(_i2c) |= I2C_CR2__ITBUFEN; break; case 2: // ** EV6_1 ** // STM32F_errata: // + the sequence read_SR2 NACK should be fast enough // + or SCL must be tied low in during it // Clear the flag by reading SR2 sr2 = *i2c_get_SR2(_i2c); // Clear ACK bit *i2c_get_CR1(_i2c) &= ~I2C_CR1__ACK; break; default: // In the default case we do not need to do anything // except clearing the flag by reading SR2 sr2 = *i2c_get_SR2(_i2c); break; } // Wait for the first byte to read data->state = I2C_RECEIVING_DATA; } // return there // in particular, we must not execute TXNE part because // we may have written into DR return; } #ifdef I2C__SLAVE_SUPPORT else if (sr1 & I2C_SR1__ADDR && (data->state == I2C_IDLE || (data->state == I2C_SL_RX && !(sr1 & I2C_SR1__RXNE)))) { // ** EV1 ** // Slave mode: Address byte has been acknowledged. // Clear the flag by reading SR2. sr2 = *i2c_get_SR2(_i2c); // Disable Buffer Interrupt *i2c_get_CR2(_i2c) &= ~I2C_CR2__ITBUFEN; if (sr2 & I2C_SR2__TRA) { uint8_t byte = 0; // we will send data data->state = I2C_SL_TX; if (data->slave_handler) { data->slave_handler(I2C_SLAVE_EV_TX_START, NULL); data->slave_handler(I2C_SLAVE_EV_TX_BYTE, &byte); } //send the first byte *i2c_get_DR(_i2c) = byte; } else { // we will receive data data->state = I2C_SL_RX; if (data->slave_handler) { data->slave_handler(I2C_SLAVE_EV_RX_START, NULL); } } return; } #endif if (sr1 & I2C_SR1__ADD10) { // This should not happen as we do not handle 10-bits addresses log_error("ADD10 interrupt!"); // Set stop bit to stop transfer *i2c_get_CR1(_i2c) |= I2C_CR1__STOP; // Update State tx_rx_end(_i2c, I2C_ERROR); return; } if (sr1 & I2C_SR1__RXNE) { /* Note: * when RXNE: * + 1 byte is in I2C controller buffers * + bus is not stalled (one byte may be in transfer) * when BTF & RXNE: * + 2 bytes are in I2C controller buffers * + bus is stalled (controller wait we read a byte) */ if (data->state == I2C_RECEIVING_DATA) { /* * * * * * * WARNING STM32F1xx HARDWARE ERRATA * * * * * * * * RXNE-only events should not be handled since it sometimes * * fails. Only BTF & RXNE events should be handled (with the * * consequence of slowing down the transfer). * * * * It seems that when a RXNE interrupt is handled 'around' * * the end of the next byte reception, the DR register read * * is ignored by the i2c controller: it does not flush the * * DR with next byte * * Thus we read twice the same byte and we read effectively * * read one byte less than expected from the i2c slave point * * of view. * * Example: * * + we want to receive 6 bytes (B1 to B6) * * + the problem appear when reading B3 * * -> we read B1 B2 B3 B3 B4 B5 (B3 twice) * * -> the i2c transfer was B1 B2 B3 B4 B5 (B6 is not sent) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int remaining = data->len_recv - data->cpt_recv; if (remaining <= 0) { //should not happen log_error("Bad I2C receiving state"); *i2c_get_CR1(_i2c) |= I2C_CR1__STOP; *i2c_get_DR(_i2c); *i2c_get_DR(_i2c); tx_rx_end(_i2c, I2C_ERROR); } else { switch (remaining) { default:// >=4 if (sr1 & I2C_SR1__BTF) { // ** EV7 ** // Read the byte that is in buffer data->buf_recv[data->cpt_recv++] = *i2c_get_DR(_i2c); } break; case 3: // Bytes 1..N-3 have been read if (sr1 & I2C_SR1__BTF) { // ** EV7 ** // Bytes N-2 and N-1 have been received // Program NACK *i2c_get_CR1(_i2c) &= ~I2C_CR1__ACK; // Read N-3 to ensure BTF after N (before STOP) data->buf_recv[data->cpt_recv++] = *i2c_get_DR(_i2c); } break; case 2: // Bytes 1..N-2 have been read if (sr1 & I2C_SR1__BTF) { // ** (EV7_1 and EV7) or EV7_3 ** // STM32F_errata: // + the sequence STOP read_DR read_DR should be fast enough // + or SCL must be tied low in during it // Program STOP *i2c_get_CR1(_i2c) |= I2C_CR1__STOP; // Read N-2 data->buf_recv[data->cpt_recv++] = *i2c_get_DR(_i2c); // Read N-1 data->buf_recv[data->cpt_recv++] = *i2c_get_DR(_i2c); // Indicate that there is nothing else to receive data->len_recv = 0; data->cpt_recv = 0; // Signal the transfer is complete tx_rx_end(_i2c, I2C_IDLE); } break; case 1: // ** EV7 ** // Happen only on single byte transfers // The byte has been received but not read // Note: BTF should not be set data->buf_recv[data->cpt_recv++] = *i2c_get_DR(_i2c); // Indicate that there is nothing else to receive data->len_recv = 0; data->cpt_recv = 0; // The transfer is complete tx_rx_end(_i2c, I2C_IDLE); break; } } } #ifdef I2C__SLAVE_SUPPORT else if (data->state == I2C_SL_RX) { if (sr1 & I2C_SR1__BTF || ((sr1 & I2C_SR1__ADDR) && (sr1 & I2C_SR1__TXE))) { // ** EV2 ** // read the byte into the buffer uint8_t byte = *i2c_get_DR(_i2c); data->slave_handler(I2C_SLAVE_EV_RX_BYTE, &byte); } } #endif } if (sr1 & I2C_SR1__TXE) { // The flag is cleared after reading SR1 (already done) and reading or writing DR if (data->state == I2C_SENDING_DATA) { if (data->len_send == data->cpt_send) { // ** EV8_2 ** // The last byte has been sent so we need to issue // a STOP condition if there is nothing to receive or // a RESTART condition otherwise if (data->len_recv == 0) { // There is nothing to receive *i2c_get_CR1(_i2c) |= I2C_CR1__STOP; // The transfer is complete tx_rx_end(_i2c, I2C_IDLE); } else { // We need to read something *i2c_get_CR1(_i2c) |= I2C_CR1__START; data->state = I2C_SENDING_RESTART; } // Indicate that there is nothing else to send data->len_send = 0; data->cpt_send = 0; } else { // ** EV8 ** // Send the data *i2c_get_DR(_i2c) = data->buf_send[data->cpt_send]; data->cpt_send++; // Stay in the I2C_SENDING_DATA state } } #ifdef I2C__SLAVE_SUPPORT else if (data->state == I2C_SL_TX) { // ** EV3 ** uint8_t byte; // request the byte to send data->slave_handler(I2C_SLAVE_EV_TX_BYTE, &byte); *i2c_get_DR(_i2c) = byte; } #endif } if (sr1 & I2C_SR1__STOPF) { switch (data->state) { #ifdef I2C__SLAVE_SUPPORT case I2C_SL_RX: if (sr1 & I2C_SR1__RXNE) { // it remains exactly 1 byte to read // since we have already read the buffer one (if any) uint8_t byte = *i2c_get_DR(_i2c); if (data->slave_handler) { data->slave_handler(I2C_SLAVE_EV_RX_BYTE, &byte); } } sr1 = *i2c_get_SR1(_i2c); *i2c_get_CR1(_i2c) &= ~I2C_CR1__STOP; data->state = I2C_IDLE; if (data->slave_handler) { data->slave_handler(I2C_SLAVE_EV_STOP, NULL); } break; case I2C_SL_TX: log_error("STOPF interrupt!"); data->state = I2C_IDLE; break; #endif default: // This should not happen as we are in master mode log_error("STOPF interrupt!"); uint8_t x = *i2c_get_CR1(_i2c); *i2c_get_CR1(_i2c) = x; // Set stop bit to stop transfer *i2c_get_CR1(_i2c) |= I2C_CR1__STOP; // Update State tx_rx_end(_i2c, I2C_ERROR); break; } } }
void i2c_enable(i2c_t i2c, i2c_clock_mode_t mode) { uint32_t pclk, freq; _i2c_t *_i2c = i2c; // Disable the I2C EV and ERR interrupt lines in the NVIC nvic_disable_interrupt_line(_i2c->irq_line_ev); nvic_disable_interrupt_line(_i2c->irq_line_er); // Enable the clock for this peripheral rcc_apb_enable(_i2c->apb_bus, _i2c->apb_bit); // Reset the peripheral *i2c_get_CR1(_i2c) = I2C_CR1__SWRST; // Clear all registers *i2c_get_CR1(_i2c) = 0; *i2c_get_CR2(_i2c) = 0; *i2c_get_CCR(_i2c) = 0; *i2c_get_TRISE(_i2c) = 0; *i2c_get_SR1(_i2c) = 0; *i2c_get_SR2(_i2c) = 0; /* Step 1: program the peripheral input clock in CR2 */ // Compute clock frequency pclk = rcc_sysclk_get_clock_frequency( _i2c->apb_bus == 1 ? RCC_SYSCLK_CLOCK_PCLK1 : RCC_SYSCLK_CLOCK_PCLK2); freq = pclk / 1000000; *i2c_get_CR2(_i2c) = freq & I2C_CR2__FREQ_MASK; /* Step 2: configure the clock control registers */ if (mode == I2C_CLOCK_MODE_FAST) { // Set Fast Speed mode and bitrate: 400kHz with duty t_low/t_high = 16/9 *i2c_get_CCR(_i2c) = I2C_CCR__FS | I2C_CCR__DUTY | (freq / 10 * 25); } else { // Set Standard Speed mode and bitrate: 100kHz *i2c_get_CCR(_i2c) = (freq * 5) & I2C_CCR__CCR_MASK; } /* Step 3: configure the rise time registers */ if (mode == I2C_CLOCK_MODE_FAST) { // Configure maximum rise time *i2c_get_TRISE(_i2c) = (freq * 3 / 10 + 1) & I2C_TRISE__TRISE_MASK; } else { // Configure maximum rise time *i2c_get_TRISE(_i2c) = (freq + 1) & I2C_TRISE__TRISE_MASK; } /* Step 4: program the CR1 register to enable the peripheral */ // Set I2C mode, enable ACK and enable I2C *i2c_get_CR1(_i2c) = I2C_CR1__ACK | I2C_CR1__PE; // Enable EV and BUF interrupt *i2c_get_CR2(_i2c) |= I2C_CR2__ITEVTEN | I2C_CR2__ITBUFEN | I2C_CR2__ITERREN; // Initialize I2C state state = I2C_IDLE; // Enable I2C EV and ERR interrupt line in the NVIC nvic_enable_interrupt_line(_i2c->irq_line_ev); nvic_enable_interrupt_line(_i2c->irq_line_er); }
void i2c_handle_ev_interrupt(_i2c_t *_i2c) { uint32_t sr1 = *i2c_get_SR1(_i2c); uint32_t sr2 = 0; (void)sr2; // clear defined but not used warning warning if (sr1 & I2C_SR1__SB) { // Start bit has been issued. // The flag is cleared after reading SR1 (already done at the // beginning of the function) and writing DR (done right now) // If there there is nothing to send, set the lower bit // of address to 1 as we are in receiving mode if (len_send == 0) { // Send address in order to receive data *i2c_get_DR(_i2c) = address | 1; // In the case of a 2-byte reception we need to set POS bit if (len_recv == 2) { *i2c_get_CR1(_i2c) |= I2C_CR1__POS; } } else { // Send address in order to send data *i2c_get_DR(_i2c) = address; } *i2c_get_CR1(_i2c) |= I2C_CR1__ACK; state = I2C_SENDING_ADDRESS; } if (sr1 & I2C_SR1__ADDR) { // Address byte has been sent. // The flag is cleared after reading both SR1 and SR2 // Send the first byte if any if (len_send > 0) { // Clear the flag by reading SR2. This must be done before sending data sr2 = *i2c_get_SR2(_i2c); // Send data *i2c_get_DR(_i2c) = buf_send[cpt_send]; cpt_send++; if (cpt_send == len_send) { // The only byte to send has already been sent so we need to issue // a STOP condition if there is nothing to receive or // a RESTART condition otherwise if (len_recv == 0) { // There is nothing to receive *i2c_get_CR1(_i2c) |= I2C_CR1__STOP; // The transfer is complete state = I2C_IDLE; } else { // We need to read something *i2c_get_CR1(_i2c) |= I2C_CR1__START; // Wait for the new start condition to be issued state = I2C_SENDING_RESTART; } // Indicate that there is nothing else to send len_send = 0; cpt_send = 0; } else { // There is something else to send // Wait for the first byte to be sent state = I2C_SENDING_DATA; } } else { switch (len_recv) { case 1: // In this case we need to clear ACK bit right now *i2c_get_CR1(_i2c) &= ~I2C_CR1__ACK; // Clear the flag by reading SR2 sr2 = *i2c_get_SR2(_i2c); // We also need to program the STOP condition *i2c_get_CR1(_i2c) |= I2C_CR1__STOP; break; case 2: // Clear the flag by reading SR2 sr2 = *i2c_get_SR2(_i2c); // Clear ACK bit *i2c_get_CR1(_i2c) &= ~I2C_CR1__ACK; break; default: // In the default case we do not need to do anything // except clearing the flag by reading SR2 sr2 = *i2c_get_SR2(_i2c); } // Wait for the first byte to read state = I2C_RECEIVING_DATA; } } if (sr1 & I2C_SR1__BTF) { // This is the only case where we need BTF flag // We have waited until the last two bytes to read are available if ((state == I2C_RECEIVING_DATA) && (len_recv == 2)) { // Program a STOP condition before reading the second last data *i2c_get_CR1(_i2c) |= I2C_CR1__STOP; // Read Data[N-1] buf_recv[cpt_recv] = *i2c_get_DR(_i2c); cpt_recv++; // Read Data[N] buf_recv[cpt_recv] = *i2c_get_DR(_i2c); cpt_recv++; // Unset POS bit in order not disturb next transfers *i2c_get_CR1(_i2c) &= ~I2C_CR1__POS; // Goto idle state state = I2C_IDLE; } } if (sr1 & I2C_SR1__ADD10) { // This should not happen as we do not handle 10-bits addresses log_error("ADD10 interrupt!"); } if (sr1 & I2C_SR1__STOPF) { // This should not happen as we are in master mode log_error("STOPF interrupt!"); } // The following two cases should not happen as ITBUFEN is not set if (sr1 & I2C_SR1__RXNE) { if (state == I2C_RECEIVING_DATA) { // We are receiving data if (len_recv == 1) { // This is the only byte to read buf_recv[cpt_recv] = *i2c_get_DR(_i2c); // Indicate that there is nothing else to receive len_recv = 0; cpt_recv = 0; // The transfer is complete state = I2C_IDLE; } else if (len_recv == 2) { // Do not read yet, wait for BTF to be issued // Stay in the I2C_RECEIVING_DATA state } else { // Read data buf_recv[cpt_recv] = *i2c_get_DR(_i2c); cpt_recv++; if (len_recv - cpt_recv == 1) { // We need to clear ACK bit to be sure NACK is sent when the last data is received *i2c_get_CR1(_i2c) &= ~I2C_CR1__ACK; // Program a STOP condition before reading the second last data *i2c_get_CR1(_i2c) |= I2C_CR1__STOP; } if (len_recv == cpt_recv) { state = I2C_IDLE; } // Else stay in the I2C_RECEIVING_DATA state } // In other cases there is nothing to do } else { // This flag should not be set when we are not in receiving mode (void)(*i2c_get_DR(_i2c)); } } if (sr1 & I2C_SR1__TXE) { // The flag is cleared after reading SR1 (already done) and reading or writing DR if (state == I2C_SENDING_DATA) { if (len_send == cpt_send) { // The last byte has been sent so we need to issue // a STOP condition if there is nothing to receive or // a RESTART condition otherwise if (len_recv == 0) { // There is nothing to receive *i2c_get_CR1(_i2c) |= I2C_CR1__STOP; // The transfer is complete state = I2C_IDLE; } else { // We need to read something *i2c_get_CR1(_i2c) |= I2C_CR1__START; state = I2C_SENDING_RESTART; } // Indicate that there is nothing else to send len_send = 0; cpt_send = 0; } else { // Send the data *i2c_get_DR(_i2c) = buf_send[cpt_send]; cpt_send++; // Stay in the I2C_SENDING_DATA state } } // If we are not sending data, do nothing } }