diff --git a/STM32H723XG_FLASH.ld b/STM32H723XG_FLASH.ld index 05a611a..4ac8d60 100644 --- a/STM32H723XG_FLASH.ld +++ b/STM32H723XG_FLASH.ld @@ -241,7 +241,14 @@ SECTIONS . = ALIGN(8); } >DTCMRAM - + /* DMA-accessible buffers in RAM_D1 (SRAM). DTCM is not reachable by DMA */ + .dma_buf (NOLOAD) : + { + . = ALIGN(4); + *(.dma_buf) + *(.dma_buf*) + . = ALIGN(4); + } >RAM_D1 /* Remove information from the standard libraries */ /DISCARD/ : diff --git a/application/cmd/robot_cmd.c b/application/cmd/robot_cmd.c index 3a38266..cf8d182 100644 --- a/application/cmd/robot_cmd.c +++ b/application/cmd/robot_cmd.c @@ -228,7 +228,7 @@ void RobotCMDInit() PIDInit(&vision_pitch_pid, &pitch_vpid_config); VisionKalmanFilterInit(); - Vision_Uart_Init(&huart10); + Vision_Uart_Init(&huart1); laser_off(); } diff --git a/bsp/usart/bsp_usart.c b/bsp/usart/bsp_usart.c index ccefeb3..e27a942 100644 --- a/bsp/usart/bsp_usart.c +++ b/bsp/usart/bsp_usart.c @@ -10,9 +10,12 @@ */ #include "bsp_usart.h" #include "bsp_log.h" -#include "stdlib.h" #include "memory.h" +/* Static pool in RAM_D1 (.dma_buf section) for DMA-accessible USART instances. + DTCM is not reachable by DMA, so malloc'd instances would cause bus errors. */ +static USARTInstance usart_pool[DEVICE_USART_CNT] __attribute__((section(".dma_buf"))); + /* usart service instance, modules' info would be recoreded here using USARTRegister() */ /* usart服务实例,所有注册了usart的模块信息会被保存在这里 */ static uint8_t idx; @@ -28,7 +31,7 @@ static USARTInstance *usart_instance[DEVICE_USART_CNT] = {NULL}; */ void USARTServiceInit(USARTInstance *_instance) { - HAL_UARTEx_ReceiveToIdle_DMA(_instance->usart_handle, _instance->recv_buff, _instance->recv_buff_size); + HAL_UARTEx_ReceiveToIdle_DMA(_instance->usart_handle, _instance->recv_buff, USART_RXBUFF_LIMIT); // 关闭dma half transfer中断防止两次进入HAL_UARTEx_RxEventCallback() // 这是HAL库的一个设计失误,发生DMA传输完成/半完成以及串口IDLE中断都会触发HAL_UARTEx_RxEventCallback() // 我们只希望处理第一种和第三种情况,因此直接关闭DMA半传输中断 @@ -46,11 +49,10 @@ USARTInstance *USARTRegister(USART_Init_Config_s *init_config) while (1) LOGERROR("[bsp_usart] USART instance already registered!"); - USARTInstance *instance = (USARTInstance *)malloc(sizeof(USARTInstance)); + USARTInstance *instance = &usart_pool[idx]; memset(instance, 0, sizeof(USARTInstance)); instance->usart_handle = init_config->usart_handle; - instance->recv_buff_size = init_config->recv_buff_size; instance->module_callback = init_config->module_callback; usart_instance[idx++] = instance; @@ -102,17 +104,18 @@ uint8_t USARTIsReady(USARTInstance *_instance) void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { for (uint8_t i = 0; i < idx; ++i) - { // find the instance which is being handled + { if (huart == usart_instance[i]->usart_handle) - { // call the callback function if it is not NULL + { + usart_instance[i]->recv_buff_size = Size; // 实际接收到的数据量 if (usart_instance[i]->module_callback != NULL) { usart_instance[i]->module_callback(); - memset(usart_instance[i]->recv_buff, 0, Size); // 接收结束后清空buffer,对于变长数据是必要的 + memset(usart_instance[i]->recv_buff, 0, Size); } - HAL_UARTEx_ReceiveToIdle_DMA(usart_instance[i]->usart_handle, usart_instance[i]->recv_buff, usart_instance[i]->recv_buff_size); + HAL_UARTEx_ReceiveToIdle_DMA(usart_instance[i]->usart_handle, usart_instance[i]->recv_buff, USART_RXBUFF_LIMIT); __HAL_DMA_DISABLE_IT(usart_instance[i]->usart_handle->hdmarx, DMA_IT_HT); - return; // break the loop + return; } } } @@ -130,9 +133,19 @@ void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) { if (huart == usart_instance[i]->usart_handle) { - HAL_UARTEx_ReceiveToIdle_DMA(usart_instance[i]->usart_handle, usart_instance[i]->recv_buff, usart_instance[i]->recv_buff_size); + LOGWARNING("[bsp_usart] USART error callback, idx [%d], ErrorCode: 0x%02X", i, huart->ErrorCode); + + /* Flush RDR and clear error flags before restarting DMA */ + (void)READ_REG(huart->Instance->RDR); + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_FEF | UART_CLEAR_NEF | UART_CLEAR_PEF); + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Clear stale DMAR to avoid a residual DMA request triggering a + bus error when UART_Start_Receive_DMA re-enables the stream */ + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + HAL_UARTEx_ReceiveToIdle_DMA(usart_instance[i]->usart_handle, usart_instance[i]->recv_buff, USART_RXBUFF_LIMIT); __HAL_DMA_DISABLE_IT(usart_instance[i]->usart_handle->hdmarx, DMA_IT_HT); - LOGWARNING("[bsp_usart] USART error callback triggered, instance idx [%d]", i); return; } } diff --git a/bsp/usart/bsp_usart.h b/bsp/usart/bsp_usart.h index f8c5a43..ffeefe6 100644 --- a/bsp/usart/bsp_usart.h +++ b/bsp/usart/bsp_usart.h @@ -24,7 +24,7 @@ typedef enum typedef struct { uint8_t recv_buff[USART_RXBUFF_LIMIT]; // 预先定义的最大buff大小,如果太小请修改USART_RXBUFF_LIMIT - uint8_t recv_buff_size; // 模块接收一包数据的大小 + uint16_t recv_buff_size; // 实际接收到的数据量(由RxEventCallback赋值) UART_HandleTypeDef *usart_handle; // 实例对应的usart_handle usart_module_callback module_callback; // 解析收到的数据的回调函数 } USARTInstance; @@ -32,7 +32,6 @@ typedef struct /* usart 初始化配置结构体 */ typedef struct { - uint8_t recv_buff_size; // 模块接收一包数据的大小 UART_HandleTypeDef *usart_handle; // 实例对应的usart_handle usart_module_callback module_callback; // 解析收到的数据的回调函数 } USART_Init_Config_s; diff --git a/modules/bluetooth/HC05.c b/modules/bluetooth/HC05.c index 2d170d6..eadc530 100644 --- a/modules/bluetooth/HC05.c +++ b/modules/bluetooth/HC05.c @@ -33,7 +33,6 @@ HC05 *HC05Init(UART_HandleTypeDef *hc05_usart_handle) USART_Init_Config_s conf; conf.module_callback = HC05RxCallback; conf.usart_handle = hc05_usart_handle; - conf.recv_buff_size = HC05_BUFFERSIZE; hc05_usart_instance = USARTRegister(&conf); hc05_init_flag = 1; diff --git a/modules/master_machine/master_machine.c b/modules/master_machine/master_machine.c index 9a548b0..1a5ab46 100644 --- a/modules/master_machine/master_machine.c +++ b/modules/master_machine/master_machine.c @@ -80,7 +80,6 @@ void Vision_Uart_Init(UART_HandleTypeDef *_handle) { USART_Init_Config_s conf = { .module_callback = DecodeVision, - .recv_buff_size = 64, .usart_handle = _handle, }; cv_usart_instance = USARTRegister(&conf); diff --git a/modules/referee/rm_referee.c b/modules/referee/rm_referee.c index 2743d7d..4a9cc0e 100644 --- a/modules/referee/rm_referee.c +++ b/modules/referee/rm_referee.c @@ -125,7 +125,6 @@ referee_info_t *RefereeInit(UART_HandleTypeDef *referee_usart_handle) USART_Init_Config_s conf; conf.module_callback = RefereeRxCallback; conf.usart_handle = referee_usart_handle; - conf.recv_buff_size = RE_RX_BUFFER_SIZE; // mx 255(u8) referee_usart_instance = USARTRegister(&conf); Daemon_Init_Config_s daemon_conf = { diff --git a/modules/remote/remote_control.c b/modules/remote/remote_control.c index e45f03d..b2197c9 100644 --- a/modules/remote/remote_control.c +++ b/modules/remote/remote_control.c @@ -229,7 +229,6 @@ RC_ctrl_t *RemoteControlInit(UART_HandleTypeDef *rc_usart_handle) USART_Init_Config_s conf; conf.module_callback = RemoteControlRxCallback; conf.usart_handle = rc_usart_handle; - conf.recv_buff_size = REMOTE_CONTROL_FRAME_SIZE; rc_usart_instance = USARTRegister(&conf); // 进行守护进程的注册,用于定时检查遥控器是否正常工作 diff --git a/modules/timachine/board_comm.c b/modules/timachine/board_comm.c index 549de5b..eafccde 100644 --- a/modules/timachine/board_comm.c +++ b/modules/timachine/board_comm.c @@ -59,7 +59,6 @@ board_comm_data_t* BoardCommInit(UART_HandleTypeDef *uart_handle) USART_Init_Config_s conf; conf.module_callback = BoardCommRxCallback; conf.usart_handle = uart_handle; - conf.recv_buff_size = BOARD_COMM_FRAME_SIZE; board_comm_usart_instance = USARTRegister(&conf); // 暂时注释掉 daemon 注册,专注于数据传输