Exemple #1
0
/** Setup the USART for recieve with DMA. This function sets up the DMA
 * controller and additional USART parameters for DMA receive. The USART must
 * first be configured using \ref usart_setup_common. */
void usart_rx_dma_setup(void) {
  /* Set up the USART1 RX DMA and interrupts. */

  /* Enable clock to DMA peripheral. */
  RCC_AHB1ENR |= RCC_AHB1ENR_DMA2EN;

  /* Enable RX DMA on the USART. */
  usart_enable_rx_dma(USART1);

  /* USART1 RX - DMA2, stream 5, channel 4. */

  /* Make sure stream is disabled to start. */
  DMA2_S5CR &= ~DMA_SxCR_EN;
  DMA2_S5CR = 0;

  /* Configure the DMA controller. */
              /* Error interrupts. */
  DMA2_S5CR = DMA_SxCR_DMEIE | DMA_SxCR_TEIE |
              /* Transfer complete interrupt. */
              DMA_SxCR_TCIE |
              /* Enable circular buffer mode. */
              DMA_SxCR_CIRC |
              DMA_SxCR_DIR_PERIPHERAL_TO_MEM |
              /* Increment the memory address after each transfer. */
              DMA_SxCR_MINC |
              /* 8 bit transfers from USART peripheral. */
              DMA_SxCR_PSIZE_8BIT |
              /* and to memory. */
              DMA_SxCR_MSIZE_8BIT |
              /* Low priority. */
              DMA_SxCR_PL_LOW |
              /* The channel selects which request line will trigger a
               * transfer. In this case, channel 4 = UART1_RX
               * (see CD00225773.pdf Table 23). */
              DMA_SxCR_CHSEL(4);

  /* Transfer up the the length of the buffer. */
  DMA2_S5NDTR = USART_RX_BUFFER_LEN;

  DMA2_S5PAR = &USART1_DR; /* DMA from the USART1 data register. */
  DMA2_S5M0AR = rx_buff;      /* to the rx_buff. */

  // TODO: Investigate more about the best FIFO settings.
  DMA2_S5FCR = DMA_SxFCR_DMDIS |         /* Enable DMA stream FIFO. */
               DMA_SxFCR_FTH_2_4_FULL |  /* Trigger level 1/2 full. */
               DMA_SxFCR_FEIE;           /* Enable FIFO error interrupt. */

  rx_rd = 0;  /* Buffer is empty to begin with. */
  rd_wraps = wr_wraps = 0;

  /* Enable DMA2 Stream 5 (RX) interrupts with the NVIC. */
  nvic_enable_irq(NVIC_DMA2_STREAM5_IRQ);

  /* Enable the DMA channel. */
  DMA2_S5CR |= DMA_SxCR_EN;
}
Exemple #2
0
/** Setup the USART for transmission with DMA. This function sets up the DMA
 * controller and additional USART parameters for DMA transmission. The USART
 * must first be configured using \ref usart_setup_common. */
