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_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 } }