static void idle_rx_handler(UARTDriver *uart) { volatile uint16_t sr = uart->usart->SR; if (sr & (USART_SR_LBD | USART_SR_ORE | /* overrun error - packet was too big for DMA or DMA was too slow */ USART_SR_NE | /* noise error - we have lost a byte due to noise */ USART_SR_FE | USART_SR_PE)) { /* framing error - start/stop bit lost or line break */ /* send a line break - this will abort transmission/reception on the other end */ osalSysLockFromISR(); uart->usart->SR = ~USART_SR_LBD; uart->usart->CR1 |= USART_CR1_SBK; num_rx_error++; uart->usart->CR3 &= ~(USART_CR3_DMAT | USART_CR3_DMAR); (void)uart->usart->SR; (void)uart->usart->DR; (void)uart->usart->DR; dmaStreamDisable(uart->dmarx); dmaStreamDisable(uart->dmatx); dmaStreamSetMemory0(uart->dmarx, &iomcu.rx_io_packet); dmaStreamSetTransactionSize(uart->dmarx, sizeof(iomcu.rx_io_packet)); dmaStreamSetMode(uart->dmarx, uart->dmamode | STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); dmaStreamEnable(uart->dmarx); uart->usart->CR3 |= USART_CR3_DMAR; osalSysUnlockFromISR(); return; } if (sr & USART_SR_IDLE) { dma_rx_end_cb(uart); num_idle_rx++; } }
/** * @brief Shared end-of-rx service routine. * * @param[in] spip pointer to the @p SPIDriver object * @param[in] flags pre-shifted content of the ISR register */ static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { /* DMA errors handling.*/ #if defined(STM32_SPI_DMA_ERROR_HOOK) if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { STM32_SPI_DMA_ERROR_HOOK(spip); } #else (void)flags; #endif /* Stop everything.*/ dmaStreamDisable(spip->dmatx); dmaStreamDisable(spip->dmarx); #if STM32_SPI_USE_BIDIMODE spip->spi->CR1 |= SPI_CR1_BIDIOE; /* Errors reset sequence. It is required becaue BIDIOE could cause extra clock pulses after DMA stopped reading.*/ (void)spip->spi->DR; (void)spip->spi->SR; #endif /* Portable SPI ISR code defined in the high level driver, note, it is a macro.*/ _spi_isr_code(spip); }
static void dma_rx_end_cb(UARTDriver *uart) { osalSysLockFromISR(); uart->usart->CR3 &= ~(USART_CR3_DMAT | USART_CR3_DMAR); (void)uart->usart->SR; (void)uart->usart->DR; (void)uart->usart->DR; dmaStreamDisable(uart->dmarx); dmaStreamDisable(uart->dmatx); iomcu.process_io_packet(); num_total_rx++; num_dma_complete_rx = num_total_rx - num_idle_rx; dmaStreamSetMemory0(uart->dmarx, &iomcu.rx_io_packet); dmaStreamSetTransactionSize(uart->dmarx, sizeof(iomcu.rx_io_packet)); dmaStreamSetMode(uart->dmarx, uart->dmamode | STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); dmaStreamEnable(uart->dmarx); uart->usart->CR3 |= USART_CR3_DMAR; dmaStreamSetMemory0(uart->dmatx, &iomcu.tx_io_packet); dmaStreamSetTransactionSize(uart->dmatx, iomcu.tx_io_packet.get_size()); dmaStreamSetMode(uart->dmatx, uart->dmamode | STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); dmaStreamEnable(uart->dmatx); uart->usart->CR3 |= USART_CR3_DMAT; osalSysUnlockFromISR(); }
/** * @brief I2C error handler. * * @param[in] i2cp pointer to the @p I2CDriver object * @param[in] isr content of the ISR register to be decoded * * @notapi */ static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) { #if STM32_I2C_USE_DMA == TRUE /* Clears DMA interrupt flags just to be safe.*/ dmaStreamDisable(i2cp->dmatx); dmaStreamDisable(i2cp->dmarx); #else /* Disabling RX and TX interrupts.*/ i2cp->i2c->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE); #endif if (isr & I2C_ISR_BERR) i2cp->errors |= I2C_BUS_ERROR; if (isr & I2C_ISR_ARLO) i2cp->errors |= I2C_ARBITRATION_LOST; if (isr & I2C_ISR_OVR) i2cp->errors |= I2C_OVERRUN; if (isr & I2C_ISR_TIMEOUT) i2cp->errors |= I2C_TIMEOUT; /* If some error has been identified then sends wakes the waiting thread.*/ if (i2cp->errors != I2C_NO_ERROR) _i2c_wakeup_error_isr(i2cp); }
uint8_t i2c_t::CmdWriteRead(uint8_t Addr, uint8_t *WPtr, uint8_t WLength, uint8_t *RPtr, uint8_t RLength) { if(IBusyWait() != OK) return FAILURE; // Clear flags ii2c->SR1 = 0; while(RxIsNotEmpty()) (void)ii2c->DR; // Read DR until it empty ClearAddrFlag(); // Start transmission SendStart(); if(WaitEv5() != OK) return FAILURE; SendAddrWithWrite(Addr); if(WaitEv6() != OK) { SendStop(); return FAILURE; } // Start TX DMA if needed if(WLength != 0) { if(WaitEv8() != OK) return FAILURE; dmaStreamSetMemory0(PDmaTx, WPtr); dmaStreamSetTransactionSize(PDmaTx, WLength); PRequestingThread = chThdSelf(); dmaStreamEnable(PDmaTx); chSysLock(); chSchGoSleepS(THD_STATE_SUSPENDED); // Sleep until end chSysUnlock(); dmaStreamDisable(PDmaTx); } // Read if needed if(RLength != 0) { if(WaitEv8() != OK) return FAILURE; // Send repeated start SendStart(); if(WaitEv5() != OK) return FAILURE; SendAddrWithRead(Addr); if(WaitEv6() != OK) { SendStop(); return FAILURE; } // If number of data to be read is 1, then DMA cannot be used if(RLength == 1) { AckDisable(); SendStop(); if(WaitRx() != OK) return FAILURE; *RPtr = ReceiveData(); if(WaitStop() != OK) return FAILURE; return OK; } else { // more than 1 byte, use DMA AckEnable(); dmaStreamSetMemory0(PDmaRx, RPtr); dmaStreamSetTransactionSize(PDmaRx, RLength); DmaLastTransferSet(); // Inform DMA that this is last transfer => do not ACK last byte PRequestingThread = chThdSelf(); dmaStreamEnable(PDmaRx); chSysLock(); chSchGoSleepS(THD_STATE_SUSPENDED); // Sleep until end chSysUnlock(); dmaStreamDisable(PDmaRx); } // if lng==1 } // if != 0 SendStop(); return OK; }
/** * @brief USART de-initialization. * @details This function must be invoked with interrupts disabled. * * @param[in] uartp pointer to the @p UARTDriver object */ static void usart_stop(UARTDriver *uartp) { /* Stops RX and TX DMA channels.*/ dmaStreamDisable(uartp->dmarx); dmaStreamDisable(uartp->dmatx); /* Stops USART operations.*/ uartp->usart->CR1 = 0; uartp->usart->CR2 = 0; uartp->usart->CR3 = 0; }
uint8_t i2c_t::CmdWriteRead(uint8_t Addr, uint8_t *WPtr, uint8_t WLength, uint8_t *RPtr, uint8_t RLength) { if(IBusyWait() != OK) return FAILURE; // Clear flags ii2c->SR1 = 0; while(RxIsNotEmpty()) (void)ii2c->DR; // Read DR until it empty ClearAddrFlag(); // Start transmission SendStart(); if(WaitEv5() != OK) return FAILURE; SendAddrWithWrite(Addr); if(WaitEv6() != OK) { SendStop(); return FAILURE; } ClearAddrFlag(); // Start TX DMA if needed if(WLength != 0) { if(WaitEv8() != OK) return FAILURE; dmaStreamSetMemory0(PDmaTx, WPtr); dmaStreamSetMode (PDmaTx, I2C_DMATX_MODE); dmaStreamSetTransactionSize(PDmaTx, WLength); chSysLock(); PRequestingThread = chThdSelf(); dmaStreamEnable(PDmaTx); chSchGoSleepS(THD_STATE_SUSPENDED); // Sleep until end chSysUnlock(); dmaStreamDisable(PDmaTx); } // Read if needed if(RLength != 0) { if(WaitEv8() != OK) return FAILURE; // Send repeated start SendStart(); if(WaitEv5() != OK) return FAILURE; SendAddrWithRead(Addr); if(WaitEv6() != OK) { SendStop(); return FAILURE; } // If single byte is to be received, disable ACK before clearing ADDR flag if(RLength == 1) AckDisable(); else AckEnable(); ClearAddrFlag(); dmaStreamSetMemory0(PDmaRx, RPtr); dmaStreamSetMode (PDmaRx, I2C_DMARX_MODE); dmaStreamSetTransactionSize(PDmaRx, RLength); DmaLastTransferSet(); // Inform DMA that this is last transfer => do not ACK last byte chSysLock(); PRequestingThread = chThdSelf(); dmaStreamEnable(PDmaRx); chSchGoSleepS(THD_STATE_SUSPENDED); // Sleep until end chSysUnlock(); dmaStreamDisable(PDmaRx); } // if != 0 else WaitBTF(); // if nothing to read, just stop SendStop(); return OK; }
void i2c_t::IServeIRQ(uint32_t isr) { // Uart.PrintfI("isr: %X\r", isr); I2C_TypeDef *pi2c = PParams->pi2c; // To make things shorter #if 1 // ==== NACK ==== if((isr & I2C_ISR_NACKF) != 0) { // Stop DMA dmaStreamDisable(PParams->PDmaTx); dmaStreamDisable(PParams->PDmaRx); // Stop transaction pi2c->CR2 |= I2C_CR2_STOP; // Disable IRQs pi2c->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE); IState = istFailure; IWakeup(); return; } #endif #if 1 // ==== TX partly completed ==== if((isr & I2C_ISR_TCR) != 0) { dmaStreamDisable(PParams->PDmaTx); if(IState == istWriteWrite) { // Send next ILen bytes pi2c->CR2 = (pi2c->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | (ILen << 16); // Prepare and enable TX DMA for second write dmaStreamSetMode(PParams->PDmaTx, DMA_MODE_TX); dmaStreamSetMemory0(PParams->PDmaTx, IPtr); dmaStreamSetTransactionSize(PParams->PDmaTx, ILen); dmaStreamEnable(PParams->PDmaTx); IState = istWrite; } } #endif #if 1 // ==== TX completed ==== if((isr & I2C_ISR_TC) != 0) { dmaStreamDisable(PParams->PDmaTx); // } dmaStreamDisable(PParams->PDmaRx); // } Both sorts of transaction may be completed if(IState == istWriteRead) { // Write phase completed // Receive ILen bytes pi2c->CR2 = (pi2c->CR2 & ~I2C_CR2_NBYTES) | I2C_CR2_RD_WRN | (ILen << 16); dmaStreamEnable(PParams->PDmaRx); pi2c->CR2 |= I2C_CR2_START; // Send repeated start IState = istRead; } // if WriteRead else { // istWrite, istRead IState = istIdle; pi2c->CR2 |= I2C_CR2_STOP; pi2c->CR1 &= ~I2C_CR1_TCIE; // Disable TransferComplete IRQ IWakeup(); } } #endif }
/** * @brief Aborts an I2C transaction. * * @param[in] i2cp pointer to the @p I2CDriver object * * @notapi */ static void i2c_lld_abort_operation(I2CDriver *i2cp) { I2C_TypeDef *dp = i2cp->i2c; /* Stops the I2C peripheral.*/ dp->CR1 = I2C_CR1_SWRST; dp->CR1 = 0; dp->CR2 = 0; dp->SR1 = 0; /* Stops the associated DMA streams.*/ dmaStreamDisable(i2cp->dmatx); dmaStreamDisable(i2cp->dmarx); }
/** * @brief I2C error handler. * * @param[in] i2cp pointer to the @p I2CDriver object * * @notapi */ static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp) { I2C_TypeDef *dp = i2cp->i2c; i2cflags_t errors; /* Clears interrupt flags just to be safe.*/ chSysLockFromIsr(); dmaStreamDisable(i2cp->dmatx); dmaStreamDisable(i2cp->dmarx); chSysUnlockFromIsr(); errors = I2CD_NO_ERROR; if (dp->SR1 & I2C_SR1_BERR) { /* Bus error. */ dp->SR1 &= ~I2C_SR1_BERR; errors |= I2CD_BUS_ERROR; } if (dp->SR1 & I2C_SR1_ARLO) { /* Arbitration lost. */ dp->SR1 &= ~I2C_SR1_ARLO; errors |= I2CD_ARBITRATION_LOST; } if (dp->SR1 & I2C_SR1_AF) { /* Acknowledge fail. */ dp->SR1 &= ~I2C_SR1_AF; dp->CR2 &= ~I2C_CR2_ITEVTEN; dp->CR1 |= I2C_CR1_STOP; /* Setting stop bit. */ errors |= I2CD_ACK_FAILURE; } if (dp->SR1 & I2C_SR1_OVR) { /* Overrun. */ dp->SR1 &= ~I2C_SR1_OVR; errors |= I2CD_OVERRUN; } if (dp->SR1 & I2C_SR1_PECERR) { /* PEC error. */ dp->SR1 &= ~I2C_SR1_PECERR; errors |= I2CD_PEC_ERROR; } if (dp->SR1 & I2C_SR1_TIMEOUT) { /* SMBus Timeout. */ dp->SR1 &= ~I2C_SR1_TIMEOUT; errors |= I2CD_TIMEOUT; } if (dp->SR1 & I2C_SR1_SMBALERT) { /* SMBus alert. */ dp->SR1 &= ~I2C_SR1_SMBALERT; errors |= I2CD_SMB_ALERT; } /* If some error has been identified then sends wakes the waiting thread.*/ if (errors != I2CD_NO_ERROR) { i2cp->errors = errors; wakeup_isr(i2cp, RDY_RESET); } }
/** * @brief Aborts an I2C transaction. * * @param[in] i2cp pointer to the @p I2CDriver object * * @notapi */ static void i2c_lld_abort_operation(I2CDriver *i2cp) { I2C_TypeDef *dp = i2cp->i2c; if (dp->CR1 & I2C_CR1_PE) { /* Stops the I2C peripheral.*/ dp->CR1 &= ~I2C_CR1_PE; while (dp->CR1 & I2C_CR1_PE) dp->CR1 &= ~I2C_CR1_PE; dp->CR1 |= I2C_CR1_PE; } /* Stops the associated DMA streams.*/ dmaStreamDisable(i2cp->dmatx); dmaStreamDisable(i2cp->dmarx); }
/** * @brief Allocates a DMA stream. * @details The stream is allocated and, if required, the DMA clock enabled. * The function also enables the IRQ vector associated to the stream * and initializes its priority. * @pre The stream must not be already in use or an error is returned. * @post The stream is allocated and the default ISR handler redirected * to the specified function. * @post The stream ISR vector is enabled and its priority configured. * @post The stream must be freed using @p dmaStreamRelease() before it can * be reused with another peripheral. * @post The stream is in its post-reset state. * @note This function can be invoked in both ISR or thread context. * * @param[in] dmastp pointer to a stm32_dma_stream_t structure * @param[in] priority IRQ priority mask for the DMA stream * @param[in] func handling function pointer, can be @p NULL * @param[in] param a parameter to be passed to the handling function * @return The operation status. * @retval false no error, stream taken. * @retval true error, stream already taken. * * @special */ bool dmaStreamAllocate(const stm32_dma_stream_t *dmastp, uint32_t priority, stm32_dmaisr_t func, void *param) { osalDbgCheck(dmastp != NULL); /* Checks if the stream is already taken.*/ if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0) return true; /* Marks the stream as allocated.*/ dma_isr_redir[dmastp->selfindex].dma_func = func; dma_isr_redir[dmastp->selfindex].dma_param = param; dma_streams_mask |= (1 << dmastp->selfindex); /* Enabling DMA clocks required by the current streams set.*/ if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0) rccEnableDMA1(false); #if STM32_HAS_DMA2 if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) != 0) rccEnableDMA2(false); #endif /* Putting the stream in a safe state.*/ dmaStreamDisable(dmastp); dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE; /* Enables the associated IRQ vector if a callback is defined.*/ if (func != NULL) nvicEnableVector(dmastp->vector, priority); return false; }
u32 usart_support_n_read(void *sd) { struct usart_support_s *u = (struct usart_support_s *)sd; struct usart_rx_dma_state *s = &u->rx; s32 n_read = s->rd_wraps * USART_RX_BUFFER_LEN + s->rd; s32 n_written = (s->wr_wraps + 1) * USART_RX_BUFFER_LEN - dmaStreamGetTransactionSize(s->dma); s32 n_available = n_written - n_read; if (n_available < 0) { /* This strange and rare case occurs when NDTR has rolled over but the flag * hasn't been raised yet and thus n_wraps hasn't been incremented in the * ISR. Simply return 0 this time and the next time this function is called * (or at some point) the interrupt will have been triggered and the number * of bytes available in the buffer will be a sane amount. */ n_available = 0; } else if (n_available > USART_RX_BUFFER_LEN) { /* If greater than a whole buffer then we have had an overflow. */ log_error("DMA RX buffer overrun"); n_available = 0; /* Disable and re-enable the DMA channel to get back to a known good * state */ dmaStreamDisable(s->dma); usart_support_init_rx(u); } return n_available; }
/** * @brief DMA RX end IRQ handler. * * @param[in] nandp pointer to the @p NANDDriver object * @param[in] flags pre-shifted content of the ISR register * * @notapi */ static void nand_lld_serve_transfer_end_irq(NANDDriver *nandp, uint32_t flags) { /* DMA errors handling.*/ #if defined(STM32_NAND_DMA_ERROR_HOOK) if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { STM32_NAND_DMA_ERROR_HOOK(nandp); } #else (void)flags; #endif osalSysLockFromISR(); dmaStreamDisable(nandp->dma); switch (nandp->state){ case NAND_DMA_TX: nandp->state = NAND_PROGRAM; nandp->map_cmd[0] = NAND_CMD_PAGEPROG; /* thread will be woken from ready_isr() */ break; case NAND_DMA_RX: nandp->state = NAND_READY; nandp->rxdata = NULL; nandp->datalen = 0; wakeup_isr(nandp); break; default: osalSysHalt("Unhandled case"); break; } osalSysUnlockFromISR(); }
/** * @brief TX DMA common service routine. * * @param[in] uartp pointer to the @p UARTDriver object * @param[in] flags pre-shifted content of the ISR register */ static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) { /* DMA errors handling.*/ #if defined(STM32_UART_DMA_ERROR_HOOK) if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { STM32_UART_DMA_ERROR_HOOK(uartp); } #else (void)flags; #endif dmaStreamDisable(uartp->dmatx); /* Only enable TC interrupt if there's a callback attached to it. We have to do it here, rather than earlier, because TC flag is set until transmission starts.*/ if (uartp->config->txend2_cb != NULL) uartp->usart->CR1 |= USART_CR1_TCIE; /* A callback is generated, if enabled, after a completed transfer.*/ uartp->txstate = UART_TX_COMPLETE; if (uartp->config->txend1_cb != NULL) uartp->config->txend1_cb(uartp); /* If the callback didn't explicitly change state then the transmitter automatically returns to the idle state.*/ if (uartp->txstate == UART_TX_COMPLETE) uartp->txstate = UART_TX_IDLE; }
/** * @brief Allocates a DMA stream. * @details The stream is allocated and, if required, the DMA clock enabled. * The function also enables the IRQ vector associated to the stream * and initializes its priority. * @pre The stream must not be already in use or an error is returned. * @post The stream is allocated and the default ISR handler redirected * to the specified function. * @post The stream ISR vector is enabled and its priority configured. * @post The stream must be freed using @p dmaStreamRelease() before it can * be reused with another peripheral. * @post The stream is in its post-reset state. * @note This function can be invoked in both ISR or thread context. * * @param[in] dmastp pointer to a stm32_dma_stream_t structure * @param[in] priority IRQ priority mask for the DMA stream * @param[in] func handling function pointer, can be @p NULL * @param[in] param a parameter to be passed to the handling function * @return The operation status. * @retval FALSE no error, stream taken. * @retval TRUE error, stream already taken. * * @special */ bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, uint32_t priority, stm32_dmaisr_t func, void *param) { chDbgCheck(dmastp != NULL, "dmaAllocate"); /* Checks if the stream is already taken.*/ if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0) return TRUE; /* Marks the stream as allocated.*/ dma_isr_redir[dmastp->selfindex].dma_func = func; dma_isr_redir[dmastp->selfindex].dma_param = param; dma_streams_mask |= (1 << dmastp->selfindex); /* Enabling DMA clocks required by the current streams set.*/ if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0) rccEnableDMA1(FALSE); #if STM32_HAS_DMA2 if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) != 0) rccEnableDMA2(FALSE); #endif /* Putting the stream in a safe state.*/ dmaStreamDisable(dmastp); dmaStreamClearInterrupt(dmastp); dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE; /* Enables the associated IRQ vector if a callback is defined.*/ if (func != NULL) NVICEnableVector(dmastp->vector, CORTEX_PRIORITY_MASK(priority)); return FALSE; }
/** * @brief RX DMA common service routine. * * @param[in] uartp pointer to the @p UARTDriver object * @param[in] flags pre-shifted content of the ISR register */ static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) { /* DMA errors handling.*/ #if defined(STM32_UART_DMA_ERROR_HOOK) if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { STM32_UART_DMA_ERROR_HOOK(uartp); } #else (void)flags; #endif if (uartp->rxstate == UART_RX_IDLE) { /* Receiver in idle state, a callback is generated, if enabled, for each received character and then the driver stays in the same state.*/ if (uartp->config->rxchar_cb != NULL) uartp->config->rxchar_cb(uartp, uartp->rxbuf); } else { /* Receiver in active state, a callback is generated, if enabled, after a completed transfer.*/ dmaStreamDisable(uartp->dmarx); uartp->rxstate = UART_RX_COMPLETE; if (uartp->config->rxend_cb != NULL) uartp->config->rxend_cb(uartp); /* If the callback didn't explicitly change state then the receiver automatically returns to the idle state.*/ if (uartp->rxstate == UART_RX_COMPLETE) { uartp->rxstate = UART_RX_IDLE; set_rx_idle_loop(uartp); } } }
/** * @brief Stops an ongoing conversion. * * @param[in] adcp pointer to the @p ADCDriver object * * @notapi */ void adc_lld_stop_conversion(ADCDriver *adcp) { dmaStreamDisable(adcp->dmastp); adcp->adc->CR1 = 0; adcp->adc->CR2 = 0; adcp->adc->CR2 = ADC_CR2_ADON; }
/** * @brief I2C shared ISR code. * * @param[in] i2cp pointer to the @p I2CDriver object * @param[in] isr content of the ISR register to be decoded * * @notapi */ static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) { I2C_TypeDef *dp = i2cp->i2c; if ((isr & I2C_ISR_TC) && (i2cp->state == I2C_ACTIVE_TX)) { size_t rxbytes; /* Make sure no more 'Transfer complete' interrupts.*/ dp->CR1 &= ~I2C_CR1_TCIE; rxbytes = dmaStreamGetTransactionSize(i2cp->dmarx); if (rxbytes > 0) { i2cp->state = I2C_ACTIVE_RX; /* Enable RX DMA */ dmaStreamEnable(i2cp->dmarx); dp->CR2 &= ~I2C_CR2_NBYTES; dp->CR2 |= rxbytes << 16; /* Starts the read operation.*/ dp->CR2 |= I2C_CR2_RD_WRN; dp->CR2 |= I2C_CR2_START; } else { /* Nothing to receive - send STOP immediately.*/ dp->CR2 |= I2C_CR2_STOP; } } if (isr & I2C_ISR_NACKF) { /* Starts a STOP sequence immediately on error.*/ dp->CR2 |= I2C_CR2_STOP; i2cp->errors |= I2CD_ACK_FAILURE; } if (isr & I2C_ISR_STOPF) { /* Stops the associated DMA streams.*/ dmaStreamDisable(i2cp->dmatx); dmaStreamDisable(i2cp->dmarx); if (i2cp->errors) { wakeup_isr(i2cp, RDY_RESET); } else { wakeup_isr(i2cp, RDY_OK); } } }
/** * @brief Stops any ongoing receive operation. * @note Stopping a receive operation also suppresses the receive callbacks. * * @param[in] uartp pointer to the @p UARTDriver object * * @return The number of data frames not received by the * stopped receive operation. * * @notapi */ size_t uart_lld_stop_receive(UARTDriver *uartp) { size_t n; dmaStreamDisable(uartp->dmarx); n = dmaStreamGetTransactionSize(uartp->dmarx); set_rx_idle_loop(uartp); return n; }
void i2c_t::IServeErrIRQ(uint32_t isr) { // Uart.PrintfI("isre: %X\r", isr); // Stop DMA dmaStreamDisable(PParams->PDmaTx); dmaStreamDisable(PParams->PDmaRx); // Check errors uint32_t Errors = 0; if(isr & I2C_ISR_BERR) Errors |= I2C_BUS_ERROR; if(isr & I2C_ISR_ARLO) Errors |= I2C_ARBITRATION_LOST; if(isr & I2C_ISR_OVR) Errors |= I2C_OVERRUN; if(isr & I2C_ISR_TIMEOUT) Errors |= I2C_TIMEOUT; // If some error has been identified then wake the waiting thread if(Errors != I2C_NO_ERROR) { Uart.PrintfI("i2c err: %X\r", Errors); IWakeup(); } }
void Lcd_t::Shutdown(void) { dmaStreamDisable(LCD_DMA); XRES_Lo(); XCS_Lo(); SCLK_Lo(); SDA_Lo(); Backlight(0); }
void AdcTxIrq(void *p, uint32_t flags) { dmaStreamDisable(ADC_DMA); Adc.Stop(); // Signal event chSysLockFromISR(); App.SignalEvtI(EVT_ADC_DONE); chSysUnlockFromISR(); }
/** * @brief Stops an ongoing conversion. * * @param[in] adcp pointer to the @p ADCDriver object * * @notapi */ void adc_lld_stop_conversion(ADCDriver *adcp) { dmaStreamDisable(adcp->dmastp); adcp->adc->CR1 = 0; /* Because ticket #822, preserving injected conversions.*/ adcp->adc->CR2 &= ~(ADC_CR2_SWSTART); adcp->adc->CR2 = ADC_CR2_ADON; }
static void dma_i2s_interrupt(void* dat, uint32_t flags) { dmaStreamDisable(i2sdma); chSysLockFromIsr(); chEvtSignalFlagsI(playerThread, 1); chSysUnlockFromIsr(); }
// ==== TX DMA IRQ ==== void Uart_t::IRQDmaTxHandler() { dmaStreamDisable(UART_DMA_TX); // Registers may be changed only when stream is disabled IFullSlotsCount -= ITransSize; PRead += ITransSize; if(PRead >= (TXBuf + UART_TXBUF_SZ)) PRead = TXBuf; // Circulate pointer if(IFullSlotsCount == 0) IDmaIsIdle = true; // Nothing left to send else ISendViaDMA(); }
/** * @brief Stops an ongoing conversion. * * @param[in] adcp pointer to the @p ADCDriver object * * @notapi */ void adc_lld_stop_conversion(ADCDriver *adcp) { /* Disabling the associated DMA stream.*/ dmaStreamDisable(adcp->dmastp); /* Stopping and restarting the whole ADC, apparently the only way to stop a conversion.*/ adc_lld_reconfig(adcp); }
/** * @brief Shared service routine. * * @param[in] qspip pointer to the @p QSPIDriver object */ static void qspi_lld_serve_interrupt(QSPIDriver *qspip) { /* Stop everything.*/ dmaStreamDisable(qspip->dma); /* Portable QSPI ISR code defined in the high level driver, note, it is a macro.*/ _qspi_isr_code(qspip); }
uint8_t i2c_t::CmdWriteWrite(uint8_t Addr, uint8_t *WPtr1, uint8_t WLength1, uint8_t *WPtr2, uint8_t WLength2) { if(IBusyWait() != OK) return FAILURE; // Clear flags ii2c->SR1 = 0; while(RxIsNotEmpty()) (void)ii2c->DR; // Read DR until it empty ClearAddrFlag(); // Start transmission SendStart(); if(WaitEv5() != OK) return FAILURE; SendAddrWithWrite(Addr); if(WaitEv6() != OK) { SendStop(); return FAILURE; } ClearAddrFlag(); // Start TX DMA if needed if(WLength1 != 0) { if(WaitEv8() != OK) return FAILURE; dmaStreamSetMemory0(PDmaTx, WPtr1); dmaStreamSetMode (PDmaTx, I2C_DMATX_MODE); dmaStreamSetTransactionSize(PDmaTx, WLength1); chSysLock(); PRequestingThread = chThdSelf(); dmaStreamEnable(PDmaTx); chSchGoSleepS(THD_STATE_SUSPENDED); // Sleep until end chSysUnlock(); dmaStreamDisable(PDmaTx); } if(WLength2 != 0) { if(WaitEv8() != OK) return FAILURE; dmaStreamSetMemory0(PDmaTx, WPtr2); dmaStreamSetMode (PDmaTx, I2C_DMATX_MODE); dmaStreamSetTransactionSize(PDmaTx, WLength2); chSysLock(); PRequestingThread = chThdSelf(); dmaStreamEnable(PDmaTx); chSchGoSleepS(THD_STATE_SUSPENDED); // Sleep until end chSysUnlock(); dmaStreamDisable(PDmaTx); } WaitBTF(); SendStop(); return OK; }
/** * @brief Aborts an I2C transaction. * * @param[in] i2cp pointer to the @p I2CDriver object * * @notapi */ static void i2c_lld_abort_operation(I2CDriver *i2cp) { I2C_TypeDef *dp = i2cp->i2c; if (dp->CR1 & I2C_CR1_PE) { /* Stops the I2C peripheral.*/ dp->CR1 &= ~I2C_CR1_PE; while (dp->CR1 & I2C_CR1_PE) dp->CR1 &= ~I2C_CR1_PE; dp->CR1 |= I2C_CR1_PE; } #if STM32_I2C_USE_DMA == TRUE /* Stops the associated DMA streams.*/ dmaStreamDisable(i2cp->dmatx); dmaStreamDisable(i2cp->dmarx); #else dp->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE); #endif }