Beispiel #1
0
/**
 * @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;
}
Beispiel #2
0
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
}
Beispiel #3
0
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;
}
Beispiel #4
0
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();
}
Beispiel #5
0
/**
 * @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);
}
Beispiel #6
0
/**
 * @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);
}
Beispiel #7
0
/**
 * @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);
}
Beispiel #8
0
/**
 * @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);
}
Beispiel #9
0
// 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);
    }

}
Beispiel #10
0
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);
}
Beispiel #11
0
 */
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;
Beispiel #12
0
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();
}
Beispiel #14
0
// ==== 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
    }
}
Beispiel #15
0
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;
}
Beispiel #16
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;
}
Beispiel #17
0
/**
 * @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;
}
Beispiel #18
0
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;
}
Beispiel #19
0
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);

}
Beispiel #20
0
/**
 * @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);
}
Beispiel #21
0
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);
    }
}
Beispiel #22
0
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();
}
Beispiel #23
0
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
}
Beispiel #24
0
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;
}
Beispiel #25
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, 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;
}
Beispiel #26
0
// ==== 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
    }
}
Beispiel #27
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;
  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;
}
Beispiel #28
0
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;
}
Beispiel #29
0
/**
 * @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);
}
Beispiel #30
0
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
}