Implement DMA for USART1 reception and update FreeRTOS configuration

- Modified shell_port.c to replace interrupt-based UART reception with DMA.
- Introduced a DMA buffer for UART data and adjusted the shell buffer handling.
- Added idle interrupt handling to process incoming data from the DMA buffer.
- Updated freertos_f407.ioc to configure DMA for USART1 RX and TX.
- Enabled necessary NVIC interrupts for DMA streams associated with USART1.
This commit is contained in:
xushenghao 2025-09-10 00:48:06 +08:00
parent 9f37c7d763
commit 21e9d75e40
7 changed files with 5262 additions and 5097 deletions

View File

@ -54,9 +54,11 @@ void UsageFault_Handler(void);
void DebugMon_Handler(void);
void USART1_IRQHandler(void);
void TIM6_DAC_IRQHandler(void);
void DMA2_Stream2_IRQHandler(void);
void DMA2_Stream3_IRQHandler(void);
void OTG_FS_IRQHandler(void);
void DMA2_Stream6_IRQHandler(void);
void DMA2_Stream7_IRQHandler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */

View File

@ -43,12 +43,18 @@ void MX_DMA_Init(void)
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
/* DMA2_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 15, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
/* DMA2_Stream6_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 15, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
/* DMA2_Stream7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
}

View File

@ -58,6 +58,8 @@
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
extern DMA_HandleTypeDef hdma_sdio_rx;
extern DMA_HandleTypeDef hdma_sdio_tx;
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart1_tx;
extern UART_HandleTypeDef huart1;
extern TIM_HandleTypeDef htim6;
@ -169,7 +171,13 @@ void DebugMon_Handler(void)
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
// 璉?<3F>亦征<E4BAA6>脖葉<E88496><EFBFBD>敹?
if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
extern void shell_uart_rx_idle_callback(void);
shell_uart_rx_idle_callback();
}
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
@ -191,6 +199,20 @@ void TIM6_DAC_IRQHandler(void)
/* USER CODE END TIM6_DAC_IRQn 1 */
}
/**
* @brief This function handles DMA2 stream2 global interrupt.
*/
void DMA2_Stream2_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream2_IRQn 0 */
/* USER CODE END DMA2_Stream2_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_usart1_rx);
/* USER CODE BEGIN DMA2_Stream2_IRQn 1 */
/* USER CODE END DMA2_Stream2_IRQn 1 */
}
/**
* @brief This function handles DMA2 stream3 global interrupt.
*/
@ -231,6 +253,20 @@ void DMA2_Stream6_IRQHandler(void)
/* USER CODE END DMA2_Stream6_IRQn 1 */
}
/**
* @brief This function handles DMA2 stream7 global interrupt.
*/
void DMA2_Stream7_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream7_IRQn 0 */
/* USER CODE END DMA2_Stream7_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_usart1_tx);
/* USER CODE BEGIN DMA2_Stream7_IRQn 1 */
/* USER CODE END DMA2_Stream7_IRQn 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@ -25,6 +25,8 @@
/* USER CODE END 0 */
UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart1_tx;
/* USART1 init function */
@ -80,6 +82,43 @@ void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART1 DMA Init */
/* USART1_RX Init */
hdma_usart1_rx.Instance = DMA2_Stream2;
hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart1_rx.Init.Mode = DMA_NORMAL;
hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);
/* USART1_TX Init */
hdma_usart1_tx.Instance = DMA2_Stream7;
hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;
hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart1_tx.Init.Mode = DMA_NORMAL;
hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
@ -106,6 +145,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USART1 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmarx);
HAL_DMA_DeInit(uartHandle->hdmatx);
/* USART1 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspDeInit 1 */

File diff suppressed because it is too large Load Diff

View File

