diff options
| -rw-r--r-- | ports/stm32/i2cslave.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/ports/stm32/i2cslave.c b/ports/stm32/i2cslave.c index e60edf53b..f3bb232f7 100644 --- a/ports/stm32/i2cslave.c +++ b/ports/stm32/i2cslave.c @@ -28,8 +28,14 @@ #if defined(STM32F4) +// The hardware triggers the following IRQs for the given scenarios: +// - scan (0-length write): ADDR STOPF +// - write of n bytes: ADDR RXNE*n STOPF +// - read of n bytes: ADDR TXE*(n+1) AF +// - write of n bytes then read of m bytes: ADDR RXNE*n ADDR TXE*(m+1) AF + void i2c_slave_init_helper(i2c_slave_t *i2c, int addr) { - i2c->CR2 = I2C_CR2_ITBUFEN | I2C_CR2_ITEVTEN | 4 << I2C_CR2_FREQ_Pos; + i2c->CR2 = I2C_CR2_ITBUFEN | I2C_CR2_ITEVTEN | 4 << I2C_CR2_FREQ_Pos | I2C_CR2_ITERREN; i2c->OAR1 = 1 << 14 | addr << 1; i2c->OAR2 = 0; i2c->CR1 = I2C_CR1_ACK | I2C_CR1_PE; @@ -37,6 +43,14 @@ void i2c_slave_init_helper(i2c_slave_t *i2c, int addr) { void i2c_slave_irq_handler(i2c_slave_t *i2c) { uint32_t sr1 = i2c->SR1; + + // Clear all error flags. + i2c->SR1 &= ~(I2C_SR1_SMBALERT | I2C_SR1_TIMEOUT | I2C_SR1_PECERR | I2C_SR1_OVR | I2C_SR1_AF | I2C_SR1_ARLO | I2C_SR1_BERR); + + if (sr1 & I2C_SR1_AF) { + // A NACK in TX mode, which is a stop condition. + i2c_slave_process_tx_end(i2c); + } if (sr1 & I2C_SR1_ADDR) { // Address matched // Read of SR1, SR2 needed to clear ADDR bit |
