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!