void usart_tx_dma_setup(void) {
  /* Set up the USART1 TX DMA and interrupts. */

  /* Enable clock to DMA peripheral. */
  RCC_AHB1ENR |= RCC_AHB1ENR_DMA2EN;

  /* Enable TX DMA on the USART. */
  usart_enable_tx_dma(USART1);

  /* USART1 TX - DMA2, stream 7, channel 4 */

  /* Make sure stream is disabled to start. */
  DMA2_S7CR &= ~DMA_SxCR_EN;
  DMA2_S7CR = 0;

  /* Configure the DMA controller. */
              /* Error interrupts. */
  DMA2_S7CR = DMA_SxCR_DMEIE | DMA_SxCR_TEIE |
              /* Transfer complete interrupt. */
              DMA_SxCR_TCIE |
              DMA_SxCR_DIR_MEM_TO_PERIPHERAL |
              /* Increment the memory address after each transfer. */
              DMA_SxCR_MINC |
              /* 8 bit transfers to USART peripheral. */
              DMA_SxCR_PSIZE_8BIT |
              /* and from memory. */
              DMA_SxCR_MSIZE_8BIT |
              /* Low priority. */
              DMA_SxCR_PL_LOW |
              /* The channel selects which request line will trigger a
               * transfer. In this case, channel 4 = UART1_TX
               * (see CD00225773.pdf Table 23). */
              DMA_SxCR_CHSEL(4);

  /* For now, don't transfer any number of datas (will be set in the initiating
   * function). */
  DMA2_S7NDTR = 0;

  DMA2_S7PAR = &USART1_DR; /* DMA into the USART1 data register. */
  DMA2_S7M0AR = buff;      /* from the buff. */

  /* TODO: Investigate more about the best FIFO settings. */
  DMA2_S7FCR = DMA_SxFCR_DMDIS |         /* Enable DMA stream FIFO. */
               DMA_SxFCR_FTH_2_4_FULL |  /* Trigger level 1/2 full. */
               DMA_SxFCR_FEIE;           /* Enable FIFO error interrupt. */

  wr = rd = 0;  /* Buffer is empty to begin with. */

  /* Enable DMA2 Stream 7 (TX) interrupts with the NVIC. */
  nvic_enable_irq(NVIC_DMA2_STREAM7_IRQ);
}
Exemple #3
0
static void spi_dma_setup_rx(uint32_t spi, uint32_t dma, u8 stream, u8 channel)
{
  spi_enable_rx_dma(spi);

  /* Make sure stream is disabled to start. */
  DMA_SCR(dma, stream) &= ~DMA_SxCR_EN;

  /* RM0090 - 9.3.17 : Supposed to wait until enable bit reads '0' before we
   * write to registers. */
  while (DMA_SCR(dma, stream) & DMA_SxCR_EN) ;

  /* RM0090 - 9.3.17 : Supposed to clear any interrupts in DMA status register
   * before we reconfigure registers. */
  dma_clear_interrupt_flags(dma, stream, DMA_ISR_FLAGS);

  /* Configure the DMA controller. */
  DMA_SCR(dma, stream) = 0;
  DMA_SCR(dma, stream) =
    /* Error interrupts. */
    DMA_SxCR_DMEIE | DMA_SxCR_TEIE |
    DMA_SxCR_DIR_PERIPHERAL_TO_MEM |
    /* Enable DMA transfer complete interrupt */
    DMA_SxCR_TCIE |
    /* Increment the memory address after each transfer. */
    DMA_SxCR_MINC |
    /* 8 bit transfers from SPI peripheral. */
    DMA_SxCR_PSIZE_8BIT |
    /* and to memory. */
    DMA_SxCR_MSIZE_8BIT |
    /* Low priority. */
    DMA_SxCR_PL_VERY_HIGH |
    /* The channel selects which request line will trigger a transfer.
     * (see CD00225773.pdf Table 23). */
    DMA_SxCR_CHSEL(channel);

  /* Transfer up to the length of the buffer. */
  DMA_SNDTR(dma, stream) = 0;

  /* DMA from the SPI data register... */
  DMA_SPAR(dma, stream) = &SPI_DR(spi);

  /* Enable DMA interrupts for this stream with the NVIC. */
  if (dma == DMA1)
    nvicEnableVector(dma_irq_lookup[0][stream],
        CORTEX_PRIORITY_MASK(CORTEX_MAX_KERNEL_PRIORITY+2));
  else if (dma == DMA2)
    nvicEnableVector(dma_irq_lookup[1][stream],
        CORTEX_PRIORITY_MASK(CORTEX_MAX_KERNEL_PRIORITY+2));
}
Exemple #4
0
static void spi_dma_setup_tx(uint32_t spi, uint32_t dma, u8 stream, u8 channel)
{
  spi_enable_tx_dma(spi);

  /* Make sure stream is disabled to start. */
  DMA_SCR(dma, stream) &= ~DMA_SxCR_EN;

  /* Configure the DMA controller. */
  DMA_SCR(dma, stream) = 0;
  DMA_SCR(dma, stream) =
    /* Error interrupts. */
    DMA_SxCR_DMEIE | DMA_SxCR_TEIE |
    DMA_SxCR_DIR_MEM_TO_PERIPHERAL |
    /* Increment the memory address after each transfer. */
    DMA_SxCR_MINC |
    /* 8 bit transfers from SPI peripheral. */
    DMA_SxCR_PSIZE_8BIT |
    /* and to memory. */
    DMA_SxCR_MSIZE_8BIT |
    /* Low priority. */
    DMA_SxCR_PL_VERY_HIGH |
    /* The channel selects which request line will trigger a transfer.
     * (see CD00225773.pdf Table 23). */
    DMA_SxCR_CHSEL(channel);

  /* Transfer up to the length of the buffer. */
  DMA_SNDTR(dma, stream) = 0;

  /* DMA from the SPI data register... */
  DMA_SPAR(dma, stream) = &SPI_DR(spi);

  /* Enable DMA interrupts for this stream with the NVIC. */
  if (dma == DMA1)
    nvicEnableVector(dma_irq_lookup[0][stream],
        CORTEX_PRIORITY_MASK(CORTEX_MAX_KERNEL_PRIORITY+2));
  else if (dma == DMA2)
    nvicEnableVector(dma_irq_lookup[1][stream],
        CORTEX_PRIORITY_MASK(CORTEX_MAX_KERNEL_PRIORITY+2));
}
Exemple #5
0
void init_usart(void) {
    usart_t *usart1 = get_usart(1);

    *RCC_APB2ENR |= RCC_APB2ENR_USART1EN;  /* Enable USART1 Clock */
    *RCC_AHB1ENR |= RCC_AHB1ENR_GPIOBEN;   /* Enable GPIOB Clock */

    /* Set PB6 and PB7 to alternative function USART
     * See stm32f4_ref.pdf pg 141 and stm32f407.pdf pg 51 */

    /* PB6 */
    gpio_moder(GPIOB, 6, GPIO_MODER_ALT);
    gpio_afr(GPIOB, 6, GPIO_AF_USART13);
    gpio_otyper(GPIOB, 6, GPIO_OTYPER_PP);
    gpio_pupdr(GPIOB, 6, GPIO_PUPDR_NONE);
    gpio_ospeedr(GPIOB, 6, GPIO_OSPEEDR_50M);

    /* PB7 */
    gpio_moder(GPIOB, 7, GPIO_MODER_ALT);
    gpio_afr(GPIOB, 7, GPIO_AF_USART13);
    gpio_otyper(GPIOB, 7, GPIO_OTYPER_PP);
    gpio_pupdr(GPIOB, 7, GPIO_PUPDR_NONE);
    gpio_ospeedr(GPIOB, 7, GPIO_OSPEEDR_50M);

    /* Enable USART1 */
    usart1->CR1 |= USART_CR1_UE;

    /* 8 data bits */
    usart1->CR1 &= ~(1 << 12);

    /* 1 stop bit */
    usart1->CR2 &= ~(3 << 12);

    /** DMA set up **/
    /* DMA2, Stream 2, Channel 4 is USART1_RX
     * DMA2, Stream 7, Channel 4 is USART1_TX */
    usart1->CR3 |= USART_CR3_DMAR | USART_CR3_DMAT;

    /* Enable DMA2 clock */
    *RCC_AHB1ENR |= RCC_AHB1ENR_DMA2EN;
    *RCC_AHB1ENR |= RCC_AHB1ENR_DMA1EN;

    /* Clear configuration registers enable bits and wait for them to be ready */
    *DMA2_CR_S(2) &= ~(DMA_SxCR_EN);
    *DMA2_CR_S(7) &= ~(DMA_SxCR_EN);
    while ( (*DMA2_CR_S(2) & DMA_SxCR_EN) || (*DMA2_CR_S(7) & DMA_SxCR_EN) );

    /* Select channel 4 */
    *DMA2_CR_S(2) |= DMA_SxCR_CHSEL(4);
    *DMA2_CR_S(7) |= DMA_SxCR_CHSEL(4);

    /* Peripheral address - Both use USART data register */
    *DMA2_PAR_S(2) = (uint32_t) &usart1->DR;    /* RX */
    *DMA2_PAR_S(7) = (uint32_t) &usart1->DR;    /* TX */

    /*
     * Allocate buffer memory.
     * This must be allocated because static data goes into
     * CCMRAM on STM32F4 implementation, and the bus matrix
     * does not connect CCMRAM to the DMA engine. Thus, it
     * is allocated from user heap to ensure it is accessible
     * by DMA
     */
    usart_rx_buf = (char *) malloc(USART_DMA_MSIZE);
    usart_tx_buf = (char *) malloc(USART_DMA_MSIZE);
    if ((usart_rx_buf == NULL) || (usart_tx_buf == NULL)) {
        panic();
    }
    else {
        /* Clear buffers */
        memset(usart_rx_buf, 0, USART_DMA_MSIZE);
        memset(usart_tx_buf, 0, USART_DMA_MSIZE);
        *DMA2_M0AR_S(2) = (uint32_t) usart_rx_buf;
        *DMA2_M0AR_S(7) = (uint32_t) usart_tx_buf;
    }

    /* Number of data items to be transferred */
    *DMA2_NDTR_S(2) = (uint16_t) USART_DMA_MSIZE;

    /* FIFO setup */
    *DMA2_FCR_S(7) |= DMA_SxFCR_FTH_4 | DMA_SxFCR_DMDIS;

    /* Data direct, memory increment, high priority, memory burst */
    *DMA2_CR_S(2) |= DMA_SxCR_DIR_PM | DMA_SxCR_MINC | DMA_SxCR_PL_HIGH | DMA_SxCR_CIRC;
    *DMA2_CR_S(7) |= DMA_SxCR_DIR_MP | DMA_SxCR_MINC | DMA_SxCR_PL_HIGH | DMA_SxCR_MBURST_4;

    /* Enable DMAs */
    *DMA2_CR_S(2) |= DMA_SxCR_EN;

    /** DMA End **/

    /* Set baud rate */
    usart1->BRR = usart_baud(115200);

    /* Enable reciever and transmitter */
    usart1->CR1 |= USART_CR1_RE;
    usart1->CR1 |= USART_CR1_TE;

    usart_ready = 1;
}
Exemple #6
0
/** Setup the USART for receive with DMA.
 * This function sets up the DMA controller and additional USART parameters for
 * DMA receive. The USART must already be configured for normal operation.
 *
 * \param s The USART DMA state structure.
 * \oaram usart The USART base address.
 * \param dma The DMA controller base address.
 * \param stream The DMA stream number to use.
 * \param channel The DMA channel to use. The stream and channel must
 *                correspond to a USART RX channel.
 */
