You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32通过DMA读取ADC时导致FreeRTOS调度崩溃问题咨询

排查STM32 DMA+ADC+FreeRTOS导致HardFault的方向

1. 中断优先级配置冲突检查

  • 确认FreeRTOS的configMAX_SYSCALL_INTERRUPT_PRIORITY(或configKERNEL_INTERRUPT_PRIORITY)设置,确保TIM6、ADC、DMA的中断优先级不低于这个值(STM32优先级数值越小优先级越高,FreeRTOS要求系统调用相关中断优先级不能高于该阈值,否则会破坏内核上下文)。
  • 检查TIM6(时基)、ADC、DMA的NVIC优先级分组是否一致,比如统一用4位抢占优先级+0位子优先级,避免分组混乱导致优先级计算错误。
  • 查看HAL库生成的NVIC配置代码,确保TIM6、ADC、DMA的抢占/子优先级设置无重叠或不合理情况,比如DMA优先级不能被低优先级任务打断后引发上下文错误。

2. TIM6时基与FreeRTOS SysTick冲突排查

  • 确认TIM6是否同时用作HAL库时基源(HAL_InitTick中配置)和其他用途?如果FreeRTOS用SysTick作为内核时钟,需确保TIM6的时基中断优先级不会干扰SysTick。
  • 检查HAL_TIM_Base_Start_IT(&htim6)这类启动TIM6中断的代码,是否在FreeRTOS启动后被错误调用,导致中断上下文与任务上下文冲突。
  • 尝试临时禁用TIM6时基(改用SysTick作为HAL时基),测试启动ADC_DMA是否仍触发HardFault,以此验证TIM6是否为冲突根源。

3. DMA与ADC配置合法性检查

  • 确认ADC的DMA请求映射正确:ADC1对应DMA1的哪个通道、ADC2对应哪个通道,避免配错通道引发硬件错误。
  • 检查DMA的内存地址合法性:传递给HAL_ADC_Start_DMA的目标数组必须是全局变量或静态变量,不能用栈上的局部变量(任务栈空间有限,且DMA访问栈地址可能因任务切换导致地址失效)。
  • 核对ADC配置:是否开启连续转换、扫描模式,DMA的传输方向、数据宽度(比如ADC是12位,DMA需对应半字传输)是否匹配;若同时使用ADC1和ADC2,双ADC模式及对应DMA配置是否正确。

4. HardFault现场调试定位

  • 进入HardFault后查看寄存器值:
    • 读取MSP(主栈指针)指向的内存,获取栈帧里的PC(程序计数器)和LR(链接寄存器)值,定位触发HardFault的具体代码行。
    • 检查CFSR(配置故障状态寄存器)的值,判断是总线故障、用法故障还是存储器故障:
      • 总线故障:大概率是DMA访问非法地址,或外设寄存器访问冲突。
      • 用法故障:可能是指令执行错误,比如对齐错误、未定义指令。
  • 在PendSV_Handler处打断点,查看进入PendSV前的调用栈,确认任务切换过程中哪个环节触发错误,是否与DMA/ADC中断抢占任务切换有关。

5. FreeRTOS任务栈与上下文检查

  • 检查ReadTask01的任务栈大小是否足够,启动ADC_DMA时若有局部变量或中断嵌套,可能导致栈溢出引发HardFault,可暂时调大任务栈大小测试。
  • 确保调用HAL_ADC_Start_DMA时,ADC和DMA外设处于未被占用状态,避免其他任务或中断同时操作ADC/DMA资源引发竞争。可使用FreeRTOS互斥锁保护ADC/DMA的操作。

内容的提问来源于stack exchange,提问作者Runzolf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 00:15:12