Add working dma example

This commit is contained in:
donghoonpark 2024-11-10 18:28:12 +09:00 committed by Valerio De Benedetto
parent a1ee35dca3
commit 3bf5ed37c8
4 changed files with 76 additions and 10 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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