STM32 Shell问题:DMA回调异常引发系统冻结的排查
STM32 Shell集成中的按键处理与DMA冻结问题
问题背景
我在STM32项目中集成Shell功能,基于STM_Shell库及对应教程完成初始实现。原方案中,shell_get_char()通过HAL_UART_Receive_IT接收单字节,HAL_UART_RxCpltCallback()直接调用shell_in()处理输入,但无法识别由3字节组成的箭头键。
为解决箭头键识别问题,我改用环形缓冲方案:让HAL_UART_RxCpltCallback()将接收字符存入环形缓冲,同时重写shell_get_byte()触发HAL接收中断,并从环形缓冲读取数据传入shell_in()。
重写后的核心代码
void shell_get_byte(char *c){ //Check that huart1 is ready to accept data if (HAL_UART_GetState(&huart1) == HAL_UART_STATE_READY){ //Enable the UART interrupt HAL_UART_Receive_IT(&huart1, (uint8_t *) c, 1); } if (rgbuffer_empty_c(&rgbuffer) == 0){ //HAL_UART_AbortReceive_IT(&huart1); shell_in(rgbuffer_read_c(&rgbuffer)); } } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ //Verify the uart used if(huart->Instance == USART1){ //Write to ring buffer rgbuffer_write_c(&rgbuffer, shell_state.c); HAL_UART_Receive_IT(&huart1, (uint8_t *) &shell_state.c, 1); } }
异常现象
- 仅按Enter键时,系统可正常换行并显示"/STM32"提示符;
- 按任意键可正常回显,但按Enter键后系统冻结。
当取消shell_in()中以下代码的注释后:
while (shell_state.busy != 0); // Don't echo unless the interface is ready (this may be unnecessary here)
异常变为:按任意键回显后系统立即冻结,仅Enter键操作正常。
排查过程
由此怀疑shell_state.busy在shell_out()的DMA调用后未被HAL_UART_TxCpltCallback()正确清除。我通过GPIO引脚验证了shell_out()和HAL_UART_TxCpltCallback()均被触发,但仍无法定位shell_state.busy被异常设置的位置。相关shell_out()及回调代码如下:
void shell_out(char* buff, int length){ HAL_UART_Transmit_DMA(&huart1, (uint8_t *) buff, length); //HAL_UART_Transmit_IT(&huart1, (uint8_t *) buff , length); shell_state.busy = 1; //DMA Transfer in progress } void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){ //Verify which USART is being used if(huart->Instance == USART1){ //Transfer complete shell_state.busy = 0; } }
疑问
目前唯一的差异是shell_in()的调用路径:现在从shell_get_char()触发,而非原方案的HAL_UART_RxCpltCallback()直接调用,无法理解该差异为何会引发系统冻结问题。完整项目源码位于Core目录,Shell相关代码在STM_SHELL目录。
内容的提问来源于stack exchange,提问作者misguidedsquid
相关产品推荐
相关产品推荐

