MULTIPLE CALL TO SEGMENT
WARNING L15: MULTIPLE CALL TO SEGMENT
1、什么是Function Multiple Call Warning
关于这个问题Keil C 给出的解释如下:
简单来说,某一个函数被Main 函数调用的时候,这个时候发生了中断,在中断中这个函数被再次调用,这个时候就会导致之前的传参,临时变量被替换掉。需要讲一下,C51 由于堆栈空间很小,因此它利用一种 Overlay 的机制,将函数中的变量不存放在堆栈中,而是固定在memory 空间中。这种方式好处是节省堆栈空间。坏处就是函数不可重入,无法被multiple call。
如果是高阶的MCU就不会有这个问题。
2、Function Multiple Call 原因
有两种情况:
1、同一个函数(不可重入), 在正常执行的时候,被中断调用,即上面描述的情况。这个时候原先的变量和传参可能会被破坏掉。
2、两个不同的函数a、b,但由于上面将的Overlay 机制,内部的变量和参数的地址空间是同一个,(Overlay 机制认为两个函数不会被同时调用,因此分配相同的地址空间是没问题的),当a 在执行时,b 被中断调用,这个时候,a的参数,变量会被b 修改掉。
3、解决方法
1、 忽视警告(不推荐)
如果该函数不会以重入的方式执行,并且没有使用任何的memory空间(参数传递和局部变量都没有用到),则可以忽略该warning。
2、 Overlay 指令
使用链接器的OVERLAY指令将函数从覆盖分析(overlay analysis)中除去
这可以让该函数独享某一块内存区域,而不参与overlay。该函数是不可重入的,但是可以在不影响其他函数memory的情况下,被多个thread调用。尽管如此,还是需要确保该函数不被多个thread 同时调用。
3、 复杂情况下应对方式
当某个函数在执行时会被其他thread打断并调用时,则可以使用如下方式:
1) main调用该函数时禁止中断,可以在该函数被调用时用#pragma disable
语句来实现禁止中断的目的。必须使用OVERLAY指令将该函数从覆盖分析中除去。
调用时禁止中断,而不是在函数中禁止中断,因为函数参数传递也有可能用到memory,同时需要使用OVERLAY指令。
2)复制两份该函数的代码,一份到主程序中,另一份复制到中断服务程序中。
最简单可靠的实现,代码量会增加。
3)将该函数设为重入型
例如:
void myfunc(void) reentrant
{
...
}
这种设置将会产生一个可重入堆栈,该堆栈被被用于存储函数值和局部变量,用这种方法时重入堆栈必须在STARTUP.A51文件中配置。这种方法消耗更多的RAM并会降低重入函数的执行速度。
4、参考文档如下:
https://www.keil.com/support/docs/805.htm
Overly 机制参考:
https://blog.csdn.net/shenjin_s/article/details/107212719
本文地址:https://blog.csdn.net/shenjin_s/article/details/108585518
下一篇: 入职后回顾数据库知识(六)
推荐阅读
-
PHP 魔术函数 __call()用法_PHP教程
-
PHP Fatal error: Call to undefined function bcmul()_PHP教程
-
PHP 函数之 call_user_func & call_user_func_array
-
ThinkPHP做文字水印时提示call an undefined function exif_imagetype()解_PHP
-
php中出现:Call to undefined function curl_init()的解决方法
-
Educational Codeforces Round 66 (Rated for Div. 2)-E. Minimal Segment Cover
-
Educational Codeforces Round 66 (Rated for Div. 2) E. Minimal Segment Cover 倍增
-
Python中有趣在__call__函数
-
Oracle中的ORA-01548: active rollback segment '_SYSSMU1$' found
-
JavaScript中的apply/call/bind和this