0%

调试技巧

  1. 上电后(或初始化完成后)点亮一枚LED可判断上述过程是否有误(复位或初始化代码问题排查),运行main函数的死循环时让LED闪烁可以判断系统此时运行状况(有效判断操作执行是否异常)
  2. 完成前期模块测试后先使用模拟器检查软件运行是否正确,后再烧写上机调试
  3. 通过对某个GPIO引脚产生逻辑电平作为调试信号,辅之以示波器可以调试某些对时序性较高的过程代码
  4. Keil的调试技巧(内存读写断点,条件/次数断点,运行时在断点用Command输出字符)

优化提示

  1. 在本机仿真或用某些调试器时可能有Profiler工具查看执行时间与调用次数,方便确定优化目标
  2. 在开发阶段务必将编译器优化关掉,因为某些编译器优化会使代码执行结果异常(必要时使用volatile变量)
  3. 使用查询表(函数指针的数列)代替switch,化判断为寻址
  4. 使用全局变量来传入参数(但程序模块化下降),特别是浮点数等较大的数据类型;使用register修饰变量可针对频繁读取的变量优化
  5. 使用内联函数优化某些微小的函数,降低堆栈传参带来的额外开销
  6. 适配堆栈大小,使程序在正常运行的情况下不浪费内存(但注意堆栈溢出会带来致命的后果)
    做法:在函数内定义变量如int a[n];并赋一个特殊值,调整n的大小直到程序完整运行的时候崩溃(崩溃后应该进行跟踪),以此估算所需堆栈大小
    减小堆栈大小:避免递归算法,减小局部变量的大小,内存对齐问题
  7. 避免浮点运算或用硬件指令代替;手动写汇编

可靠性改进

阅读全文 »

现象:使用CubeMX多次Generate Code发现串口初始化出现问题,DMA的CR寄存器除了中断位和使能位其他配置未能写入。调试时发现似乎写入寄存器CR时无效。此问题在仿真情况下不会发生

img

原因:在先配置UART后Generate Code回头再修改DMA配置,第二次Generate Code后会出现该问题。MX_DMA_Init()初始化函数中负责启动DMA2的时钟,而UART初始化里面也包含了部分DMA2的初始化配置。观察例程可判断正确顺序应该是先MX_DMA_Init()再MX_USART1_UART_Init(),但是在这种情况下,CubeMX的MX_USART1_UART_Init()和MX_DMA_Init()的顺序就会按照Generate Code的顺序。个人推测根本原因应该是在这种顺序下,DMA的时钟未启动而提前写入配置导致配置丢失。参见这篇文章

解决方案:一定可行的办法是一次配置重建整个项目。在不推倒重来的前提下,可以在CubeMX中取消勾选UART和DMA,然后Generate Code,再按照原先配置勾选UART和DMA然后再Generate Code即可。或者暴力修改.ioc文件中的ProjectManager.functionlistsort,调换UART和DMA的顺序。在Project Manager下的Advanced Setting里面可以看到顺序。

现象:打开调试/仿真Command窗口出现“*** error 65: access violation at 0x40021000 : no ‘read’ permission”,程序停在了system_stm32f10x.c中的一行

原因:该仿真器对只保证CMSIS兼容性,并没有对STM32进行专门配置

解决方案:修改仿真器/调试器加载的DLL,如图

img