@ -17,12 +17,14 @@ char shellBuffer[512];
static SemaphoreHandle_t shellMutex;
// 串口接收缓冲区(环形队列)
// DMA接收缓冲区和shell环形缓冲区
#define SHELL_UART_DMA_BUF_SIZE 256
#define SHELL_UART_RX_BUF_SIZE 128
static uint8_t shell_uart_dma_buf[SHELL_UART_DMA_BUF_SIZE];
static uint8_t shell_uart_rx_buf[SHELL_UART_RX_BUF_SIZE];
static volatile uint16_t shell_uart_rx_head = 0;
static volatile uint16_t shell_uart_rx_tail = 0;
static uint8_t shell_uart_rx_temp;
static volatile uint16_t shell_uart_dma_last_pos = 0;
/**
* @brief shell写
@ -106,8 +108,10 @@ void userShellInit(void)
shell.unlock = userShellUnlock;
shellInit(&shell, shellBuffer, 512);
// 启动串口中断接收
HAL_UART_Receive_IT(&huart1, &shell_uart_rx_temp, 1);
// 启动DMA接收
HAL_UART_Receive_DMA(&huart1, shell_uart_dma_buf, SHELL_UART_DMA_BUF_SIZE);
// 使能空闲中断
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
xTaskCreate((TaskFunction_t)shellTask, // 任务入口函数
(const char *)"shell_task", // 任务名字
@ -117,19 +121,21 @@ void userShellInit(void)
NULL); // 任务句柄
}
// 串口接收完成回调(在 usart.c 里实现也可
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
// USART1 空闲中断处理DMA新数据转入shell缓冲区
void shell_uart_rx_idle_callback(void)
{
if (huart->Instance == USART1)
uint16_t dma_pos = SHELL_UART_DMA_BUF_SIZE - __HAL_DMA_GET_COUNTER(huart1.hdmarx);
uint16_t data_len = (dma_pos >= shell_uart_dma_last_pos) ? (dma_pos - shell_uart_dma_last_pos) : (SHELL_UART_DMA_BUF_SIZE - shell_uart_dma_last_pos + dma_pos);
for (uint16_t i = 0; i < data_len; i++)
{
uint8_t ch = shell_uart_dma_buf[(shell_uart_dma_last_pos + i) % SHELL_UART_DMA_BUF_SIZE];
uint16_t next = (shell_uart_rx_head + 1) % SHELL_UART_RX_BUF_SIZE;
if (next != shell_uart_rx_tail)
{
shell_uart_rx_buf[shell_uart_rx_head] = shell_uart_rx_temp;
shell_uart_rx_buf[shell_uart_rx_head] = ch;
shell_uart_rx_head = next;
}
// 继续接收下一个字节
HAL_UART_Receive_IT(&huart1, &shell_uart_rx_temp, 1);
}
shell_uart_dma_last_pos = dma_pos;
}
// CEVENT_EXPORT(EVENT_INIT_STAGE2, userShellInit);

View File

@ -4,7 +4,9 @@ CAD.pinconfig=
CAD.provider=
Dma.Request0=SDIO_RX
Dma.Request1=SDIO_TX
Dma.RequestsNb=2
Dma.Request2=USART1_RX
Dma.Request3=USART1_TX
Dma.RequestsNb=4
Dma.SDIO_RX.0.Direction=DMA_PERIPH_TO_MEMORY
Dma.SDIO_RX.0.FIFOMode=DMA_FIFOMODE_ENABLE
Dma.SDIO_RX.0.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL
@ -31,6 +33,26 @@ Dma.SDIO_TX.1.PeriphDataAlignment=DMA_PDATAALIGN_WORD
Dma.SDIO_TX.1.PeriphInc=DMA_PINC_DISABLE
Dma.SDIO_TX.1.Priority=DMA_PRIORITY_LOW
Dma.SDIO_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,FIFOThreshold,MemBurst,PeriphBurst
Dma.USART1_RX.2.Direction=DMA_PERIPH_TO_MEMORY
Dma.USART1_RX.2.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.USART1_RX.2.Instance=DMA2_Stream2
Dma.USART1_RX.2.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.USART1_RX.2.MemInc=DMA_MINC_ENABLE
Dma.USART1_RX.2.Mode=DMA_NORMAL
Dma.USART1_RX.2.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.USART1_RX.2.PeriphInc=DMA_PINC_DISABLE
Dma.USART1_RX.2.Priority=DMA_PRIORITY_LOW
Dma.USART1_RX.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
Dma.USART1_TX.3.Direction=DMA_MEMORY_TO_PERIPH
Dma.USART1_TX.3.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.USART1_TX.3.Instance=DMA2_Stream7
Dma.USART1_TX.3.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.USART1_TX.3.MemInc=DMA_MINC_ENABLE
Dma.USART1_TX.3.Mode=DMA_NORMAL
Dma.USART1_TX.3.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.USART1_TX.3.PeriphInc=DMA_PINC_DISABLE
Dma.USART1_TX.3.Priority=DMA_PRIORITY_LOW
Dma.USART1_TX.3.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
FATFS.BSP.number=1
FATFS.IPParameters=_CODE_PAGE,_USE_LFN,_VOLUMES
FATFS._CODE_PAGE=936
@ -105,8 +127,10 @@ Mcu.UserName=STM32F407ZGTx
MxCube.Version=6.9.2
MxDb.Version=DB.6.0.92
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
NVIC.DMA2_Stream2_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
NVIC.DMA2_Stream3_IRQn=true\:15\:0\:true\:false\:true\:true\:false\:true\:true
NVIC.DMA2_Stream6_IRQn=true\:15\:0\:true\:false\:true\:true\:false\:true\:true
NVIC.DMA2_Stream7_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
NVIC.ForceEnableDMAVector=true
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false