diff --git a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c index 48a5c4497e..2b09016e31 100644 --- a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c +++ b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c @@ -34,6 +34,7 @@ /* Driver local definitions. */ /*===========================================================================*/ +#if STM32_I2C_USE_DMA == TRUE #define I2C1_RX_DMA_CHANNEL \ STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \ STM32_I2C1_RX_DMA_CHN) @@ -57,6 +58,23 @@ #define I2C3_TX_DMA_CHANNEL \ STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \ STM32_I2C3_TX_DMA_CHN) +#endif /* STM32_I2C_USE_DMA == TRUE */ + +#if STM32_I2C_USE_DMA == TRUE +#define i2c_lld_get_rxbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmarx) +#define i2c_lld_get_txbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmatx) +#else +#define i2c_lld_get_rxbytes(i2cp) (i2cp)->rxbytes +#define i2c_lld_get_txbytes(i2cp) (i2cp)->txbytes +#define i2c_lld_write_byte(i2cp) \ + i2cp->i2c->DR = *i2cp->txptr; \ + i2cp->txptr++; \ + i2cp->txbytes-- +#define i2c_lld_read_byte(i2cp) \ + *i2cp->rxptr = (uint8_t)i2cp->i2c->DR; \ + i2cp->rxptr++; \ + i2cp->rxbytes-- +#endif /*===========================================================================*/ /* Driver constants. */ @@ -79,6 +97,21 @@ ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \ I2C_SR1_BTF | I2C_SR1_TXE)) +#define I2C_EV8_MASTER_BYTE_TRANSMIT \ + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \ + I2C_SR1_TXE)) + +#define I2C_EV8_1_MASTER_BYTE_TRANSMIT \ + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16))) + +#define I2C_EV7_MASTER_BYTE_RECEIVE \ + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | \ + I2C_SR1_RXNE)) + +#define I2C_EV7_1_MASTER_LAST_BYTES_RECEIVED \ + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | \ + I2C_SR1_BTF | I2C_SR1_RXNE)) + #define I2C_EV9_MASTER_ADD10 \ ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | I2C_SR1_ADD10)) @@ -135,9 +168,38 @@ static void i2c_lld_abort_operation(I2CDriver *i2cp) { dp->CR2 = 0; dp->SR1 = 0; +#if STM32_I2C_USE_DMA == TRUE /* Stops the associated DMA streams.*/ dmaStreamDisable(i2cp->dmatx); dmaStreamDisable(i2cp->dmarx); +#else + i2cp->txbytes = 0; + i2cp->rxbytes = 0; +#endif +} + +/** + * @brief Stops an I2C transaction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_stop_operation(I2CDriver *i2cp, uint32_t rxbytes) { + I2C_TypeDef *dp = i2cp->i2c; + + dp->CR2 &= ~(I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN | I2C_CR2_ITERREN); + dp->CR1 |= I2C_CR1_STOP; /* stop will clear TxE / RxNE */ +#if STM32_I2C_USE_DMA == FALSE + while (rxbytes-- > 0) { /* read pending bytes if necessary */ + i2c_lld_read_byte(i2cp); + } + i2cp->txbytes = 0; + i2cp->rxbytes = 0; +#else + (void)rxbytes; +#endif + _i2c_wakeup_isr(i2cp); } /** @@ -320,15 +382,18 @@ static void i2c_lld_reset(I2CDriver *i2cp) { static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { I2C_TypeDef *dp = i2cp->i2c; uint32_t regSR2 = dp->SR2; - uint32_t event = dp->SR1; + uint32_t regSR1 = dp->SR1; + uint32_t event = I2C_EV_MASK & (regSR2 << 16 | regSR1); #ifdef STM32_I2C_ISR_LIMIT if (i2cp->isr_count++ > i2cp->isr_limit) { i2cp->errors |= I2C_ISR_LIMIT; +#if STM32_I2C_USE_DMA == TRUE if (i2cp->dmatx) dmaStreamDisable(i2cp->dmatx); if (i2cp->dmarx) dmaStreamDisable(i2cp->dmarx); +#endif dp->CR1 |= I2C_CR1_SWRST; dp->CR1 &= ~I2C_CR1_PE; i2c_lld_reset(i2cp); @@ -349,7 +414,7 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { /* Interrupts are disabled just before dmaStreamEnable() because there is no need of interrupts until next transaction begin. All the work is done by the DMA.*/ - switch (I2C_EV_MASK & (event | (regSR2 << 16))) { + switch (event) { case I2C_EV5_MASTER_MODE_SELECT: case I2C_EV5_MASTER_MODE_SELECT_NO_BUSY: if ((i2cp->addr >> 8) > 0) { @@ -364,49 +429,124 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { dp->DR = (0xFF & (i2cp->addr >> 1)); break; case I2C_EV6_MASTER_REC_MODE_SELECTED: +#if STM32_I2C_USE_DMA == TRUE dp->CR2 &= ~I2C_CR2_ITEVTEN; dmaStreamEnable(i2cp->dmarx); - dp->CR2 |= I2C_CR2_LAST; /* Needed in receiver mode. */ - if (dmaStreamGetTransactionSize(i2cp->dmarx) < 2) + dp->CR2 |= I2C_CR2_LAST; /* Needed in receiver mode for NACK generation. */ +#endif + switch (i2c_lld_get_rxbytes(i2cp)) { + case 2: /* special treatment for 1-2-byte reception */ + dp->CR1 |= I2C_CR1_POS; + dp->CR1 &= ~I2C_CR1_ACK; + break; + case 1: dp->CR1 &= ~I2C_CR1_ACK; + dp->CR2 |= I2C_CR2_ITBUFEN; /* start per-byte interrupt generation */ + break; + default: + dp->CR2 |= I2C_CR2_ITBUFEN; /* start per-byte interrupt generation */ + break; + } break; case I2C_EV6_MASTER_TRA_MODE_SELECTED: +#if STM32_I2C_USE_DMA == TRUE dp->CR2 &= ~I2C_CR2_ITEVTEN; dmaStreamEnable(i2cp->dmatx); +#else + dp->CR2 |= I2C_CR2_ITBUFEN; /* start per-byte interrupt generation */ +#endif + break; + case I2C_EV8_MASTER_BYTE_TRANSMIT: +#if STM32_I2C_USE_DMA == FALSE + if (i2cp->txbytes > 0U) { + i2c_lld_write_byte(i2cp); + } else { /* ref: Stop condition should be programmed during EV8_2 event, when either TxE or BTF is set */ + dp->CR2 &= ~I2C_CR2_ITBUFEN; /* stop receiving any more TxE interrupts */ + if (i2c_lld_get_rxbytes(i2cp) > 0U) { + i2cp->addr |= 0x01; + /* start will clear TxE and generate ReStart at end of current byte transfer */ + dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK; + return; + } + i2c_lld_stop_operation(i2cp, 0); + } break; case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: + if (i2cp->txbytes > 0U) { + i2c_lld_write_byte(i2cp); + return; + } +#else + case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: +#endif /* Catches BTF event after the end of transmission.*/ (void)dp->DR; /* Clear BTF.*/ - if (dmaStreamGetTransactionSize(i2cp->dmarx) > 0) { + + if (i2c_lld_get_rxbytes(i2cp) > 0U) { /* Starts "read after write" operation, LSB = 1 -> receive.*/ i2cp->addr |= 0x01; dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK; return; } - dp->CR2 &= ~I2C_CR2_ITEVTEN; - dp->CR1 |= I2C_CR1_STOP; - _i2c_wakeup_isr(i2cp); + i2c_lld_stop_operation(i2cp, 0); break; +#if STM32_I2C_USE_DMA == FALSE + case I2C_EV7_MASTER_BYTE_RECEIVE: { + uint32_t rxbytes = i2c_lld_get_rxbytes(i2cp); + if (rxbytes > 3U) { + i2c_lld_read_byte(i2cp); + if (i2c_lld_get_rxbytes(i2cp) == 3U) { + dp->CR2 &= ~I2C_CR2_ITBUFEN; /* stop receiving any more RxNE interrupts */ + } + } else if (i2c_lld_get_rxbytes(i2cp) == 3U) { + dp->CR2 &= ~I2C_CR2_ITBUFEN; /* stop receiving any more RxNE interrupts */ + } else if (rxbytes <= 1) { + i2c_lld_stop_operation(i2cp, rxbytes); + } + break; + } + case I2C_EV7_1_MASTER_LAST_BYTES_RECEIVED: { + uint32_t rxbytes = i2c_lld_get_rxbytes(i2cp); + switch (rxbytes) { + case 4: + dp->CR2 &= ~I2C_CR2_ITBUFEN; + i2c_lld_read_byte(i2cp); + break; + case 3: + dp->CR2 &= ~I2C_CR2_ITBUFEN; + dp->CR1 &= ~I2C_CR1_ACK; /* generate NACK on next read */ + i2c_lld_read_byte(i2cp); + break; + case 2: + case 1: + i2c_lld_stop_operation(i2cp, rxbytes); + break; + default: + i2c_lld_read_byte(i2cp); + } + break; + } +#endif case I2C_EV5_MASTER_MODE_INVALID: i2c_lld_abort_operation(i2cp); - dp->CR2 &= ~I2C_CR2_ITEVTEN; break; default: - break; + break; } /* Clear ADDR flag. */ - if (event & (I2C_SR1_ADDR | I2C_SR1_ADD10)) + if (regSR1 & (I2C_SR1_ADDR | I2C_SR1_ADD10)) (void)dp->SR2; /* BERR flag doesn�t happen anymore in event handling */ #if 0 /* Errata 2.4.6 for STM32F40x, Spurious Bus Error detection in Master mode.*/ - if (event & I2C_SR1_BERR) { + if (regSR1 & I2C_SR1_BERR) { dp->SR1 &= ~I2C_SR1_BERR; } #endif } +#if STM32_I2C_USE_DMA == TRUE /** * @brief DMA RX end IRQ handler. * @@ -460,6 +600,7 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { of R/W transaction itself.*/ dp->CR2 |= I2C_CR2_ITEVTEN; } +#endif /** * @brief I2C error handler. @@ -471,11 +612,18 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { */ static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) { +#if STM32_I2C_USE_DMA == TRUE /* Clears interrupt flags just to be safe.*/ if (i2cp->dmatx) dmaStreamDisable(i2cp->dmatx); if (i2cp->dmarx) dmaStreamDisable(i2cp->dmarx); +#else + /* Clear interrupt flags. DMA-path will have already cleared I2C_CR2_ITEVTEN */ + i2cp->i2c->CR2 &= ~(I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN); + i2cp->txbytes = 0; + i2cp->rxbytes = 0; +#endif #ifdef STM32_I2C_ISR_LIMIT if (i2cp->isr_count++ > i2cp->isr_limit) { @@ -648,24 +796,30 @@ void i2c_lld_init(void) { i2cObjectInit(&I2CD1); I2CD1.thread = NULL; I2CD1.i2c = I2C1; +#if STM32_I2C_USE_DMA == TRUE I2CD1.dmarx = NULL; I2CD1.dmatx = NULL; +#endif #endif /* STM32_I2C_USE_I2C1 */ #if STM32_I2C_USE_I2C2 i2cObjectInit(&I2CD2); I2CD2.thread = NULL; I2CD2.i2c = I2C2; +#if STM32_I2C_USE_DMA == TRUE I2CD2.dmarx = NULL; I2CD2.dmatx = NULL; +#endif #endif /* STM32_I2C_USE_I2C2 */ #if STM32_I2C_USE_I2C3 i2cObjectInit(&I2CD3); I2CD3.thread = NULL; I2CD3.i2c = I2C3; +#if STM32_I2C_USE_DMA == TRUE I2CD3.dmarx = NULL; I2CD3.dmatx = NULL; +#endif #endif /* STM32_I2C_USE_I2C3 */ } @@ -682,6 +836,7 @@ void i2c_lld_start(I2CDriver *i2cp) { /* If in stopped state then enables the I2C and DMA clocks.*/ if (i2cp->state == I2C_STOP) { +#if STM32_I2C_USE_DMA == TRUE 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 | @@ -690,11 +845,12 @@ void i2c_lld_start(I2CDriver *i2cp) { STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | STM32_DMA_CR_DIR_P2M; +#endif #if STM32_I2C_USE_I2C1 if (&I2CD1 == i2cp) { rccResetI2C1(); - +#if STM32_I2C_USE_DMA == TRUE i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C1_RX_DMA_STREAM, STM32_I2C_I2C1_IRQ_PRIORITY, (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, @@ -706,21 +862,21 @@ void i2c_lld_start(I2CDriver *i2cp) { (void *)i2cp); osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); - rccEnableI2C1(true); - 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_DMA == TRUE */ + rccEnableI2C1(true); + nvicEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + nvicEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); } #endif /* STM32_I2C_USE_I2C1 */ #if STM32_I2C_USE_I2C2 if (&I2CD2 == i2cp) { rccResetI2C2(); - +#if STM32_I2C_USE_DMA == TRUE i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C2_RX_DMA_STREAM, STM32_I2C_I2C2_IRQ_PRIORITY, (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, @@ -732,21 +888,21 @@ void i2c_lld_start(I2CDriver *i2cp) { (void *)i2cp); osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); - rccEnableI2C2(true); - nvicEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); - nvicEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); +#endif /* STM32_I2C_USE_DMA == TRUE */ + rccEnableI2C2(true); + nvicEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); + nvicEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); } #endif /* STM32_I2C_USE_I2C2 */ #if STM32_I2C_USE_I2C3 if (&I2CD3 == i2cp) { rccResetI2C3(); - +#if STM32_I2C_USE_DMA == TRUE i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C3_RX_DMA_STREAM, STM32_I2C_I2C3_IRQ_PRIORITY, (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, @@ -758,26 +914,33 @@ void i2c_lld_start(I2CDriver *i2cp) { (void *)i2cp); osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); - rccEnableI2C3(true); - nvicEnableVector(I2C3_EV_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); - nvicEnableVector(I2C3_ER_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) | STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) | STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); +#endif /* STM32_I2C_USE_DMA == TRUE */ + rccEnableI2C3(true); + nvicEnableVector(I2C3_EV_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); + nvicEnableVector(I2C3_ER_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); } #endif /* STM32_I2C_USE_I2C3 */ } +#if STM32_I2C_USE_DMA == TRUE /* I2C registers pointed by the DMA.*/ dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR); dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR); +#else + i2cp->txbytes = 0; + i2cp->rxbytes = 0; +#endif /* Reset i2c peripheral.*/ dp->CR1 = I2C_CR1_SWRST; dp->CR1 = 0; - dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN; +#if STM32_I2C_USE_DMA == TRUE + dp->CR2 = I2C_CR2_DMAEN; +#endif /* Setup I2C parameters.*/ i2c_lld_set_clock(i2cp); @@ -804,10 +967,12 @@ void i2c_lld_stop(I2CDriver *i2cp) { /* I2C disable.*/ i2c_lld_abort_operation(i2cp); +#if STM32_I2C_USE_DMA == TRUE dmaStreamFreeI(i2cp->dmatx); dmaStreamFreeI(i2cp->dmarx); i2cp->dmatx = NULL; i2cp->dmarx = NULL; +#endif #if STM32_I2C_USE_I2C1 if (&I2CD1 == i2cp) { @@ -847,11 +1012,16 @@ void i2c_lld_soft_stop(I2CDriver *i2cp) { /* If not in stopped state then disables the I2C clock.*/ if (i2cp->state != I2C_STOP) { +#if STM32_I2C_USE_DMA == TRUE /* I2C disable.*/ dmaStreamFreeI(i2cp->dmatx); dmaStreamFreeI(i2cp->dmarx); i2cp->dmatx = NULL; i2cp->dmarx = NULL; +#else + i2cp->txbytes = 0; + i2cp->rxbytes = 0; +#endif #if STM32_I2C_USE_I2C1 if (&I2CD1 == i2cp) { @@ -931,22 +1101,29 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, /* Releases the lock from high level driver.*/ osalSysUnlock(); +#if STM32_I2C_USE_DMA == TRUE /* RX DMA setup.*/ dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); dmaStreamSetMemory0(i2cp->dmarx, rxbuf); dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); +#else + i2cp->rxptr = rxbuf; + i2cp->rxbytes = rxbytes; +#endif osalSysLock(); i2cp->in_transaction = true; /* Starts the operation.*/ - dp->CR2 |= I2C_CR2_ITEVTEN; + dp->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITERREN; dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK; /* Waits for the operation completion or a timeout.*/ msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); +#if STM32_I2C_USE_DMA == TRUE dmaStreamDisable(i2cp->dmarx); +#endif i2cp->in_transaction = false; @@ -1010,6 +1187,7 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, /* Releases the lock from high level driver.*/ osalSysUnlock(); +#if STM32_I2C_USE_DMA == TRUE /* TX DMA setup.*/ dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); dmaStreamSetMemory0(i2cp->dmatx, txbuf); @@ -1019,19 +1197,28 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); dmaStreamSetMemory0(i2cp->dmarx, rxbuf); dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); +#else + i2cp->txptr = txbuf; + i2cp->txbytes = txbytes; + i2cp->rxptr = rxbuf; + i2cp->rxbytes = rxbytes; +#endif osalSysLock(); i2cp->in_transaction = true; /* Starts the operation.*/ - dp->CR2 |= I2C_CR2_ITEVTEN; + dp->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITERREN; dp->CR1 |= I2C_CR1_START; /* Waits for the operation completion or a timeout.*/ msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); + +#if STM32_I2C_USE_DMA == TRUE dmaStreamDisable(i2cp->dmatx); dmaStreamDisable(i2cp->dmarx); +#endif i2cp->in_transaction = false; diff --git a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h index 6575a6576d..aa2d223441 100644 --- a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h +++ b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h @@ -104,6 +104,13 @@ #endif /** + * @brief DMA use switch. + */ +#if !defined(STM32_I2C_USE_DMA) || defined(__DOXYGEN__) +#define STM32_I2C_USE_DMA TRUE +#endif + +/** * @brief I2C1 DMA priority (0..3|lowest..highest). * @note The priority level is used for both the TX and RX DMA streams but * because of the streams ordering the RX stream has always priority @@ -253,6 +260,7 @@ #error "Invalid IRQ priority assigned to I2C3" #endif +#if STM32_I2C_USE_DMA == TRUE #if STM32_I2C_USE_I2C1 && \ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY) #error "Invalid DMA priority assigned to I2C1" @@ -323,6 +331,7 @@ #if !defined(STM32_DMA_REQUIRED) #define STM32_DMA_REQUIRED #endif +#endif /* STM32_I2C_USE_DMA == TRUE */ /* Check clock range. */ #if defined(STM32F4XX) @@ -445,6 +454,7 @@ struct hal_i2c_driver { * @brief Current slave address without R/W bit. */ i2caddr_t addr; +#if (STM32_I2C_USE_DMA == TRUE) || defined(__DOXYGEN__) /** * @brief RX DMA mode bit mask. */ @@ -461,6 +471,24 @@ struct hal_i2c_driver { * @brief Transmit DMA channel. */ const stm32_dma_stream_t *dmatx; +#else /* STM32_I2C_USE_DMA == FALSE */ + /** + * @brief Pointer to the next TX buffer location. + */ + const uint8_t *txptr; + /** + * @brief Number of bytes in TX phase. + */ + size_t txbytes; + /** + * @brief Pointer to the next RX buffer location. + */ + uint8_t *rxptr; + /** + * @brief Number of bytes in RX phase. + */ + size_t rxbytes; +#endif /* STM32_I2C_USE_DMA == FALSE */ /** * @brief Pointer to the I2Cx registers block. */