关于*** WARNING L15: MULTIPLE CALL TO SEGMENT解决方案
Posted perseverance52
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于*** WARNING L15: MULTIPLE CALL TO SEGMENT解决方案相关的知识,希望对你有一定的参考价值。
关于*** WARNING L15: MULTIPLE CALL TO SEGMENT
编写51程序的时候,有时候会在主函数和中断函数里面调用同一个函数,如果正的出现这种情况,编译器会提出 这种警告: *** WARNING L15: MULTIPLE CALL TO SEGMENT(重复调用同一个函数)
这种情况时因为函数发生了重入,
尽管这样出现错误的概率很低,但是一旦出现错误,将会是很讨厌的错误,在网上我看到的一篇博文里面,说这个错误必须引起注意,特别是像我们这种做控制和自动化的,一点小小的错误和异常都可能引起一次事故和灾难,必须小心谨慎。
因为它可能引起程序冲突,导致信号产生尖峰。 产生这一警告的一个根源是:你在主循环 里调用了一个函数(如aaa),而在中断服务函数里,你用调用了这个函数(如aaa)。这样当主循环运行到该函数中 是,一旦产生中断,则在中断里又再次调用该函数!这时,很可能出错! 避免这种情况的方法很多:如,在进中断的时候置需调用该函数的标志,而在主循环中调用该函数。
解决方法:
- 可以定义两个功能相同的函数,在中断和主函数里面分别调用,但是需要很多额外重复函数;
- 在中断函数里面设置一个标志,然后在主循环里面调用该函数。
3.用关键字reentrant
使函数重入。
下面具体说说的我的情况和解决办法。
在主函数里面我多次调用 show_string函数,用TFT来显示需要的信息,当中断产生的时候,我又需要在TFT里面显示其他信息,这样就出现了函数的重入,但是又不能取消,进入中断和主函数都是必须的。
当我用第一种方法来解决的时候,发现需要重新定义的函数太多了,太占内存,不能用。于是考虑第二种方法,在中断里面设置标志,然后在主循环里面实现。
void int0() interrupt 0{
delayms(5);
if(k3_set==0){
set_flag = ~set_flag;//标志
chose_flag = 0;
ds1302_init();//如果没有这句的话,设置完后又会回到原来的数字
}
}
在主循环里面:
while(1){
if(set_flag==0){//正常
ds1302_readtime();
show_string(120,16," ");//刷新提示区,就是这个,不能写在中断里面
}
else{
key_init();
}
- 用
reentrant
使函数重入,需要注意事项:
-
重入函数不能传递bit类型的参数和变量;
-
重入函数建立的是模拟堆栈区,所以不使用一般函数位于存储模式默认空间的可覆盖式堆栈,而是在同一空间从顶端另行分配一个非覆盖式的重入堆栈。
small
默认空间是 data
;
compact
默认空间是 pdata
;
largr
默认空间是 xdata
;
- 由于要保存参数和局部变量,所以会消耗很大的栈空间;尽量少用这种模式;
- 在同一程序中可以定义和使用不同存储器模式的重入函数,任意模式的重入函数不能调用不同存储器模式的重入函数,但可以调用普通函数。
- 实际参数可以传递给间接调用的重入函数。无重入属性的间接调用函数不能包含调用参数。
.如果空间多的话,可以定义两个同功能的函数,分别在中断和中断外调。
摘自:http://www.51hei.com/mcu/3272.html
以上是关于关于*** WARNING L15: MULTIPLE CALL TO SEGMENT解决方案的主要内容,如果未能解决你的问题,请参考以下文章
填坑*** WARNING L15: MULTIPLE CALL TO SEGMENT
如何禁用关于#warning 指令是 GCC 扩展的 GCC 警告?
关于Moment.js warning:Deprecation warning: value provided is not in a recognized RFC2822 or ISO format