microcontroller - Direct memory access RX for the STM32L1 -
i've been trying while transmit block of data computer stm32l100c-disco
on usart. performance reasons, done using dma. far, however, have not been able work. cannot seem figure out might doing wrong, figured i'd ask here.
i'm using libopencm3, unfortunately, otherwise excellent repository of examples not appear contain 1 dma on stm32l1xxx
. checked covered bases when comes configuration options available in common dma header file, though.
naturally, i've referred reference manual stm32l1xxx, mentions following requests table dma1, leading me believe channel 6 need using..
as unsure size of memory , peripheral (i.e. usart2), varied across combinations of 8, 16 , 32 bit both, no avail.
without further ado; minimal working (well, not working..) excerpt of i'm trying do. feel i'm overlooking in dma configuration, usart works fine.
at point, appreciated.
the idea behind code loop forever until data in buffer replaced entirely, , when is, output it. host, i'm sending kilobyte of highly recognisable data, i'm getting malformed garbage. is writing something, not intend write.
edit: here's picture of memory map. usart2_base
evaluates 0x4000 4400
, seems right well.
#include <libopencm3/stm32/rcc.h> #include <libopencm3/stm32/gpio.h> #include "libopencm3/stm32/usart.h" #include <libopencm3/stm32/dma.h> const int buflength = 1024; uint8_t buffer[1024]; static void clock_setup(void) { rcc_clock_setup_pll(&clock_config[clock_vrange1_hsi_pll_32mhz]); rcc_peripheral_enable_clock(&rcc_ahbenr, rcc_ahbenr_gpioaen); rcc_peripheral_enable_clock(&rcc_apb1enr, rcc_apb1enr_usart2en); rcc_periph_clock_enable(rcc_dma1); } static void gpio_setup(void) { gpio_mode_setup(gpioa, gpio_mode_af, gpio_pupd_none, gpio3); gpio_mode_setup(gpioa, gpio_mode_af, gpio_pupd_none, gpio2); gpio_set_af(gpioa, gpio_af7, gpio3); gpio_set_af(gpioa, gpio_af7, gpio2); } static void usart_setup(void) { usart_set_baudrate(usart2, 115200); usart_set_databits(usart2, 8); usart_set_stopbits(usart2, usart_stopbits_1); usart_set_mode(usart2, usart_mode_tx_rx); usart_set_parity(usart2, usart_parity_none); usart_set_flow_control(usart2, usart_flowcontrol_none); usart_enable(usart2); } static void dma_setup(void) { dma_channel_reset(dma1, dma_channel6); dma_set_priority(dma1, dma_channel6, dma_ccr_pl_very_high); dma_set_memory_size(dma1, dma_channel6, dma_ccr_msize_8bit); dma_set_peripheral_size(dma1, dma_channel6, dma_ccr_psize_8bit); dma_enable_memory_increment_mode(dma1, dma_channel6); dma_disable_peripheral_increment_mode(dma1, dma_channel6); dma_enable_circular_mode(dma1, dma_channel6); dma_set_read_from_peripheral(dma1, dma_channel6); dma_disable_transfer_error_interrupt(dma1, dma_channel6); dma_disable_half_transfer_interrupt(dma1, dma_channel6); dma_disable_transfer_complete_interrupt(dma1, dma_channel6); dma_set_peripheral_address(dma1, dma_channel6, (uint32_t) usart2_base); dma_set_memory_address(dma1, dma_channel6, (uint32_t) buffer); dma_set_number_of_data(dma1, dma_channel6, buflength); dma_enable_channel(dma1, dma_channel6); } int main(void) { int i; (i = 0; < buflength; i++) { buffer[i] = 65; } clock_setup(); gpio_setup(); usart_setup(); dma_setup(); usart_enable_rx_dma(usart2); char flag = 1; while (flag) { flag = 0; (i = 0; < buflength; i++) { if (buffer[i] == 65) { flag = 1; } } } usart_disable_rx_dma(usart2); (i = 0; < buflength; i++) { usart_send_blocking(usart2, buffer[i]); } usart_send_blocking(usart2, '\n'); return 0; }
i not familiar libopencm3 or stm32l series, familiar stm32f series. know there differences in peripherals, believe mistake lies in following line:
dma_set_peripheral_address(dma1, dma_channel6, (uint32_t) usart2_base);
here setting dma peripheral address usart2_base
address, typically, want set usart2 data register, may not right @ usart2_base
.
i see of comments on question have pointed out, there still remaining question of how indicate data register. st peripheral library, there memory mapped structures peripherals. appears libopencm3 has defined macro can use data register address: usart2_dr
. here definition in documentation
so, believe if change line above following, may solve problem:
dma_set_peripheral_address(dma1, dma_channel6, (uint32_t) usart2_dr);
Comments
Post a Comment