子函数多层调用的主要注意事项分析

描述

应用方案设计中,开发者经常会碰到某个子函数需要多次多级调用的情况。程序执行过程中有可能打断本该顺序执行的指令转而跨层执行其他层级指令的情况,为了说明方便,将主循环程序作为一层,不同的中断服务程序各自为一层。

一、现象描述

keil编译器编译code后,经常会遇到如下warning:[*** WARNING L15:MULTIPLE CALL TO SEGMENT ],碰到此warning就是编译器提醒开发者,不同层级出现调用同一子函数的情况,或者主循环与中断服务中都有调用,或者不同中断服务程序中都有调用。

二、注意事项分析

1)全局变量有可能被非可控篡改

 同一子函数在不同层同时调用,那如果在当前层执行此函数时被临时打断跨层后同样执行此函数,那此子函数中的变了就有可能出现主循环中此子函数调用的变了出现非需求改变。

出错举例:键盘应用中,主循环和中断中都调用USB上报键值的子函数,如下:

RAM

当主循环刚好在执行这个子函数时,出现中断,转而去执行中断服务程序,而中断服务程序中也执行这个子函数的时候。buffer_addr(xdata全局指针变量)的数据就将被填充成非正常的状态,整程序运行就会出错。

2)局部变量和全局变量全被非可控篡改

KEIL编译器在顺序分配局部变量地址时,不同层级临时变量分配地址不会复用,但同层级调用的子函数分配局部变量的地址时可能是相同的,举个简单的例子

RAM

RAM

如上:

 delay_us()和pwm_control_led_mode1()在主循环中调用,KEIL编译器可能将两个函数中的临时变量i(不局限同名)分配到同一个RAM地址中,如果子函数同层级调用时不会有问题的,因为函数都是顺序执行的。

同样是上述两个函数,delay_us()在timer0中断服务程序中调用, pwm_control_led_mode1()在主循环和timer0中断服务程序中都有调用,那编译器有可能将delay_us()和pwm_control_led_mode1()判定为同层级(中断服务),那临时变量i就有可能分配为同一RAM地址。

此时如果主循环在pwm_control_led_mode1()函数中执行到i=10时timer中断发生,程序被打断进入中断服务程序,中断执行delay_us()函数后i=500后回到主循环,因为两个子函数中临时变量i在RAM中的地址是公用的,所以回到主循环pwm_control_led_mode1()继续执行时,其临时变量i的值已经是500了,变量led_status_temp[i]可能会因为i值溢出导致赋值的数据被赋值到非led_status_temp变量存储驱导致程序中变量出错。

三、解决办法建议

出现[*** WARNING L15:MULTIPLE CALL TO SEGMENT ]warning的时候,程序都是存在潜在风险的,最彻底的改善就是从程序架构上避免出现不同层级重复调用的情况。当然正式应用方案中可能会因为空间大小或者其他原因不得不重复调用同一子函数的情况,针对此种情况,推荐几种规避方式,仅供读者参考

1)执行子函数关中断法

程序开发中,出现多层调用的情况一般就是两种情况,一是主循环跟中断服务程序中重复调用,另外就是不同中断服务程序中同时调用,经过上面分析,但凡出问题时,都是在执行被重复调用的子函数时打断去执行其他层指令,要彻底解决出问题的可能,只需在执行低优先级层(比如主循环)同一子函数之前关中断,执行完此子函数后再开中断就可解决所以可能存在的问题。

说明:有一种情况虽然会这个warning,但不会出问题,比如在不同的中断服务程序中掉用同一个子函数,但是中断的优先级同级,也就是不存在嵌套的情况。

优点:简单便捷,彻底解决问题。

缺点:有些应用中因为时序的问题,不允许临时关中断。

2)子函数copy改名法

就是重复调用的子函数,copy一份改一下函数名称,分别给不同层级调用,这样waring也会消失。

优点:简单,不存在临时变量被改的情况

缺点:仍然存在全局变量同时操作并被修改的情况,需要设计者注意是否会存在执行此子函数时临时中断换层又执行到此子函数的情况。

3)临时变量不复用法

在开发者确定不会存在执行此子函数时临时中断换层又执行到此子函数的情况(全局变量篡改)下,可配置KEIL编译器,使编译器给临时变量分配地址时,每个临时变量占用一个地址,不复用。配置方式如下:

RAM

编译器中嵌入这个NOOVERLAY命令,意思是临时变量不复用RAM地址

优点:可简单方便解决临时变量篡改导致的问题。

缺点:增加RAM的使用量。

说明:如果重复调用的子函数临时变量很少,不妨就将子函数中的临时变量直接定义成全局变量,这样不至于增加太多的RAM空间。

结束语:

上述推荐的方法只是一点建议,必定还有很多办法可以解决这类问题,个人认为最重要的是慎重处理此warning,并明确其存在的风险和内在逻辑,至于如何解除应用风险,每个人每个方案的做法可以根据实际情况处理。



审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分