今日来说说*** WARNING L15: MULTIPLE CALL TO SEGMENT这个问题!
其实这个问题实践上便是函数重入问题,在操作系统的多线程很常见。应该是引起留意的,有或许引起程序抵触,可是一般时分程序运转不会有问题,可是假如出来问题,那将会是很厌烦的问题.
剖析一下发生这一正告的一个本源是:例如在主循环里调用了一个函数,而在中止服务中,你又一次调用了相同的函数。这样当主循环运转到该函数中时,一旦发生中止,则在中止里又再次调用该函数!而使得该子函数发生了重入,这时,虽然概率很低,可是很或许犯错!这样,编译器就给出了正告!告知你*** WARNING L15: MULTIPLE CALL TO SEGMENT ,表达的意思是发生了重入!字面意思自己了解去吧~~~
想要避免这种状况的办法
一.用reentrant使函数重入
关于reentrant的阐明:
1,重入函数不能传递bit类型的参数和变量;
2,重入函数树立的是模仿仓库区,所以不运用一般函数坐落存储方式默许空间的可掩盖式仓库,而是在同一空间从顶端另行分配一个非掩盖式的重入仓库。
small 默许空间是 data;
compact 默许空间是 pdata;
largr 默许空间是 xdata;
3,因为要保存参数和局部变量,所以会耗费很大的栈空间;尽量少用这种方式;
4、 在同一程序中能够界说和运用不同存储器方式的重入函数,恣意方式的重入函数不能调用不同存储器方式的重入函数,但能够调用一般函数。
5、 实践参数能够传递给直接调用的重入函数。无重入特点的直接调用函数不能包括调用参数。
二.假如空间多的话,能够界说两个同功用的函数,分别在中止和中止外调用
其他办法没研究出来,嘿嘿~~~对了 我主张用第二种办法好点,第一种有些约束,不爽~~
在其它环境下(比方PC,比方ARM),函数重入的问题一般不是要特别留意的问题.只需你没有运用static变量,或许指向static变量的指针,一般状况下,函数自然而然地便是可重入的.
但C51不一样,假如你不特别规划你的函数,它便是不行重入的.
引起这个差其他原因在于:一般的C编译器(或许更确切点地说:根据一般的处理器上的C编译器),其函数的局部变量是存放于仓库中的,而C51是存放于一个可掩盖的(数据)段中的.
WARNING L15: MULTIPLE CALL TO SEGMENT(转–感觉讲的不错)
这个问题有必要留意,或许引起程序抵触,假定你用于自动化范畴,则或许导致信号发生尖峰。 发生这一正告的一个本源是:你在主循环里调用了一个函数(如aaa),而在中止服务函数里,你用调用了这个函数(如aaa)。这样当主循环运转到该函数中是,一旦发生中止,则在中止里又再次调用该函数!这时,很或许犯错! 避免这种状况的办法许多:如,在进中止的时分置需调用该函数的标志,而在主循环中调用该函数
Keil C -WARNING L15: MULTIPLE CALL TO SEGMENT
1.第一种错误信息
***WARNING L15: MULTIPLE CALL TO SEGMENT
SEGMENT:?PR?_WRITE_GMVLX1_REG?D_GMVLX1
CALLER1:?PR?VSYNC_INTERRUPT?MAIN
CALLER2:?C_C51STARTUP
该正告表明连接器发现有一个函数或许会被主函数和一个中止服务程序(或许调用中止服务程序的函数)一起调用,或许一起被多个中止服务程序调用。
呈现这种问题的原因之一是这个函数是不行重入性函数,当该函数运转时它或许会被一个中止打断,然后使得成果发生变化并或许会引起一些变量方式的抵触(即引起函数内一些数据的丢掉,可重入性函数在任何时分都能够被ISR打断,一段时间后又能够
运转,可是相应数据不会丢掉)。
原因之二是用于局部变量和变量(暂时这样翻译,arguments,[自变量,变元一数值,用于确认程序或子程序的值])的内存区被其他函数的内存区所掩盖,假如该函数被中止,则它的内存区就会被运用,这将导致其他函数的内存抵触。
例如,第一个正告中函数WRITE_GMVLX1_REG 在D_GMVLX1.C 或许D_GMVLX1.A51被界说,它被一个中止服务程序或许一个调用了中止服务程序的函数调用了,调用它的函数是VSYNC_INTERRUPT,在MAIN.C中。
解决办法:
假如你确认两个函数决不会在同一时间履行(该函数被主程序调用而且中止被制止),而且该函数不占用内存(假定只运用寄存器),则你能够彻底疏忽这种正告。
假如该函数占用了内存,则应该运用连接器(linker)OVERLAY指令将函数从掩盖剖析(overlay analysis)中除掉,例如:
OVERLAY (?PR?_WRITE_GMVLX1_REG?D_GMVLX1 ! *)
上面的指令避免了该函数运用的内存区被其他函数掩盖。假如该函数中调用了其他函数,而这些被调用在程序中其他地方也被调用,你或许会需求也将这些函数扫除在掩盖剖析(overlay analysis)之外。这种OVERLAY指令能使编译器除掉上述正告信息。
假如函数能够在其履行时被调用,则状况会变得更杂乱一些。这时能够选用以下几种办法:
1.主程序调用该函数时制止中止,能够在该函数被调用时用#pragma disable句子来完成制止中止的意图。有必要运用OVERLAY指令将该函数从掩盖剖析中除掉。
2.仿制两份该函数的代码,一份到主程序中,另一份仿制到中止服务程序中。
3.将该函数设为重入型。例如:
void myfunc(void) reentrant
{
…
}
这种设置将会发生一个可重入仓库,该仓库被被用于存储函数值和局部变量,用这种办法时重入仓库有必要在STARTUP.A51文件中装备。
这种办法耗费更多的RAM并会下降重入函数的履行速度。