void usart_rx_dma_setup(usart_rx_dma_state* s, u32 usart,
                        u32 dma, u8 stream, u8 channel)
{
  s->dma = dma;
  s->usart = usart;
  s->stream = stream;
  s->channel = channel;
  chBSemInit(&s->ready_sem, TRUE);

  s->byte_counter = 0;
  s->last_byte_ticks = chTimeNow();

  /* Enable clock to DMA peripheral. */
  if (dma == DMA1)
    RCC_AHB1ENR |= RCC_AHB1ENR_DMA1EN;
  else if (dma == DMA2)
    RCC_AHB1ENR |= RCC_AHB1ENR_DMA2EN;

  /* Enable RX DMA on the USART. */
  usart_enable_rx_dma(usart);

  /* Make sure stream is disabled to start. */
  DMA_SCR(dma, stream) &= ~DMA_SxCR_EN;

  /* RM0090 - 9.3.17 : Supposed to wait until enable bit reads '0' before we
   * write to registers. */
  while (DMA_SCR(dma, stream) & DMA_SxCR_EN) ;

  /* RM0090 - 9.3.17 : Supposed to clear any interrupts in DMA status register
   * before we reconfigure registers. */
  dma_clear_interrupt_flags(dma, stream, DMA_ISR_FLAGS);

  /* Configure the DMA controller. */
  DMA_SCR(dma, stream) = 0;
  DMA_SCR(dma, stream) =
    /* Error interrupts. */
    DMA_SxCR_DMEIE | DMA_SxCR_TEIE |
    /* Transfer complete interrupt. */
    DMA_SxCR_TCIE |
    /* Enable circular buffer mode. */
    DMA_SxCR_CIRC |
    DMA_SxCR_DIR_PERIPHERAL_TO_MEM |
    /* Increment the memory address after each transfer. */
    DMA_SxCR_MINC |
    /* 8 bit transfers from USART peripheral. */
    DMA_SxCR_PSIZE_8BIT |
    /* and to memory. */
    DMA_SxCR_MSIZE_8BIT |
    /* Low priority. */
    DMA_SxCR_PL_LOW |
    /* The channel selects which request line will trigger a transfer.
     * (see CD00225773.pdf Table 23). */
    DMA_SxCR_CHSEL(channel);

  /* Transfer up to the length of the buffer. */
  DMA_SNDTR(dma, stream) = USART_RX_BUFFER_LEN;

  /* DMA from the USART data register... */
  DMA_SPAR(dma, stream) = &USART_DR(usart);
  /* ...to the RX buffer. */
  DMA_SM0AR(dma, stream) = s->buff;

  /* Buffer is empty to begin with. */
  s->rd = 0;
  s->rd_wraps = s->wr_wraps = 0;

  /* Enable DMA interrupts for this stream with the NVIC. */
  if (dma == DMA1)
    nvicEnableVector(dma_irq_lookup[0][stream],
        CORTEX_PRIORITY_MASK(USART_DMA_ISR_PRIORITY));
  else if (dma == DMA2)
    nvicEnableVector(dma_irq_lookup[1][stream],
        CORTEX_PRIORITY_MASK(USART_DMA_ISR_PRIORITY));

  /* These reads clear error flags before enabling DMA */
  (void)USART_SR(usart);
  (void)USART_DR(usart);

  /* Enable the DMA channel. */
  DMA_SCR(dma, stream) |= DMA_SxCR_EN;
}
Exemple #7
0
/** Setup the USART for transmission with DMA.
 * This function sets up the DMA controller and additional USART parameters for
 * DMA transmit. The USART must already be configured for normal operation.
 *
 * \param s The USART DMA state structure.
 * \oaram usart The USART base address.
 * \param dma The DMA controller base address.
 * \param stream The DMA stream number to use.
 * \param channel The DMA channel to use. The stream and channel must
 *                correspond to a USART RX channel.
 */
