Я пытался какое-то время передать блок данных с моего компьютера на STM32L100C-DISCO
по USART. По соображениям производительности это должно быть сделано с использованием DMA. Однако пока мне не удалось заставить его работать. Поскольку я не могу понять, что я могу делать неправильно, я решил, что спрошу здесь.Прямой доступ к памяти RX для STM32L1
Я использую libopencm3, но, к сожалению, их отличное отличное repository of examples не содержит одного для DMA на STM32L1xxx
. Я проверил, что я рассмотрел все базы, когда дело доходит до параметров конфигурации, доступных в common DMA header file.
Естественно, я сослался на справочное руководство по STM32L1xxx, в которой говорится следующее запросов таблицу DMA1, что приводит меня верить канал 6 является то, что мне нужно использовать ..
Поскольку я не был уверен в размерах памяти и периферии (например, USART2), я варьировался во всех комбинациях 8, 16 и 32 бит для обоих, но безрезультатно.
Без дальнейших церемоний; это минимальный рабочий (ну, а не рабочий ...) отрывок из того, что я пытаюсь сделать. Мне кажется, что я пропускаю что-то в конфигурации DMA, поскольку сам USART отлично работает.
На данный момент все оценивается.
Идея этого кода в основном заключается в том, чтобы зацикливаться навсегда, пока данные в буфере не будут полностью заменены, а затем, когда это будет, вывести его. От хоста я отправляю килобайт высоко узнаваемых данных, но все, что я получаю, - это искаженный мусор. Это что-то пишут, но не то, что я намереваюсь написать.
EDIT: Вот изображение карты памяти. USART2_BASE
оценивает 0x4000 4400
, так что, похоже, все в порядке.
#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;
for (i = 0; i < 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;
for (i = 0; i < buflength; i++) {
if (buffer[i] == 65) {
flag = 1;
}
}
}
usart_disable_rx_dma(USART2);
for (i = 0; i < buflength; i++) {
usart_send_blocking(USART2, buffer[i]);
}
usart_send_blocking(USART2, '\n');
return 0;
}
Просто идея: не решение, но если вы можете указать время прохождения RX и посмотреть, совместимо ли это с скоростью передачи (минимум 0,08 секунды), которая может показать, что неправильное событие вызывает DMA (один предполагает скорость передачи данных верна, так как у вас есть работа, отличная от DMA). –
Я не уверен, что полностью понимаю, что вы имели в виду, но я попытался снизить скорость передачи до 9600 с обеих сторон, и это не помогло решить проблему (или представить мне значимый результат). Вызовы 'usart_send_blocking' и' usart_recv_blocking' действительно работают очень хорошо. – Joost
Добавить; 9600 был выбран с ошибкой на стороне осторожности - я понял, что это будет безопасная нижняя граница. – Joost