From 3bf5ed37c8cd9aeaa6bd98f8ed1cecad4ef9b9f6 Mon Sep 17 00:00:00 2001 From: donghoonpark Date: Sun, 10 Nov 2024 18:28:12 +0900 Subject: [PATCH] Add working dma example --- examples/stm32/bsp/blackpill/blackpill.c | 15 +++++++ examples/stm32/nmbs/port.c | 51 ++++++++++++++++++++++++ examples/stm32/nmbs/port.h | 5 ++- examples/stm32/readme.md | 15 ++++--- 4 files changed, 76 insertions(+), 10 deletions(-) diff --git a/examples/stm32/bsp/blackpill/blackpill.c b/examples/stm32/bsp/blackpill/blackpill.c index f2fadf7..e727dc8 100644 --- a/examples/stm32/bsp/blackpill/blackpill.c +++ b/examples/stm32/bsp/blackpill/blackpill.c @@ -194,6 +194,11 @@ static void MX_USART1_UART_Init(void) Error_Handler(); } + // Enable USART1 interrupt + // It must higher or equal than 5 + HAL_NVIC_SetPriority(USART1_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(USART1_IRQn); + // USART1 Pin configuration: TX (PA9), RX (PA10) GPIO_InitTypeDef GPIO_InitStruct = {0}; @@ -207,6 +212,8 @@ static void MX_USART1_UART_Init(void) GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + } static void MX_SPI1_Init(void) @@ -321,12 +328,15 @@ static void MX_DMA_Init(void) hdma_usart1_rx.Init.Mode = DMA_NORMAL; hdma_usart1_rx.Init.Priority = DMA_PRIORITY_HIGH; hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK) { // Initialization error handling Error_Handler(); } + __HAL_LINKDMA(&huart1, hdmarx, hdma_usart1_rx); + // DMA2_Stream3 (SPI1_TX) Interrupt Configuration HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); @@ -369,3 +379,8 @@ void DMA2_Stream2_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_usart1_rx); } + +void USART1_IRQHandler(void) +{ + HAL_UART_IRQHandler(&huart1); +} diff --git a/examples/stm32/nmbs/port.c b/examples/stm32/nmbs/port.c index 15e0fe0..842a173 100644 --- a/examples/stm32/nmbs/port.c +++ b/examples/stm32/nmbs/port.c @@ -9,6 +9,13 @@ static int32_t write_socket(const uint8_t* buf, uint16_t count, int32_t byte_tim #ifdef NMBS_RTU static int32_t read_serial(uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg); static int32_t write_serial(const uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg); + +#if MB_UART_DMA +#include "queue.h" +xQueueHandle rtu_rx_q; +uint8_t rtu_rx_b[MB_RX_BUF_SIZE]; +#endif + #endif static nmbs_server_t* server; @@ -47,6 +54,11 @@ nmbs_error nmbs_server_init(nmbs_t* nmbs, nmbs_server_t* _server) cb.write_single_register = server_write_single_register; cb.write_multiple_registers = server_write_multiple_registers; +#if MB_UART_DMA + rtu_rx_q = xQueueCreate(MB_RX_BUF_SIZE, sizeof(uint8_t)); + HAL_UARTEx_ReceiveToIdle_DMA(&MB_UART, rtu_rx_b, MB_RX_BUF_SIZE); +#endif + nmbs_error status = nmbs_server_create(nmbs, server->id, &conf, &cb); if(status != NMBS_ERROR_NONE) { @@ -202,6 +214,21 @@ int32_t write_socket(const uint8_t *buf, uint16_t count, int32_t byte_timeout_ms #ifdef NMBS_RTU static int32_t read_serial(uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg) { +#if MB_UART_DMA + uint32_t tick_start = HAL_GetTick(); + while(uxQueueMessagesWaiting(rtu_rx_q) < count) + { + if(HAL_GetTick() - tick_start >= (uint32_t)byte_timeout_ms) + { + return 0; + } + } + for(int i = 0; i < count; i++) + { + xQueueReceive(rtu_rx_q, buf + i, 1); + } + return count; +#else HAL_StatusTypeDef status = HAL_UART_Receive(&MB_UART, buf, count, byte_timeout_ms); if(status == HAL_OK) { @@ -211,9 +238,13 @@ static int32_t read_serial(uint8_t* buf, uint16_t count, int32_t byte_timeout_ms { return 0; } +#endif } static int32_t write_serial(const uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg) { +#if MB_UART_DMA + HAL_UART_Transmit_DMA(&MB_UART, buf, count); +#else HAL_StatusTypeDef status = HAL_UART_Transmit(&MB_UART, buf, count, byte_timeout_ms); if(status == HAL_OK) { @@ -223,5 +254,25 @@ static int32_t write_serial(const uint8_t* buf, uint16_t count, int32_t byte_tim { return 0; } +#endif } + + +#if MB_UART_DMA +void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + if(huart == &MB_UART) + { + for(int i = 0; i < Size; i++) + { + xQueueSendFromISR(rtu_rx_q, rtu_rx_b + i, &xHigherPriorityTaskWoken); + } + HAL_UARTEx_ReceiveToIdle_DMA(huart, rtu_rx_b, MB_RX_BUF_SIZE); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } + // You may add your additional uart handler below +} +#endif + #endif \ No newline at end of file diff --git a/examples/stm32/nmbs/port.h b/examples/stm32/nmbs/port.h index ca80e23..1495382 100644 --- a/examples/stm32/nmbs/port.h +++ b/examples/stm32/nmbs/port.h @@ -21,8 +21,9 @@ extern "C" { #ifdef NMBS_RTU // modbus rtu -#define MB_UART huart1 -#define RX_BUF_SIZE 256 +#define MB_UART huart1 +#define MB_UART_DMA 1 +#define MB_RX_BUF_SIZE 256 extern UART_HandleTypeDef MB_UART; #endif diff --git a/examples/stm32/readme.md b/examples/stm32/readme.md index fb8a3ec..b3523be 100644 --- a/examples/stm32/readme.md +++ b/examples/stm32/readme.md @@ -6,15 +6,19 @@ - Blackpill board - STM32F401CCUx -- USART1 with DMA +- USART1 (with/without) DMA - PA9 : TX1 - PA10 : RX1 +- SPI1 with DMA (connected to W5500) + - PB3 : SCK1 + - PB4 : MISO1 + - PB5 : MOSI1 + - PA15 : NSS (Software select) ## Toolchain and environment -Tested on Mac OS Sonoma(Apple Silicon M1) but other os having same toolchain should have no problem. +Tested on Mac OS Sonoma(Apple Silicon) & Windows 10 but other os having same toolchain should have no problem. -- STM32CubeMX 6.11.1 - arm-none-eabi-gcc - cmake - ninja @@ -23,8 +27,3 @@ Tested on Mac OS Sonoma(Apple Silicon M1) but other os having same toolchain sho - CMake - cortex-debug -## How to run - -1. Generate driver code from stm32f401ccux.ioc using STM32CubeMX -2. Configure with CMake -3. Launch with elf file or flash it