void usart_tx_dma_setup(usart_tx_dma_state* s, u32 usart,
                        u32 dma, u8 stream, u8 channel)
{
    s->dma = dma;
    s->usart = usart;
    s->stream = stream;
    s->channel = channel;

    s->byte_counter = 0;
    s->last_byte_ticks = chTimeNow();

    /* Enable clock to DMA peripheral. */
    if (dma == DMA1)
        RCC_AHB1ENR |= RCC_AHB1ENR_DMA1EN;
    else if (dma == DMA2)
        RCC_AHB1ENR |= RCC_AHB1ENR_DMA2EN;

    /* Enable TX DMA on the USART. */
    usart_enable_tx_dma(usart);

    /* Make sure stream is disabled to start. */
    DMA_SCR(dma, stream) &= ~DMA_SxCR_EN;

    /* Configure the DMA controller. */
    DMA_SCR(dma, stream) = 0;
    DMA_SCR(dma, stream) =
        /* Error interrupts. */
        DMA_SxCR_DMEIE | DMA_SxCR_TEIE |
        /* Transfer complete interrupt. */
        DMA_SxCR_TCIE |
        DMA_SxCR_DIR_MEM_TO_PERIPHERAL |
        /* Increment the memory address after each transfer. */
        DMA_SxCR_MINC |
        /* 4 bytes written to the FIFO from memory at a time */
        DMA_SxCR_MBURST_INCR4 |
        /* 8 bit transfers from USART peripheral. */
        DMA_SxCR_PSIZE_8BIT |
        /* and to memory. */
        DMA_SxCR_MSIZE_8BIT |
        /* TODO: what priority level is necessary? */
        /* Very high priority. */
        DMA_SxCR_PL_VERY_HIGH |
        /* The channel selects which request line will trigger a transfer.
         * (see CD00225773.pdf Table 23). */
        DMA_SxCR_CHSEL(channel);

    /* For now, don't transfer any number of datas
     * (will be set in the initiating function). */
    DMA_SNDTR(dma, stream) = 0;

    /* DMA into the USART data register... */
    DMA_SPAR(dma, stream) = &USART_DR(usart);
    /* ...from the TX buffer. */
    DMA_SM0AR(dma, stream) = s->buff;

    /* TODO: Investigate more about the best FIFO settings. */
    DMA_SFCR(dma, stream) =
        DMA_SxFCR_DMDIS |         /* Enable DMA stream FIFO. */
        DMA_SxFCR_FTH_2_4_FULL |  /* Trigger level 2/4 full. */
        DMA_SxFCR_FEIE;           /* Enable FIFO error interrupt. */

    s->wr = s->rd = 0;  /* Buffer is empty to begin with. */

    /* Enable DMA interrupts for this stream with the NVIC. */
    if (dma == DMA1)
        nvicEnableVector(dma_irq_lookup[0][stream],
                         CORTEX_PRIORITY_MASK(USART_DMA_ISR_PRIORITY));
    else if (dma == DMA2)
        nvicEnableVector(dma_irq_lookup[1][stream],
                         CORTEX_PRIORITY_MASK(USART_DMA_ISR_PRIORITY));
}