/** * @brief Receives data via the I2C bus as master. * @details Number of receiving bytes must be more than 1 because of stm32 * hardware restrictions. * * @param[in] i2cp pointer to the @p I2CDriver object * @param[in] addr slave device address * @param[out] rxbuf pointer to the receive buffer * @param[in] rxbytes number of bytes to be received * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: * - @a TIME_INFINITE no timeout. * . * @return The operation status. * @retval RDY_OK if the function succeeded. * @retval RDY_RESET if one or more I2C errors occurred, the errors can * be retrieved using @p i2cGetErrors(). * @retval RDY_TIMEOUT if a timeout occurred before operation end. <b>After a * timeout the driver must be stopped and restarted * because the bus is in an uncertain state</b>. * * @notapi */ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, uint8_t *rxbuf, size_t rxbytes, systime_t timeout) { I2C_TypeDef *dp = i2cp->i2c; VirtualTimer vt; chDbgCheck((rxbytes > 1), "i2c_lld_master_receive_timeout"); /* Global timeout for the whole operation.*/ if (timeout != TIME_INFINITE) chVTSetI(&vt, timeout, i2c_lld_safety_timeout, (void *)i2cp); /* Releases the lock from high level driver.*/ chSysUnlock(); /* Initializes driver fields, LSB = 1 -> receive.*/ i2cp->addr = (addr << 1) | 0x01; i2cp->errors = 0; /* RX DMA setup.*/ dmaStreamSetMemory0(i2cp->dmarx, rxbuf); dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); /* Waits until BUSY flag is reset and the STOP from the previous operation is completed, alternatively for a timeout condition.*/ while ((dp->SR2 & I2C_SR2_BUSY) || (dp->CR1 & I2C_CR1_STOP)) { chSysLock(); if ((timeout != TIME_INFINITE) && !chVTIsArmedI(&vt)) return RDY_TIMEOUT; chSysUnlock(); } /* This lock will be released in high level driver.*/ chSysLock(); /* Atomic check on the timer in order to make sure that a timeout didn't happen outside the critical zone.*/ if ((timeout != TIME_INFINITE) && !chVTIsArmedI(&vt)) return RDY_TIMEOUT; /* Starts the operation.*/ dp->CR2 |= I2C_CR2_ITEVTEN; dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK; /* Waits for the operation completion or a timeout.*/ i2cp->thread = chThdSelf(); chSchGoSleepS(THD_STATE_SUSPENDED); if ((timeout != TIME_INFINITE) && chVTIsArmedI(&vt)) chVTResetI(&vt); return chThdSelf()->p_u.rdymsg; }
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 }
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; } // Start TX DMA if needed if(WLength1 != 0) { if(WaitEv8() != OK) return FAILURE; dmaStreamSetMemory0(PDmaTx, WPtr1); dmaStreamSetTransactionSize(PDmaTx, WLength1); PRequestingThread = chThdSelf(); dmaStreamEnable(PDmaTx); chSysLock(); chSchGoSleepS(THD_STATE_SUSPENDED); // Sleep until end chSysUnlock(); dmaStreamDisable(PDmaTx); } if(WLength2 != 0) { if(WaitEv8() != OK) return FAILURE; dmaStreamSetMemory0(PDmaTx, WPtr2); dmaStreamSetTransactionSize(PDmaTx, WLength2); PRequestingThread = chThdSelf(); dmaStreamEnable(PDmaTx); chSysLock(); chSchGoSleepS(THD_STATE_SUSPENDED); // Sleep until end chSysUnlock(); dmaStreamDisable(PDmaTx); } SendStop(); return OK; }
void Adc_t::Measure(Thread *PThread, eventmask_t Evt) { IPThread = PThread; IEvt = Evt; // DMA dmaStreamSetMemory0(ADC_DMA, Result); dmaStreamSetTransactionSize(ADC_DMA, ADC_BUF_SZ); dmaStreamSetMode(ADC_DMA, ADC_DMA_MODE); dmaStreamEnable(ADC_DMA); // ADC ADC1->CR1 = ADC_CR1_SCAN; ADC1->CR2 = ADC_CR2_DMA | ADC_CR2_ADON; StartConversion(); }
/** * @brief Sends a command then receives data over the QSPI bus. * @post At the end of the operation the configured callback is invoked. * * @param[in] qspip pointer to the @p QSPIDriver object * @param[in] cmd pointer to the command descriptor * @param[in] n number of bytes to send * @param[out] rxbuf the pointer to the receive buffer * * @notapi */ void qspi_lld_receive(QSPIDriver *qspip, const qspi_command_t *cmdp, size_t n, uint8_t *rxbuf) { dmaStreamSetMemory0(qspip->dma, rxbuf); dmaStreamSetTransactionSize(qspip->dma, n); dmaStreamSetMode(qspip->dma, qspip->dmamode | STM32_DMA_CR_DIR_P2M); qspip->qspi->DLR = n - 1; qspip->qspi->ABR = cmdp->alt; qspip->qspi->CCR = cmdp->cfg | QUADSPI_CCR_FMODE_0; qspip->qspi->AR = cmdp->addr; dmaStreamEnable(qspip->dma); }
/** * @brief Sends a command with data over the QSPI bus. * @post At the end of the operation the configured callback is invoked. * * @param[in] qspip pointer to the @p QSPIDriver object * @param[in] cmd pointer to the command descriptor * @param[in] n number of bytes to send * @param[in] txbuf the pointer to the transmit buffer * * @notapi */ void qspi_lld_send(QSPIDriver *qspip, const qspi_command_t *cmdp, size_t n, const uint8_t *txbuf) { dmaStreamSetMemory0(qspip->dma, txbuf); dmaStreamSetTransactionSize(qspip->dma, n); dmaStreamSetMode(qspip->dma, qspip->dmamode | STM32_DMA_CR_DIR_M2P); qspip->qspi->DLR = n - 1; qspip->qspi->ABR = cmdp->alt; qspip->qspi->CCR = cmdp->cfg; qspip->qspi->AR = cmdp->addr; dmaStreamEnable(qspip->dma); }
/** * @brief Puts the receiver in the UART_RX_IDLE state. * * @param[in] uartp pointer to the @p UARTDriver object */ static void set_rx_idle_loop(UARTDriver *uartp) { uint32_t mode; /* RX DMA channel preparation, if the char callback is defined then the TCIE interrupt is enabled too.*/ if (uartp->config->rxchar_cb == NULL) mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC; else mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC | STM32_DMA_CR_TCIE; dmaStreamSetMemory0(uartp->dmarx, &uartp->rxbuf); dmaStreamSetTransactionSize(uartp->dmarx, 1); dmaStreamSetMode(uartp->dmarx, uartp->dmamode | mode); dmaStreamEnable(uartp->dmarx); }
/** * @brief Starts a receive operation on the UART peripheral. * @note The buffers are organized as uint8_t arrays for data sizes below * or equal to 8 bits else it is organized as uint16_t arrays. * * @param[in] uartp pointer to the @p UARTDriver object * @param[in] n number of data frames to send * @param[out] rxbuf the pointer to the receive buffer * * @notapi */ void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { /* Stopping previous activity (idle state).*/ dmaStreamDisable(uartp->dmarx); /* RX DMA channel preparation.*/ dmaStreamSetMemory0(uartp->dmarx, rxbuf); dmaStreamSetTransactionSize(uartp->dmarx, n); dmaStreamSetMode(uartp->dmarx, uartp->dmamode | STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); /* Starting transfer.*/ dmaStreamEnable(uartp->dmarx); }
// Used on double-buffered DMA streams. Set the buffer address which is // not currently in use void dmaSetOtherMemory(const stm32_dma_stream_t *dmastp, volatile uint16_t *addr) { if(dmastp->stream->CR | DMA_SxCR_CT) { // Memory address 1 active, so set address 0 dmaStreamSetMemory0(dmastp, addr); } else { // Memory address 0 active, so set address 1 dmaStreamSetMemory1(dmastp, addr); } }
void LedSk_t::ISetCurrentColors() { PBuf = IBuf + (RST_W_CNT / 2); // First words are zero to form reset // Fill bit buffer for(uint32_t i=0; i<LED_CNT; i++) { AppendBitsMadeOfByte(ICurrentClr[i].G); AppendBitsMadeOfByte(ICurrentClr[i].R); AppendBitsMadeOfByte(ICurrentClr[i].B); AppendBitsMadeOfByte(ICurrentClr[i].W); } // Start transmission dmaStreamSetMemory0(LEDWS_DMA, IBuf); dmaStreamSetTransactionSize(LEDWS_DMA, TOTAL_W_CNT); dmaStreamSetMode(LEDWS_DMA, LED_DMA_MODE); dmaStreamEnable(LEDWS_DMA); }
*/ bool_t sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk, uint8_t *buf, uint32_t n) { uint32_t resp[1]; chDbgCheck((n < (0x1000000 / MMCSD_BLOCK_SIZE)), "max transaction size"); //SDIO->DTIMER = STM32_SDC_READ_TIMEOUT; SDIO->DTIMER = 0xFFFFFFFF; // KL /* Checks for errors and waits for the card to be ready for reading.*/ if (_sdc_wait_for_transfer_state(sdcp)) return CH_FAILED; /* Prepares the DMA channel for writing.*/ dmaStreamSetMemory0(sdcp->dma, buf); dmaStreamSetTransactionSize(sdcp->dma, (n * MMCSD_BLOCK_SIZE) / sizeof (uint32_t)); dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M); dmaStreamEnable(sdcp->dma); /* Setting up data transfer.*/ SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS; SDIO->MASK = SDIO_MASK_DCRCFAILIE | SDIO_MASK_DTIMEOUTIE | SDIO_MASK_STBITERRIE | SDIO_MASK_RXOVERRIE | SDIO_MASK_DATAENDIE; SDIO->DLEN = n * MMCSD_BLOCK_SIZE; /* Talk to card what we want from it.*/ if (sdc_lld_prepare_read(sdcp, startblk, n, resp) == TRUE) goto error; /* Transaction starts just after DTEN bit setting.*/ SDIO->DCTRL = SDIO_DCTRL_DTDIR | SDIO_DCTRL_DBLOCKSIZE_3 | SDIO_DCTRL_DBLOCKSIZE_0 | SDIO_DCTRL_DMAEN | SDIO_DCTRL_DTEN; if (sdc_lld_wait_transaction_end(sdcp, n, resp) == TRUE) goto error; return CH_SUCCESS; error: sdc_lld_error_cleanup(sdcp, n, resp); return CH_FAILED;
static void dma_schedule(struct usart_tx_dma_state *s) { dmaStreamSetMemory0(s->dma, &s->buff[s->rd]); /* Save the transfer length so we can increment the read index after the * transfer is finished. */ if (s->rd < s->wr) /* DMA up until write pointer. */ s->xfer_len = s->wr - s->rd; else /* DMA up until the end of the buffer. */ s->xfer_len = USART_TX_BUFFER_LEN - s->rd; dmaStreamSetTransactionSize(s->dma, s->xfer_len); dmaStreamEnable(s->dma); s->busy = true; }
// ¬нешнее прерывание (не используетс¤) void eAdc_t::IIrqExtiHandler() { IrqSDO.CleanIrqFlag(); IrqSDO.DisableIrq(); PinSetupAlterFunc(ADC_GPIO, ADC_SDO, omPushPull, pudNone, AF5); (void)ADC_SPI->DR; // Clear input register dmaStreamAllocate (EADC_DMA, IRQ_PRIO_MEDIUM, SIrqDmaHandler, NULL); dmaStreamSetPeripheral(EADC_DMA, &ADC_SPI->DR); dmaStreamSetMode (EADC_DMA, EADC_DMA_MODE); dmaStreamSetMemory0(EADC_DMA, &Adc.Rslt); dmaStreamSetTransactionSize(EADC_DMA, 1); dmaStreamEnable(EADC_DMA); ISpi.Enable(); // LED1_TOGGLE(); }
// ==== TX DMA IRQ ==== void CmdUart_t::IRQDmaTxHandler() { dmaStreamDisable(UART_DMA_TX); // Registers may be changed only when stream is disabled IFullSlotsCount -= ITransSize; PRead += ITransSize; if(PRead >= (TXBuf + UART_TXBUF_SIZE)) PRead = TXBuf; // Circulate pointer if(IFullSlotsCount == 0) IDmaIsIdle = true; // Nothing left to send else { // There is something to transmit more dmaStreamSetMemory0(UART_DMA_TX, PRead); uint32_t PartSz = (TXBuf + UART_TXBUF_SIZE) - PRead; ITransSize = (IFullSlotsCount > PartSz)? PartSz : IFullSlotsCount; dmaStreamSetTransactionSize(UART_DMA_TX, ITransSize); dmaStreamSetMode(UART_DMA_TX, UART_DMA_TX_MODE); dmaStreamEnable(UART_DMA_TX); // Restart DMA } }
void Adc_t::Measure() { // DMA dmaStreamSetMemory0(ADC_DMA, Result); dmaStreamSetTransactionSize(ADC_DMA, ADC_BUF_SZ); dmaStreamSetMode(ADC_DMA, ADC_DMA_MODE); dmaStreamEnable(ADC_DMA); // ADC ADC1->CR1 = ADC_CR1_SCAN; ADC1->CR2 = ADC_CR2_DMA | ADC_CR2_ADON; chSysLock(); PAdcThread = chThdSelf(); StartConversion(); chSchGoSleepS(THD_STATE_SUSPENDED); chSysUnlock(); ADC1->CR2 = 0; }
/** * @brief Starts an ADC conversion. * * @param[in] adcp pointer to the @p ADCDriver object * * @notapi */ void adc_lld_start_conversion(ADCDriver *adcp) { uint32_t mode; uint32_t cr2; const ADCConversionGroup *grpp = adcp->grpp; /* DMA setup.*/ mode = adcp->dmamode; if (grpp->circular) { mode |= STM32_DMA_CR_CIRC; if (adcp->depth > 1) { /* If circular buffer depth > 1, then the half transfer interrupt is enabled in order to allow streaming processing.*/ mode |= STM32_DMA_CR_HTIE; } } dmaStreamSetMemory0(adcp->dmastp, adcp->samples); dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * (uint32_t)adcp->depth); dmaStreamSetMode(adcp->dmastp, mode); dmaStreamEnable(adcp->dmastp); /* ADC setup.*/ adcp->adc->SR = 0; adcp->adc->SMPR1 = grpp->smpr1; adcp->adc->SMPR2 = grpp->smpr2; adcp->adc->SQR1 = grpp->sqr1; adcp->adc->SQR2 = grpp->sqr2; adcp->adc->SQR3 = grpp->sqr3; /* ADC configuration and start.*/ adcp->adc->CR1 = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN; /* Enforcing the mandatory bits in CR2.*/ cr2 = grpp->cr2 | ADC_CR2_DMA | ADC_CR2_DDS | ADC_CR2_ADON; /* The start method is different dependign if HW or SW triggered, the start is performed using the method specified in the CR2 configuration.*/ if ((cr2 & ADC_CR2_SWSTART) != 0) { /* Initializing CR2 while keeping ADC_CR2_SWSTART at zero.*/ adcp->adc->CR2 = (cr2 | ADC_CR2_CONT) & ~ADC_CR2_SWSTART; /* Finally enabling ADC_CR2_SWSTART.*/ adcp->adc->CR2 = (cr2 | ADC_CR2_CONT); } else adcp->adc->CR2 = cr2; }
/** * @brief Writes one or more blocks. * * @param[in] sdcp pointer to the @p SDCDriver object * @param[in] startblk first block to write * @param[out] buf pointer to the write buffer * @param[in] n number of blocks to write * * @return The operation status. * @retval HAL_SUCCESS operation succeeded. * @retval HAL_FAILED operation failed. * * @notapi */ bool sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk, const uint8_t *buf, uint32_t blocks) { uint32_t resp[1]; osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE); sdcp->sdio->DTIMER = STM32_SDC_WRITE_TIMEOUT; /* Checks for errors and waits for the card to be ready for writing.*/ if (_sdc_wait_for_transfer_state(sdcp)) return HAL_FAILED; /* Prepares the DMA channel for writing.*/ dmaStreamSetMemory0(sdcp->dma, buf); dmaStreamSetTransactionSize(sdcp->dma, (blocks * MMCSD_BLOCK_SIZE) / sizeof (uint32_t)); dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_M2P); dmaStreamEnable(sdcp->dma); /* Setting up data transfer.*/ sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS; sdcp->sdio->MASK = SDIO_MASK_DCRCFAILIE | SDIO_MASK_DTIMEOUTIE | SDIO_MASK_STBITERRIE | SDIO_MASK_TXUNDERRIE | SDIO_MASK_DATAENDIE; sdcp->sdio->DLEN = blocks * MMCSD_BLOCK_SIZE; /* Talk to card what we want from it.*/ if (sdc_lld_prepare_write(sdcp, startblk, blocks, resp) == TRUE) goto error; /* Transaction starts just after DTEN bit setting.*/ sdcp->sdio->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3 | SDIO_DCTRL_DBLOCKSIZE_0 | SDIO_DCTRL_DMAEN | SDIO_DCTRL_DTEN; if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == TRUE) goto error; return HAL_SUCCESS; error: sdc_lld_error_cleanup(sdcp, blocks, resp); return HAL_FAILED; }
void Infrared_t::TxInit() { // ==== Carrier timer ==== Carrier.Init(); Carrier.Enable(); Carrier.PwmInit(IR_CARRIER_GPIO, IR_CARRIER_PIN, IR_CARRIER_CHNL, invNotInverted); Carrier.SetUpdateFrequency(IR_CARRIER_HZ); MaxPower = Carrier.GetTopValue() / 2; // Setup master-slave Carrier.SetTriggerInput(IR_CARRIER_TRG_IN); // Slave using TIM5 as input (ITR2) Carrier.SlaveModeSelect(smReset); // Slave mode: reset on trigger Carrier.MasterModeSelect(mmReset); // Master mode: trigger output on Reset Carrier.DmaOnTriggerEnable(); // Request DMA on trigger output == req on Reset = req on input //Carrier.PwmSet(MaxPower); // Debug // ==== Modulation timer ==== Modulator.Init(); Modulator.Enable(); Modulator.SetTopValue(IR_TICK_US-1); // Delay in us Modulator.MasterModeSelect(mmUpdate); // Master mode: Update is used as TRGO Modulator.SetupPrescaler(1000000); // Input Freq: 1 MHz => one tick = 1 uS Modulator.Disable(); // Debug // PinSetupAlterFunc(GPIOA, 0, omPushPull, pudNone, AF2); // Debug pin // TIM5->CCMR1 = (0b110<<4); // PWM mode1 // TIM5->CCR1 = IR_TICK_US/2; // TIM5->CCER = TIM_CCER_CC1E; // Enable output1 // ==== DMA ==== Here only the unchanged parameters of the DMA are configured dmaStreamAllocate (IR_TX_DMA_STREAM, IRQ_PRIO_LOW, IrTxcIrq, NULL); dmaStreamSetPeripheral(IR_TX_DMA_STREAM, Carrier.PCCR); dmaStreamSetMemory0 (IR_TX_DMA_STREAM, TxPwrBuf); dmaStreamSetMode (IR_TX_DMA_STREAM, STM32_DMA_CR_CHSEL(IR_TX_DMA_CHNL) | DMA_PRIORITY_MEDIUM | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MINC // Memory pointer increase | STM32_DMA_CR_DIR_M2P // Direction is memory to peripheral // | STM32_DMA_CR_CIRC // Enable circular buffer | STM32_DMA_CR_TCIE // Enable Transmission Complete IRQ ); // ==== Variables ==== IsBusy = false; }
static void usart_support_init_rx(struct usart_support_s *sd) { struct usart_rx_dma_state *s = &sd->rx; s->rd = s->rd_wraps = s->wr_wraps = 0; COMPILER_BARRIER(); /* Setup RX DMA */ dmaStreamSetMode(sd->rx.dma, sd->dmamode | STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | STM32_DMA_CR_CIRC); dmaStreamSetTransactionSize(sd->rx.dma, USART_RX_BUFFER_LEN); dmaStreamSetPeripheral(sd->rx.dma, &sd->usart->DR); dmaStreamSetMemory0(sd->rx.dma, sd->rx.buff); chBSemObjectInit(&sd->rx.ready, TRUE); dmaStreamEnable(sd->rx.dma); }
/** * @brief Starts a transmission on the UART peripheral. * @note The buffers are organized as uint8_t arrays for data sizes below * or equal to 8 bits else it is organized as uint16_t arrays. * * @param[in] uartp pointer to the @p UARTDriver object * @param[in] n number of data frames to send * @param[in] txbuf the pointer to the transmit buffer * * @notapi */ void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { /* TX DMA channel preparation.*/ dmaStreamSetMemory0(uartp->dmatx, txbuf); dmaStreamSetTransactionSize(uartp->dmatx, n); dmaStreamSetMode(uartp->dmatx, uartp->dmamode | STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); /* Only enable TC interrupt if there's a callback attached to it. Also we need to clear TC flag which could be set before. */ if (uartp->config->txend2_cb != NULL) { uartp->usart->ICR = USART_ICR_TCCF; uartp->usart->CR1 |= USART_CR1_TCIE; } /* Starting transfer.*/ dmaStreamEnable(uartp->dmatx); }
void CmdUart_t::Printf(const char *format, ...) { uint32_t MaxLength = (PWrite < PRead)? (PRead - PWrite) : ((UART_TXBUF_SIZE + PRead) - PWrite); va_list args; va_start(args, format); IFullSlotsCount += kl_vsprintf(FPutChar, MaxLength, format, args); va_end(args); // Start transmission if Idle if(IDmaIsIdle) { IDmaIsIdle = false; dmaStreamSetMemory0(UART_DMA_TX, PRead); uint32_t PartSz = (TXBuf + UART_TXBUF_SIZE) - PRead; // Char count from PRead to buffer end ITransSize = (IFullSlotsCount > PartSz)? PartSz : IFullSlotsCount; // How many to transmit now dmaStreamSetTransactionSize(UART_DMA_TX, ITransSize); dmaStreamSetMode(UART_DMA_TX, UART_DMA_TX_MODE); dmaStreamEnable(UART_DMA_TX); } }
void Adc_t::StartMeasurement() { // Stop ADC if(IsEnabled()) { SET_BIT(ADC1->CR, ADC_CR_ADSTP); // Stop any ongoing conversion while(READ_BIT(ADC1->CR, ADC_CR_ADSTP) != 0); // Let it to complete Disable(); while(IsEnabled()); // Let it to complete } Calibrate(); __NOP(); __NOP(); __NOP(); __NOP(); // ADEN bit cannot be set during ADCAL=1 and 4 ADC clock cycle after the ADCAL bit is cleared by hardware(end of the calibration). // Start ADC SET_BIT(ADC1->ISR, ADC_ISR_ADRDY); // Clear ADRDY bit by writing 1 to it SET_BIT(ADC1->CR, ADC_CR_ADEN); // Enable ADC while(READ_BIT(ADC1->ISR, ADC_ISR_ADRDY) == 0); // Let it to complete // Setup oversampler #if ADC_OVERSAMPLING_RATIO == 1 ADC1->CFGR2 = 0; // Oversampler disabled #elif ADC_OVERSAMPLING_RATIO == 2 ADC1->CFGR2 = (0b0001 << 5) | (0b000 << 2) | ADC_CFGR2_ROVSE; #elif ADC_OVERSAMPLING_RATIO == 4 ADC1->CFGR2 = (0b0010 << 5) | (0b001 << 2) | ADC_CFGR2_ROVSE; #elif ADC_OVERSAMPLING_RATIO == 8 ADC1->CFGR2 = (0b0011 << 5) | (0b010 << 2) | ADC_CFGR2_ROVSE; #elif ADC_OVERSAMPLING_RATIO == 16 ADC1->CFGR2 = (0b0100 << 5) | (0b011 << 2) | ADC_CFGR2_ROVSE; #elif ADC_OVERSAMPLING_RATIO == 32 ADC1->CFGR2 = (0b0101 << 5) | (0b100 << 2) | ADC_CFGR2_ROVSE; #elif ADC_OVERSAMPLING_RATIO == 64 ADC1->CFGR2 = (0b0110 << 5) | (0b101 << 2) | ADC_CFGR2_ROVSE; #elif ADC_OVERSAMPLING_RATIO == 128 ADC1->CFGR2 = (0b0111 << 5) | (0b110 << 2) | ADC_CFGR2_ROVSE; #elif ADC_OVERSAMPLING_RATIO == 256 ADC1->CFGR2 = (0b1000 << 5) | (0b111 << 2) | ADC_CFGR2_ROVSE; #endif // Setup ADC. Do not set OVRMOD bit as it breaks sequence in case of DMA SET_BIT(ADC1->CFGR, ADC_CFGR_DMAEN); // Enable DMA // DMA dmaStreamSetMemory0(ADC_DMA, IBuf); dmaStreamSetTransactionSize(ADC_DMA, ADC_SEQ_LEN); dmaStreamSetMode(ADC_DMA, ADC_DMA_MODE); dmaStreamEnable(ADC_DMA); // ADC StartConversion(); }
void Uart_t::Init(uint32_t ABaudrate, GPIO_TypeDef *PGpioTx, const uint16_t APinTx, GPIO_TypeDef *PGpioRx, const uint16_t APinRx) { #else void Uart_t::Init(uint32_t ABaudrate, GPIO_TypeDef *PGpioTx, const uint16_t APinTx) { #endif PinSetupAlterFunc(PGpioTx, APinTx, omPushPull, pudNone, UART_AF); IBaudrate = ABaudrate; // ==== USART configuration ==== if(UART == USART1) {rccEnableUSART1(FALSE); } else if(UART == USART2) {rccEnableUSART2(FALSE); } OnAHBFreqChange(); // Setup baudrate UART->CR2 = 0; #if UART_USE_DMA // ==== DMA ==== dmaStreamAllocate (UART_DMA_TX, IRQ_PRIO_MEDIUM, CmdUartTxIrq, NULL); dmaStreamSetPeripheral(UART_DMA_TX, &UART_TX_REG); dmaStreamSetMode (UART_DMA_TX, UART_DMA_TX_MODE); IDmaIsIdle = true; #endif #if UART_RX_ENABLED UART->CR1 = USART_CR1_TE | USART_CR1_RE; // TX & RX enable UART->CR3 = USART_CR3_DMAT | USART_CR3_DMAR; // Enable DMA at TX & RX PinSetupAlterFunc(PGpioRx, APinRx, omOpenDrain, pudPullUp, UART_AF); dmaStreamAllocate (UART_DMA_RX, IRQ_PRIO_LOW, nullptr, NULL); dmaStreamSetPeripheral(UART_DMA_RX, &UART_RX_REG); dmaStreamSetMemory0 (UART_DMA_RX, IRxBuf); dmaStreamSetTransactionSize(UART_DMA_RX, UART_RXBUF_SZ); dmaStreamSetMode (UART_DMA_RX, UART_DMA_RX_MODE); dmaStreamEnable (UART_DMA_RX); // Thread IPThd = chThdCreateStatic(waUartRxThread, sizeof(waUartRxThread), LOWPRIO, UartRxThread, NULL); #else UART->CR1 = USART_CR1_TE; // Transmitter enabled #if UART_USE_DMA UART->CR3 = USART_CR3_DMAT; // Enable DMA at transmitter #endif #endif UART->CR1 |= USART_CR1_UE; // Enable USART }
uint8_t i2c_t::WriteWrite(uint32_t Addr, uint8_t *WPtr1, uint32_t WLength1, uint8_t *WPtr2, uint32_t WLength2) { if(chBSemWait(&BSemaphore) != MSG_OK) return FAILURE; uint8_t Rslt; msg_t r; I2C_TypeDef *pi2c = PParams->pi2c; // To make things shorter if(WLength1 == 0 or WPtr1 == nullptr) { Rslt = CMD_ERROR; goto WriteWriteEnd; } if(IBusyWait() != OK) { Rslt = BUSY; goto WriteWriteEnd; } IReset(); // Reset I2C // Prepare TX DMA dmaStreamSetMode(PParams->PDmaTx, DMA_MODE_TX); dmaStreamSetMemory0(PParams->PDmaTx, WPtr1); dmaStreamSetTransactionSize(PParams->PDmaTx, WLength1); // Prepare transmission if(WLength2 != 0 and WPtr2 != nullptr) { IState = istWriteWrite; IPtr = WPtr2; ILen = WLength2; pi2c->CR2 = (Addr << 1) | (WLength1 << 16) | I2C_CR2_RELOAD; } else { // No second write IState = istWrite; pi2c->CR2 = (Addr << 1) | (WLength1 << 16); } dmaStreamEnable(PParams->PDmaTx); // Enable TX DMA // Enable IRQs: TX completed, error, NAck pi2c->CR1 |= (I2C_CR1_TCIE | I2C_CR1_ERRIE | I2C_CR1_NACKIE); pi2c->CR2 |= I2C_CR2_START; // Start transmission // Wait completion chSysLock(); r = chThdSuspendTimeoutS(&PThd, MS2ST(I2C_TIMEOUT_MS)); chSysUnlock(); // Disable IRQs pi2c->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_ERRIE | I2C_CR1_NACKIE); if(r == MSG_TIMEOUT) { pi2c->CR2 |= I2C_CR2_STOP; Rslt = TIMEOUT; } else Rslt = (IState == istFailure)? FAILURE : OK; WriteWriteEnd: chBSemSignal(&BSemaphore); return Rslt; }
/** * @brief Starts an ADC conversion. * * @param[in] adcp pointer to the @p ADCDriver object * * @notapi */ void adc_lld_start_conversion(ADCDriver *adcp) { uint32_t mode, cfgr1; const ADCConversionGroup *grpp = adcp->grpp; /* DMA setup.*/ mode = adcp->dmamode; cfgr1 = grpp->cfgr1 | ADC_CFGR1_DMAEN; if (grpp->circular) { mode |= STM32_DMA_CR_CIRC; cfgr1 |= ADC_CFGR1_DMACFG; if (adcp->depth > 1) { /* If circular buffer depth > 1, then the half transfer interrupt is enabled in order to allow streaming processing.*/ mode |= STM32_DMA_CR_HTIE; } } dmaStreamSetMemory0(adcp->dmastp, adcp->samples); dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * (uint32_t)adcp->depth); dmaStreamSetMode(adcp->dmastp, mode); dmaStreamEnable(adcp->dmastp); /* ADC setup, if it is defined a callback for the analog watch dog then it is enabled.*/ adcp->adc->ISR = adcp->adc->ISR; adcp->adc->IER = ADC_IER_OVRIE | ADC_IER_AWDIE; adcp->adc->TR = grpp->tr; adcp->adc->SMPR = grpp->smpr; adcp->adc->CHSELR = grpp->chselr; /* ADC configuration and start.*/ adcp->adc->CFGR1 = cfgr1; #if STM32_ADC_SUPPORTS_OVERSAMPLING == TRUE { uint32_t cfgr2 = adcp->adc->CFGR2 & STM32_ADC_CKMODE_MASK; adcp->adc->CFGR1 = cfgr2 | grpp->cfgr2; } #endif /* ADC conversion start.*/ adcp->adc->CR |= ADC_CR_ADSTART; }
// ==== IRQs ==== void DbgUart_t::IRQDmaTxHandler() { dmaStreamDisable(STM32_DMA2_STREAM7); // Registers may be changed only when stream is disabled if(ICountToSendNext == 0) IDmaIsIdle = true; else { // There is something to transmit more dmaStreamSetMemory0(STM32_DMA2_STREAM7, PRead); // Handle pointer uint32_t BytesLeft = UART_TXBUF_SIZE - (PRead - TXBuf); if(ICountToSendNext < BytesLeft) { // Data fits in buffer without split dmaStreamSetTransactionSize(STM32_DMA2_STREAM7, ICountToSendNext); PRead += ICountToSendNext; ICountToSendNext = 0; } else { // Some portion of data placed in the beginning dmaStreamSetTransactionSize(STM32_DMA2_STREAM7, BytesLeft); PRead = TXBuf; // Set pointer to beginning ICountToSendNext -= BytesLeft; } dmaStreamEnable(STM32_DMA2_STREAM7); // Restart DMA } }
/** * @brief Starts an ADC conversion. * * @param[in] adcp pointer to the @p ADCDriver object * * @notapi */ void adc_lld_start_conversion(ADCDriver *adcp) { uint32_t mode; const ADCConversionGroup *grpp = adcp->grpp; /* DMA setup.*/ mode = adcp->dmamode; if (grpp->circular) { mode |= STM32_DMA_CR_CIRC; if (adcp->depth > 1) { /* If circular buffer depth > 1, then the half transfer interrupt is enabled in order to allow streaming processing.*/ mode |= STM32_DMA_CR_HTIE; } } dmaStreamSetMemory0(adcp->dmastp, adcp->samples); dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * (uint32_t)adcp->depth); dmaStreamSetMode(adcp->dmastp, mode); dmaStreamEnable(adcp->dmastp); /* ADC setup.*/ adcp->adc->SR = 0; adcp->adc->SMPR1 = grpp->smpr1; adcp->adc->SMPR2 = grpp->smpr2; adcp->adc->SMPR3 = grpp->smpr3; adcp->adc->SQR1 = grpp->sqr1; adcp->adc->SQR2 = grpp->sqr2; adcp->adc->SQR3 = grpp->sqr3; adcp->adc->SQR4 = grpp->sqr4; adcp->adc->SQR5 = grpp->sqr5; /* ADC configuration and start, the start is performed using the method specified in the CR2 configuration, usually ADC_CR2_SWSTART.*/ adcp->adc->CR1 = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN; if ((grpp->cr2 & ADC_CR2_SWSTART) != 0) adcp->adc->CR2 = grpp->cr2 | ADC_CR2_CONT | ADC_CR2_DMA | ADC_CR2_DDS | ADC_CR2_ADON; else adcp->adc->CR2 = grpp->cr2 | ADC_CR2_DMA | ADC_CR2_DDS | ADC_CR2_ADON; }
void Infrared_t::Init() { // ==== Carrier timer ==== uint16_t tmp = (uint16_t)(Clk.AHBFreqHz / IR_CARRIER_HZ); // Top timer value Carrier.Init(GPIOA, 8, 1, 1, tmp, IR_TX_INVERTED); IR_CAR_TMR->SMCR = (0b000 << 4) | 0b100; // Slave using TIM5 as input (ITR0), Reset mode IR_CAR_TMR->CR2 = 0; // Reset is trigger output IR_CAR_TMR->DIER = TIM_DIER_TDE; // Request DMA on trigger MaxPower = tmp / 2; //Carrier.On(MaxPower); // Debug // ==== Modulation timer ==== rccEnableTIM5(FALSE); TIM5->ARR = IR_TICK_US-1; // Delay TIM5->CR2 = (0b010<<4); // Master mode: Update is used as TRGO TIM5->PSC = (Clk.APB1FreqHz / 1000000) - 1; // Input Freq: 1 MHz => one tick = 1 uS // Debug // PinSetupAlterFunc(GPIOA, 0, omPushPull, pudNone, AF2); // Debug pin // TIM5->CCMR1 = (0b110<<4); // PWM mode1 // TIM5->CCR1 = IR_TICK_US/2; // TIM5->CCER = TIM_CCER_CC1E; // Enable output1 // ==== DMA ==== Here only the unchanged parameters of the DMA are configured dmaStreamAllocate (IR_TX_DMA_STR, 1, IrTxcIrq, NULL); dmaStreamSetPeripheral(IR_TX_DMA_STR, Carrier.PCCR); dmaStreamSetMemory0(IR_TX_DMA_STR, Buf); //dmaStreamSetPeripheral(IR_TX_DMA_STR, &TIM1->CCR1); dmaStreamSetMode (IR_TX_DMA_STR, STM32_DMA_CR_CHSEL(IR_TX_DMA_CHNL) | DMA_PRIORITY_MEDIUM | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MINC // Memory pointer increase | STM32_DMA_CR_DIR_M2P // Direction is memory to peripheral // | STM32_DMA_CR_CIRC // Enable circular buffer | STM32_DMA_CR_TCIE // Enable Transmission Complete IRQ ); // ==== Variables ==== IsBusy = false; }
/** * @brief Starts a transmission on the UART peripheral. * @note The buffers are organized as uint8_t arrays for data sizes below * or equal to 8 bits else it is organized as uint16_t arrays. * * @param[in] uartp pointer to the @p UARTDriver object * @param[in] n number of data frames to send * @param[in] txbuf the pointer to the transmit buffer * * @notapi */ void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { /* TX DMA channel preparation.*/ dmaStreamSetMemory0(uartp->dmatx, txbuf); dmaStreamSetTransactionSize(uartp->dmatx, n); dmaStreamSetMode(uartp->dmatx, uartp->dmamode | STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); /* Only enable TC interrupt if there's a callback attached to it or if called from uartSendFullTimeout(). Also we need to clear TC flag which could be set before.*/ #if UART_USE_WAIT == TRUE if ((uartp->config->txend2_cb != NULL) || (uartp->early == false)) { #else if (uartp->config->txend2_cb != NULL) { #endif uartp->usart->SR = ~USART_SR_TC; uartp->usart->CR1 |= USART_CR1_TCIE; } /* Starting transfer.*/ dmaStreamEnable(uartp->dmatx); } /** * @brief Stops any ongoing transmission. * @note Stopping a transmission also suppresses the transmission callbacks. * * @param[in] uartp pointer to the @p UARTDriver object * * @return The number of data frames not transmitted by the * stopped transmit operation. * * @notapi */ size_t uart_lld_stop_send(UARTDriver *uartp) { dmaStreamDisable(uartp->dmatx); return dmaStreamGetTransactionSize(uartp->dmatx); }
void CmdUart_t::Init(uint32_t ABaudrate) { PWrite = TXBuf; PRead = TXBuf; IDmaIsIdle = true; IFullSlotsCount = 0; PinSetupAlterFunc(UART_GPIO, UART_TX_PIN, omPushPull, pudNone, UART_AF); // ==== USART configuration ==== UART_RCC_ENABLE(); // UART->CR1 = USART_CR1_UE; // Enable USART UART->BRR = Clk.APBFreqHz / ABaudrate; UART->CR2 = 0; // ==== DMA ==== dmaStreamAllocate (UART_DMA_TX, IRQ_PRIO_HIGH, CmdUartTxIrq, NULL); dmaStreamSetPeripheral(UART_DMA_TX, &UART->TDR); dmaStreamSetMode (UART_DMA_TX, UART_DMA_TX_MODE); #if UART_RX_ENABLED UART->CR1 = USART_CR1_TE | USART_CR1_RE; // TX & RX enable UART->CR3 = USART_CR3_DMAT | USART_CR3_DMAR; // Enable DMA at TX & RX IResetCmd(); PinSetupAlterFunc(UART_GPIO, UART_RX_PIN, omOpenDrain, pudPullUp, UART_AF); dmaStreamAllocate (UART_DMA_RX, IRQ_PRIO_LOW, nullptr, NULL); dmaStreamSetPeripheral(UART_DMA_RX, &UART->DR); dmaStreamSetMemory0 (UART_DMA_RX, IRxBuf); dmaStreamSetTransactionSize(UART_DMA_RX, UART_RXBUF_SZ); dmaStreamSetMode (UART_DMA_RX, UART_DMA_RX_MODE); dmaStreamEnable (UART_DMA_RX); // Create and start thread chThdCreateStatic(waUartRxThread, sizeof(waUartRxThread), NORMALPRIO, (tfunc_t)UartRxThread, NULL); #else UART->CR1 = USART_CR1_TE; // Transmitter enabled UART->CR3 = USART_CR3_DMAT; // Enable DMA at transmitter #endif UART->CR1 |= USART_CR1_UE; // Enable USART }