void i2c_t::Resume() { Error = false; // ==== GPIOs ==== PinSetupAlterFunc(IPGpio, ISclPin, omOpenDrain, pudNone, AF4); PinSetupAlterFunc(IPGpio, ISdaPin, omOpenDrain, pudNone, AF4); // ==== Clock and reset ==== if (ii2c == I2C1) { rccEnableI2C1(FALSE); rccResetI2C1(); } else if (ii2c == I2C2) { rccEnableI2C2(FALSE); rccResetI2C2(); } else if (ii2c == I2C3) { rccEnableI2C3(FALSE); rccResetI2C3(); } // Minimum clock is 2 MHz uint32_t ClkMhz = Clk.APB1FreqHz / 1000000; uint16_t tmpreg = ii2c->CR2; tmpreg &= (uint16_t)~I2C_CR2_FREQ; if(ClkMhz < 2) ClkMhz = 2; if(ClkMhz > 30) ClkMhz = 30; tmpreg |= ClkMhz; ii2c->CR2 = tmpreg; ii2c->CR1 &= (uint16_t)~I2C_CR1_PE; // Disable i2c to setup TRise & CCR ii2c->TRISE = (uint16_t)(((ClkMhz * 300) / 1000) + 1); // 16/9 tmpreg = (uint16_t)(Clk.APB1FreqHz / (IBitrateHz * 25)); if(tmpreg == 0) tmpreg = 1; // minimum allowed value tmpreg |= I2C_CCR_FS | I2C_CCR_DUTY; ii2c->CCR = tmpreg; ii2c->CR1 |= I2C_CR1_PE; // Enable i2c back // ==== DMA ==== ii2c->CR2 |= I2C_CR2_DMAEN; }
void i2c_t::Init() { // GPIO PinSetupAlterFunc(PParams->PGpio, PParams->SclPin, omOpenDrain, pudNone, PParams->PinAF); PinSetupAlterFunc(PParams->PGpio, PParams->SdaPin, omOpenDrain, pudNone, PParams->PinAF); #if I2C_USE_SEMAPHORE chBSemObjectInit(&BSemaphore, NOT_TAKEN); #endif // I2C I2C_TypeDef *pi2c = PParams->pi2c; // To make things shorter pi2c->CR1 = 0; // Clear PE bit => disable and reset i2c if(pi2c == I2C1) { rccResetI2C1(); rccEnableI2C1(FALSE); } else if(pi2c == I2C2) { rccResetI2C2(); rccEnableI2C2(FALSE); } else if(pi2c == I2C3) { rccResetI2C3(); rccEnableI2C3(FALSE); } pi2c->TIMINGR = PParams->Timing; // setup timings // Analog filter enabled, digital disabled, clk stretch enabled, DMA enabled pi2c->CR1 = I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN; // DMA dmaStreamAllocate(STM32_DMA1_STREAM2, IRQ_PRIO_MEDIUM, nullptr, nullptr); dmaStreamAllocate(STM32_DMA1_STREAM3, IRQ_PRIO_MEDIUM, nullptr, nullptr); dmaStreamSetPeripheral(PParams->PDmaRx, &pi2c->RXDR); dmaStreamSetPeripheral(STM32_DMA1_STREAM2, &pi2c->TXDR); // IRQ nvicEnableVector(72, IRQ_PRIO_MEDIUM); nvicEnableVector(73, IRQ_PRIO_MEDIUM); }
/** * @brief Configures and activates the I2C peripheral. * * @param[in] i2cp pointer to the @p I2CDriver object * * @notapi */ void i2c_lld_start(I2CDriver *i2cp) { I2C_TypeDef *dp = i2cp->i2c; i2cp->dmamode = 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; /* If in stopped state then enables the I2C and DMA clocks.*/ if (i2cp->state == I2C_STOP) { #if STM32_I2C_USE_I2C1 if (&I2CD1 == i2cp) { bool_t b; rccResetI2C1(); b = dmaStreamAllocate(i2cp->dmarx, STM32_I2C_I2C1_IRQ_PRIORITY, (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, (void *)i2cp); chDbgAssert(!b, "i2c_lld_start(), #1", "stream already allocated"); b = dmaStreamAllocate(i2cp->dmatx, STM32_I2C_I2C1_IRQ_PRIORITY, (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, (void *)i2cp); chDbgAssert(!b, "i2c_lld_start(), #2", "stream already allocated"); rccEnableI2C1(FALSE); nvicEnableVector(I2C1_EV_IRQn, CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); nvicEnableVector(I2C1_ER_IRQn, CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); i2cp->dmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); } #endif /* STM32_I2C_USE_I2C1 */ #if STM32_I2C_USE_I2C2 if (&I2CD2 == i2cp) { bool_t b; rccResetI2C2(); b = dmaStreamAllocate(i2cp->dmarx, STM32_I2C_I2C2_IRQ_PRIORITY, (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, (void *)i2cp); chDbgAssert(!b, "i2c_lld_start(), #3", "stream already allocated"); b = dmaStreamAllocate(i2cp->dmatx, STM32_I2C_I2C2_IRQ_PRIORITY, (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, (void *)i2cp); chDbgAssert(!b, "i2c_lld_start(), #4", "stream already allocated"); rccEnableI2C2(FALSE); nvicEnableVector(I2C2_EV_IRQn, CORTEX_PRIORITY_MASK(STM32_I2C_I2C2_IRQ_PRIORITY)); nvicEnableVector(I2C2_ER_IRQn, CORTEX_PRIORITY_MASK(STM32_I2C_I2C2_IRQ_PRIORITY)); i2cp->dmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); } #endif /* STM32_I2C_USE_I2C2 */ #if STM32_I2C_USE_I2C3 if (&I2CD3 == i2cp) { bool_t b; rccResetI2C3(); b = dmaStreamAllocate(i2cp->dmarx, STM32_I2C_I2C3_IRQ_PRIORITY, (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, (void *)i2cp); chDbgAssert(!b, "i2c_lld_start(), #5", "stream already allocated"); b = dmaStreamAllocate(i2cp->dmatx, STM32_I2C_I2C3_IRQ_PRIORITY, (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, (void *)i2cp); chDbgAssert(!b, "i2c_lld_start(), #6", "stream already allocated"); rccEnableI2C3(FALSE); nvicEnableVector(I2C3_EV_IRQn, CORTEX_PRIORITY_MASK(STM32_I2C_I2C3_IRQ_PRIORITY)); nvicEnableVector(I2C3_ER_IRQn, CORTEX_PRIORITY_MASK(STM32_I2C_I2C3_IRQ_PRIORITY)); i2cp->dmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) | STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); } #endif /* STM32_I2C_USE_I2C3 */ } /* DMA streams mode preparation in advance.*/ dmaStreamSetMode(i2cp->dmatx, i2cp->dmamode | STM32_DMA_CR_DIR_M2P); dmaStreamSetMode(i2cp->dmarx, i2cp->dmamode | STM32_DMA_CR_DIR_P2M); /* I2C registers pointed by the DMA.*/ dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR); dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR); /* Reset i2c peripheral.*/ dp->CR1 = I2C_CR1_SWRST; dp->CR1 = 0; dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN; /* Setup I2C parameters.*/ i2c_lld_set_clock(i2cp); i2c_lld_set_opmode(i2cp); /* Ready to go.*/ dp->CR1 |= I2C_CR1_PE; }
/** * @brief Configures and activates the I2C peripheral. * * @param[in] i2cp pointer to the @p I2CDriver object * * @notapi */ void i2c_lld_start(I2CDriver *i2cp) { I2C_TypeDef *dp = i2cp->i2c; #if STM32_I2C_USE_DMA == TRUE /* Common DMA modes.*/ i2cp->txdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_M2P; i2cp->rxdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_P2M; #endif /* Make sure I2C peripheral is disabled */ dp->CR1 &= ~I2C_CR1_PE; /* If in stopped state then enables the I2C and DMA clocks.*/ if (i2cp->state == I2C_STOP) { #if STM32_I2C_USE_I2C1 if (&I2CD1 == i2cp) { rccResetI2C1(); rccEnableI2C1(FALSE); #if STM32_I2C_USE_DMA == TRUE { bool b; b = dmaStreamAllocate(i2cp->dmarx, STM32_I2C_I2C1_IRQ_PRIORITY, NULL, (void *)i2cp); osalDbgAssert(!b, "stream already allocated"); b = dmaStreamAllocate(i2cp->dmatx, STM32_I2C_I2C1_IRQ_PRIORITY, NULL, (void *)i2cp); osalDbgAssert(!b, "stream already allocated"); 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 */ #if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) nvicEnableVector(STM32_I2C1_GLOBAL_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); #elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) nvicEnableVector(STM32_I2C1_EVENT_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); nvicEnableVector(STM32_I2C1_ERROR_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); #else #error "I2C1 interrupt numbers not defined" #endif } #endif /* STM32_I2C_USE_I2C1 */ #if STM32_I2C_USE_I2C2 if (&I2CD2 == i2cp) { rccResetI2C2(); rccEnableI2C2(FALSE); #if STM32_I2C_USE_DMA == TRUE { bool b; b = dmaStreamAllocate(i2cp->dmarx, STM32_I2C_I2C2_IRQ_PRIORITY, NULL, (void *)i2cp); osalDbgAssert(!b, "stream already allocated"); b = dmaStreamAllocate(i2cp->dmatx, STM32_I2C_I2C2_IRQ_PRIORITY, NULL, (void *)i2cp); osalDbgAssert(!b, "stream already allocated"); 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 */ #if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) nvicEnableVector(STM32_I2C2_GLOBAL_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); #elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) nvicEnableVector(STM32_I2C2_EVENT_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); nvicEnableVector(STM32_I2C2_ERROR_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); #else #error "I2C2 interrupt numbers not defined" #endif } #endif /* STM32_I2C_USE_I2C2 */ #if STM32_I2C_USE_I2C3 if (&I2CD3 == i2cp) { rccResetI2C3(); rccEnableI2C3(FALSE); #if STM32_I2C_USE_DMA == TRUE { bool b; b = dmaStreamAllocate(i2cp->dmarx, STM32_I2C_I2C3_IRQ_PRIORITY, NULL, (void *)i2cp); osalDbgAssert(!b, "stream already allocated"); b = dmaStreamAllocate(i2cp->dmatx, STM32_I2C_I2C3_IRQ_PRIORITY, NULL, (void *)i2cp); osalDbgAssert(!b, "stream already allocated"); 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 */ #if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__) nvicEnableVector(STM32_I2C3_GLOBAL_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); #elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER) nvicEnableVector(STM32_I2C3_EVENT_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); nvicEnableVector(STM32_I2C3_ERROR_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); #else #error "I2C3 interrupt numbers not defined" #endif } #endif /* STM32_I2C_USE_I2C3 */ #if STM32_I2C_USE_I2C4 if (&I2CD4 == i2cp) { rccResetI2C4(); rccEnableI2C4(FALSE); #if STM32_I2C_USE_DMA == TRUE { bool b; b = dmaStreamAllocate(i2cp->dmarx, STM32_I2C_I2C4_IRQ_PRIORITY, NULL, (void *)i2cp); osalDbgAssert(!b, "stream already allocated"); b = dmaStreamAllocate(i2cp->dmatx, STM32_I2C_I2C4_IRQ_PRIORITY, NULL, (void *)i2cp); osalDbgAssert(!b, "stream already allocated"); i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C4_RX_DMA_CHANNEL) | STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C4_TX_DMA_CHANNEL) | STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); } #endif /*STM32_I2C_USE_DMA == TRUE */ #if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__) nvicEnableVector(STM32_I2C4_GLOBAL_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); #elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER) nvicEnableVector(STM32_I2C4_EVENT_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); nvicEnableVector(STM32_I2C4_ERROR_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); #else #error "I2C4 interrupt numbers not defined" #endif } #endif /* STM32_I2C_USE_I2C4 */ } #if STM32_I2C_USE_DMA == TRUE /* I2C registers pointed by the DMA.*/ dmaStreamSetPeripheral(i2cp->dmarx, &dp->RXDR); dmaStreamSetPeripheral(i2cp->dmatx, &dp->TXDR); #endif /* Reset i2c peripheral, the TCIE bit will be handled separately.*/ dp->CR1 = i2cp->config->cr1 | #if STM32_I2C_USE_DMA == TRUE I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN | /* Enable only if using DMA */ #endif I2C_CR1_ERRIE | I2C_CR1_NACKIE; /* Setup I2C parameters.*/ dp->TIMINGR = i2cp->config->timingr; /* Ready to go.*/ dp->CR1 |= I2C_CR1_PE; }