STM32使用HAL库移植系统时的一个特别注意点

https://mp.weixin.qq.com/s/RnhyBrzudkxultsm37yBGg

相信使用过HAL库的同学都应该接触过HAL_Delay();及HAL_GetTick();等等函数,其定义在stm32f0xx_hal.c文件中(见图1,这里以STM32F0系列为例,其它只是名字不一样,例如:F1、F4),从注释得知,其时基为1ms,可在用户文件中重新实现此函数,HAL_IncTick();函数在stm32f0xx_it.c文件的SysTick_Handler();函数中被调用,正是这里让uwTick全局变量以固定的周期执行加1操作,相当于赋予了心跳,我们使用前面提到的那些接口函数也才有了意义,在裸机编程中我们可以很方便使用这些接口来达到延时或者处理超时的异常情况,我们在工程中搜索一下HAL_GetTick可以看到整个工程中非常多的地方都使用了这个函数,而且大部分都在HAL库的代码中,下图2是我截取的异步串口库文件调用此接口的部分搜索结果。

图片

图1

图片

图2

那这个有什么需要注意的地方呢,在裸机编程中我们完全不用担心,可以大胆使用,但是一旦你移植了操作系统,那么移植的时候就需要注意了,说不定你平时用得很好的程序在某些时候就不正常了,而且还特别不好定位出问题的地方,问题的大致现象就是程序表现为假死,能响应中断,所有任务表现为停止运行的状态。

下面我们就来分析为什么会出现这样的问题(以异步串口为例),在stm32f0xx_hal_uart.c文件中找到HAL_UART_Transmit();函数,可以看到此函数中先调用了HAL_GetTick();获取当前的tick值,然后调用UART_WaitOnFlagUntilTimeout();处理超时的异常情况(见图3),我们进入这个函数,函数的功能就是在while循环中不断的读取发送缓冲区空的标志,如果在给定的时间内还未发送完成则认为发送超时,执行清理操作然后退出循环(见图4),假设不考虑while循环本身的条件不满足(条件为假),从框选的代码可以看出只有在超时时间为0,或者超时时间到了才会退出循环,假设我们设定了超时时间,那么条件就变成只有超时时间到了才会退出循环,在移植操作系统时往往会忽略HAL_IncTick();函数的移植,如果忽略了此函数的移植,那么关于此函数相关的其它接口也就没有了意义,失去心跳后uwTick变量的值永远为0,那么我们通过HAL_GetTick();获取的值也就永远为0,超时条件永远不会满足,循环退出的唯一条件就变成while循环本身的条件不满足而退出,正常情况下发送数据是肯定没有问题的,发送缓冲区总有空的时候,这时while循环退出,但异常情况呢,如果读取的发送缓冲区空标志位始终为假,那么while永远不会退出,就出现了前面说的异常情况,不出现还好,一旦出现连BUG复现都是非常困难的,而且使用中断和DMA方式不会出现这个问题,所以排查很困难。

图片

图3

图片

图4

总结:在有操作系统的应用中,没有移植HAL_IncTick();函数时,千万不要调用其相关的接口函数,不会百分之百出错,但是百分之百是个错!就算移植了,也最好重写相关函数,比如延时函数用系统的延时函数替代(freeRTOS有对应的函数接口可以一一替换,其它的不知道,没有的话自己实现就行了),否则你会发现你的程序实时性很难提高,要么就多用中断和DMA吧。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值