STM32F4 I2C: System halt after double i2cstart
Posted: Sat May 06, 2017 5:05 pm
Hello there,
First time i'm posting here and also having the first steps on ChibiOs world.
I am using RT and HAL of the release 16.1.8 and as a target the STM32F4DISCOVERY.
The stm32f4 halts on calling i2cMasterTransmitTimeout() once i2cStart() is called a second time.
Calling the i2c_lld_start() low level function for the second time cleans the DMA channel selection and priority configurations.
Since the i2c driver isn't in the STOP condition it will not reinitialize the I2c and DMA clocks.
However, DMA channel selection and priorities are also configured inside this block.
As a result, DMA channel selection and priorities are never configured again and ends up on DMA not working and therefore a timeout occurs while using the i2cMasterTransmitTimeout(). The system is halted because the second time i2cMasterTransmitTimeout() is called, the i2c driver is in I2C_LOCKED state and an assert with I2C_READY is made.
Pulling out the DMA_CR_CHSEL and DMA_CR_PL configurations of the block resolves this problem.
Keep up the ChibiOS project, cheers!
First time i'm posting here and also having the first steps on ChibiOs world.
I am using RT and HAL of the release 16.1.8 and as a target the STM32F4DISCOVERY.
The stm32f4 halts on calling i2cMasterTransmitTimeout() once i2cStart() is called a second time.
Calling the i2c_lld_start() low level function for the second time cleans the DMA channel selection and priority configurations.
Code: Select all
i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE |
STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE |
STM32_DMA_CR_DIR_M2P;
i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE |
STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE |
STM32_DMA_CR_DIR_P2M;Since the i2c driver isn't in the STOP condition it will not reinitialize the I2c and DMA clocks.
Code: Select all
/* If in stopped state then enables the I2C and DMA clocks.*/
if (i2cp->state == I2C_STOP) {However, DMA channel selection and priorities are also configured inside this block.
Code: Select all
i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) |
STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) |
STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);As a result, DMA channel selection and priorities are never configured again and ends up on DMA not working and therefore a timeout occurs while using the i2cMasterTransmitTimeout(). The system is halted because the second time i2cMasterTransmitTimeout() is called, the i2c driver is in I2C_LOCKED state and an assert with I2C_READY is made.
Pulling out the DMA_CR_CHSEL and DMA_CR_PL configurations of the block resolves this problem.
Code: Select all
#if STM32_I2C_USE_I2C1
if (&I2CD1 == i2cp) {
/* If in stopped state then enables the I2C and DMA clocks.*/
if (i2cp->state == I2C_STOP) {
bool b;
rccResetI2C1();
b = dmaStreamAllocate(i2cp->dmarx,
STM32_I2C_I2C1_IRQ_PRIORITY,
(stm32_dmaisr_t)i2c_lld_serve_rx_end_irq,
(void *)i2cp);
osalDbgAssert(!b, "stream already allocated");
b = dmaStreamAllocate(i2cp->dmatx,
STM32_I2C_I2C1_IRQ_PRIORITY,
(stm32_dmaisr_t)i2c_lld_serve_tx_end_irq,
(void *)i2cp);
osalDbgAssert(!b, "stream already allocated");
rccEnableI2C1(FALSE);
nvicEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY);
nvicEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY);
}
i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) |
STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) |
STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
}
#endif /* STM32_I2C_USE_I2C1 */Keep up the ChibiOS project, cheers!