stm32/i2cslave: Fix ordering of event callbacks in slave IRQ handler.

It's possible (at least on F4 MCU's) to have RXNE and STOPF set at the same
time during a call to the slave IRQ handler.  In such cases RXNE should be
handled before STOPF so that all bytes are processed before
i2c_slave_process_rx_end() is called.
This commit is contained in:
Damien George 2018-06-15 14:15:31 +10:00
parent bc5e8a2cb6
commit 7be4a23c0c
1 changed files with 12 additions and 12 deletions

View File

@ -44,6 +44,12 @@ void i2c_slave_ev_irq_handler(i2c_slave_t *i2c) {
uint32_t sr2 = i2c->SR2; uint32_t sr2 = i2c->SR2;
i2c_slave_process_addr_match((sr2 >> I2C_SR2_TRA_Pos) & 1); i2c_slave_process_addr_match((sr2 >> I2C_SR2_TRA_Pos) & 1);
} }
if (sr1 & I2C_SR1_TXE) {
i2c->DR = i2c_slave_process_tx_byte();
}
if (sr1 & I2C_SR1_RXNE) {
i2c_slave_process_rx_byte(i2c->DR);
}
if (sr1 & I2C_SR1_STOPF) { if (sr1 & I2C_SR1_STOPF) {
// STOPF only set at end of RX mode (in TX mode AF is set on NACK) // STOPF only set at end of RX mode (in TX mode AF is set on NACK)
// Read of SR1, write CR1 needed to clear STOPF bit // Read of SR1, write CR1 needed to clear STOPF bit
@ -52,12 +58,6 @@ void i2c_slave_ev_irq_handler(i2c_slave_t *i2c) {
i2c_slave_process_rx_end(); i2c_slave_process_rx_end();
i2c->CR1 |= I2C_CR1_ACK; i2c->CR1 |= I2C_CR1_ACK;
} }
if (sr1 & I2C_SR1_TXE) {
i2c->DR = i2c_slave_process_tx_byte();
}
if (sr1 & I2C_SR1_RXNE) {
i2c_slave_process_rx_byte(i2c->DR);
}
} }
#elif defined(STM32F7) #elif defined(STM32F7)
@ -79,6 +79,12 @@ void i2c_slave_ev_irq_handler(i2c_slave_t *i2c) {
i2c->ICR = I2C_ICR_ADDRCF; i2c->ICR = I2C_ICR_ADDRCF;
i2c_slave_process_addr_match(0); i2c_slave_process_addr_match(0);
} }
if (isr & I2C_ISR_TXIS) {
i2c->TXDR = i2c_slave_process_tx_byte();
}
if (isr & I2C_ISR_RXNE) {
i2c_slave_process_rx_byte(i2c->RXDR);
}
if (isr & I2C_ISR_STOPF) { if (isr & I2C_ISR_STOPF) {
// STOPF only set for STOP condition, not a repeated START // STOPF only set for STOP condition, not a repeated START
i2c->ICR = I2C_ICR_STOPCF; i2c->ICR = I2C_ICR_STOPCF;
@ -90,12 +96,6 @@ void i2c_slave_ev_irq_handler(i2c_slave_t *i2c) {
} }
i2c->OAR1 |= I2C_OAR1_OA1EN; i2c->OAR1 |= I2C_OAR1_OA1EN;
} }
if (isr & I2C_ISR_TXIS) {
i2c->TXDR = i2c_slave_process_tx_byte();
}
if (isr & I2C_ISR_RXNE) {
i2c_slave_process_rx_byte(i2c->RXDR);
}
} }
#endif #endif