multiple call you to deathto segment怎么解决

WARNING 15 (MULTIPLE CALL TO SEGMENT)
Applies to:
Information in this article applies to:
C51 All Version
I have added an Interrupt Service Routine (ISR) to my project and
I am now getting the following warnings:
***WARNING L15:
MULTIPLE CALL TO SEGMENT
?PR?_WRITE_GMVLX1_REG?D_GMVLX1
?PR?VSYNC_INTERRUPT?MAIN
?C_C51STARTUP
***WARNING L15:
MULTIPLE CALL TO SEGMENT
?PR?_SPI_SEND_WORD?D_SPI
?PR?VSYNC_INTERRUPT?MAIN
?C_C51STARTUP
***WARNING L15:
MULTIPLE CALL TO SEGMENT
?PR?SPI_RECEIVE_WORD?D_SPI
?PR?VSYNC_INTERRUPT?MAIN
?C_C51STARTUP
What does it mean and how do I solve the problem?
Warning 15 indicates that the linker has found a function that may
be called from both main code and an ISR (or functions called by an
ISR) or from multiple ISRs at the same time.
One problem is that the function is not reentrant and it may get
invoked (by an ISR) while the function is already executing. The
result will be variable and probably involve some form of argument
corruption.
Another problem is that memory used for local variables and
arguments may be overlaid with the memory of other functions. If the
function is invoked by an interrupt, that memory will be used. This
may cause memory corruption of other functions.
For example, for your first warning 15 the WRITE_GMVLX1_REG
function is being called from multiple roots. This function is
defined in the file D_GMVLX1.C or D_GMVLX1.A51. It is called from
both an ISR (or a function called by an ISR) and the function
VSYNC_INTERRUPT in MAIN.C
RESOLUTION
There are several ways to solve this problem.
If you are certain that the function is not executed in a
reentrant fashion and that there is no physical memory used by the
function (only registers are used), then you may simply choose to
ignore this warning.
If arguments are passed in registers and if the function uses only
registers during its execution, the function may be reentrant.
However, you must be very careful that changes to compiler or to the
compiler settings do not change this.
If there is physical memory used by the function, you should use
the linker OVERLAY directive to remove the function from overlay
analysis. For example:
OVERLAY (?PR?_WRITE_GMVLX1_REG?D_GMVLX1 ! *)
This prevents memory used by this function from being overlaid. If
this function calls other functions that are also used elsewhere in
your program, you may need to exclude those functions from overlay
analysis as well. This overlay command makes the linker happy and
removes the Warning 15 for this function.
The function is not reentrant. However, it may be called from
multiple threads without corrupting other function memory.
Nonetheless, you must ensure that the function is not called
simultaneously by multiple threads.
If the function could be called while it is executing then things
become slightly more complex. You may:
Disable interrupts whenever the function is called from main
code. You may use #pragma disable with the function that is called.
You must also use the OVERLAY directive to remove the function from
overlay analysis.
Make two copies of the function. One for main code and one for
Make the function reentrant. For example:
void myfunc(void) reentrant {
This results in a reentrant stack being used to store arguments
and local variables. With this method the reentrant stack must be
configured in the STARTUP.A51 file. This consumes more RAM and slows
down execution of the reentrant function.
MORE INFORMATION
in the BL51 User's Guide.
in the Cx51 User's Guide.
in the BL51 User's Guide.
Article last edited on:
Rate this article
Disagree? Move your mouse over the bar and click
Did you find this article helpful?
How can we improve this article?
Submit Rating and Feedback博客访问: 1590136
博文数量: 970
博客积分: 10011
博客等级: 上将
技术积分: 9615
注册时间:
日日行,不怕千万里;时时学,不怕千万卷
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: C/C++
WARNING L15: MULTIPLE CALL TO SEGMENT
这个问题必须注意,可能引起程序冲突,假设你用于自动化领域,则可能导致信号产生尖峰。 产生这一警告的一个根源是:你在主循环里调用了一个函数(如aaa),而在中断服务函数里,你用调用了这个函数(如aaa)。这样当主循环运行到该函数中是,一旦产生中断,则在中断里又再次调用该函数!这时,很可能出错! 避免这种情况的方法很多:如,在进中断的时候置需调用该函数的标志,而在主循环中调用该函数
参考资料:
1)C51&的重入问题&WARNING&L15:&MULTIPLE&CALL&TO&SEGMENT
2)*** WARNING L15: MULTIPLE CALL TO SEGMENT
3)关于“可重入函数”及c51警告信息:Multy Caller- -
4)KEILC51可重入函数及模拟栈浅析
阅读(2014) | 评论(0) | 转发(0) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。***WARNING L15: MULTIPLE CALL TO SEGMENT错误信息的处理 - 其他技术 - 电子工程世界网
***WARNING L15: MULTIPLE CALL TO SEGMENT错误信息的处理
10:45:40来源: eefocus
今天来说说*** WARNING L15: MULTIPLE CALL TO SEGMENT这个问题!&
&&&&&其实这个问题应该是引起注意的,有可能引起程序冲突,但是一般时候程序运行不会有问题,但是如果出来问题,那将会是很讨厌的问题.&
分析一下 产生这一警告的一个根源是:例如在主循环里调用了一个函数,而在中断服务中,你又一次调用了同样的函数。这样当主循环运行到该函数中时, 一旦产生中断,则在中断里又再次调用该函数!而使得该子函数发生了重入,这时,经管概率很低,但是很可能出错!这样,编译器就给出了警告!告诉你*** WARNING L15: MULTIPLE CALL TO SEGMENT ,表达的意思是发生了重入!字面意思自己理解去吧~~~&
想要避免这种情况的方法&
一.用reentrant使函数重入&
关于reentrant的说明:&
1,重入函数不能传递bit类型的参数和变量;&
2,重入函数建立的是模拟堆栈区,所以不使用一般函数位于存储模式默认空间的可覆盖式堆栈,而是在同一空间从顶端另行分配一个非覆盖式的重入堆栈。&
&&&&&small 默认空间是&
&&&&&compact 默认空间是&
&&&&&largr 默认空间是&
3,由于要保存参数和局部变量,所以会消耗很大的栈空间;尽量少用这种模式;&
4、&&&&在同一程序中可以定义和使用不同存储器模式的重入函数,任意模式的重入函数不能调用不同存储器模式的重入函数,但可以调用普通函数。&
5、&&&&实际参数可以传递给间接调用的重入函数。无重入属性的间接调用函数不能包含调用参数。&
二.如果空间多的话,可以定义两个同功能的函数,分别在中断和中断外调用&
别的方法没研究出来,嘿嘿~~~对了 我建议用第二种方法好点,第一种有些限制,不爽~~
三.主程序调用该函数时禁止中断。
可以在该函数被调用时用#pragma disable语句来实现禁止中断的目的。必须使用OVERLAY指令将该函数从覆盖分析中除去。
&&&&&&&&也可以用EA=1,EA=0来开关中断&
最后,WARNING L15: MULTIPLE CALL TO SEGMENT&
&&&&&这个问题必须注意,可能引起程序冲突,假设你用于自动化领域,则可能导致信号产生尖峰。 产生这一警告的一个根源是:你在主循环 里调用了一个函数(如aaa),而在中断服务函数里,你用调用了这个函数(如aaa)。这样当主循环运行到该函数中 是,一旦产生中断,则在中断里又再次调用该函数!这时,很可能出错! 避免这种情况的方法很多:如,在进中断的时候置需调用该函数的标志,而在主循环中调用该函数
关键字:&&
编辑:什么鱼 引用地址:
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。
微信扫一扫加关注 论坛活动 E手掌握
微信扫一扫加关注
芯片资讯 锐利解读
大学堂最新课程
汇总了TI汽车信息娱乐系统方案、优质音频解决方案、汽车娱乐系统和仪表盘参考设计相关的文档、视频等资源
热门资源推荐
频道白皮书
何立民专栏
北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。2014年7月 硬件/嵌入开发大版内专家分月排行榜第二
2013年10月 硬件/嵌入开发大版内专家分月排行榜第三2013年6月 硬件/嵌入开发大版内专家分月排行榜第三2013年3月 硬件/嵌入开发大版内专家分月排行榜第三
2014年7月 硬件/嵌入开发大版内专家分月排行榜第二
2013年10月 硬件/嵌入开发大版内专家分月排行榜第三2013年6月 硬件/嵌入开发大版内专家分月排行榜第三2013年3月 硬件/嵌入开发大版内专家分月排行榜第三
2014年7月 硬件/嵌入开发大版内专家分月排行榜第二
2013年10月 硬件/嵌入开发大版内专家分月排行榜第三2013年6月 硬件/嵌入开发大版内专家分月排行榜第三2013年3月 硬件/嵌入开发大版内专家分月排行榜第三
2014年7月 硬件/嵌入开发大版内专家分月排行榜第二
2013年10月 硬件/嵌入开发大版内专家分月排行榜第三2013年6月 硬件/嵌入开发大版内专家分月排行榜第三2013年3月 硬件/嵌入开发大版内专家分月排行榜第三
2014年7月 硬件/嵌入开发大版内专家分月排行榜第二
2013年10月 硬件/嵌入开发大版内专家分月排行榜第三2013年6月 硬件/嵌入开发大版内专家分月排行榜第三2013年3月 硬件/嵌入开发大版内专家分月排行榜第三
2014年7月 硬件/嵌入开发大版内专家分月排行榜第二
2013年10月 硬件/嵌入开发大版内专家分月排行榜第三2013年6月 硬件/嵌入开发大版内专家分月排行榜第三2013年3月 硬件/嵌入开发大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。***&WARNING&L15:&MULTIPLE&CALL&TO&SEGMENT[整理与网上资料]
这个问题应该是引起注意的,有可能引起程序冲突,但是一般时候程序运行不会有问题,但是如果出来问题,那将会是很讨厌的问题.
产生这一警告的一个根源是:例如在主循环里调用了一个函数,而在中断服务中,你又一次调用了同样的函数。这样当主循环运行到该函数中时,一旦产生中断,则在中断里又再次调用该函数!而使得该子函数发生了重入,这时,经管概率很低,但是很可能出错!这样,编译器就给出了警告!告诉你***
WARNING L15: MULTIPLE CALL TO SEGMENT
,表达的意思是发生了重入!字面意思自己理解去吧~~~
想要避免这种情况的方法
一.用reentrant使函数重入
&关于reentrant的说明:
1,重入函数不能传递bit类型的参数和变量;
2,重入函数建立的是模拟堆栈区,所以不使用一般函数位于存储模式默认空间的可覆盖式堆栈,而是在
同一空间从顶端另行分配一个非覆盖式的重入堆栈。
&& & small
&默认空间是
compact &默认空间是
&& & largr
&默认空间是
3,由于要保存参数和局部变量,所以会消耗很大的栈空间;尽量少用这种模式;
4,在同一程序中可以定义和使用不同存储器模式的重入函数,任意模式的重入函数不能调用不同存储
器模式的重入函数,但可以调用普通函数。
5,实际参数可以传递给间接调用的重入函数。无重入属性的间接调用函数不能包含调用参数。&
二.如果空间多的话,可以定义两个同功能的函数,分别在中断和中断外调用
三.在进中断的时候置需调用该函数的标志,而在主循环中调用该函数
&在其它环境下(比如PC,比如ARM),函数重入的问题一般不是要特别注意的问题.只要你没有使用static变量,或者指向static变量的指针,一般情况下,函数自然而然地就是可重入的。但C51不一样,如果你不特别设计你的函数,它就是不可重入的.
  引起这个差别的原因在于:一般的C编译器(或者更确切点地说:基于一般的处理器上的C编译器),其函数的局部变量是存放于堆栈中的,而C51是存放于一个可覆盖的(数据)段中的.
  至于C51这样做的原因,不是象有些人说的那样,为了节约内存.事实上,这样做根本节约不了内存.理由如下:
如果一个函数func1调用另一个函数func2,那么func1,func2的局部变量根本就不能是同一块内存.C51还是要为他们分配不同的RAM.这跟使用堆栈相比,节约不了内存.
如果func1,func2不是在一个调用链上,那么C51可以通过覆盖分析,让它们的局部变量共享相同的内存地址.但这样也不会比使用堆栈节约内存.因为既然它们是在不同的调用链上,那么当其中一个函数运行时,那么另外一个函数必然不在其生命期内,它所占用的堆栈也已释放,归还给系统.
  真实的原因(C51使用覆盖段作为局部变量的存放地的原因)是:
  51的指令系统没有一个有效的相对寻址(变址寻址)的指令,这使得使用堆栈作为变量的代价太过昂贵.
  使用堆栈存放变量的一般做法是:
  进入函数时,保留一段堆栈空间,作为变量的存放空间,用一个可作为基址寻址的寄存器指向这个空间,通过加上一个偏移量,就可以访问不同的变量了.
  例如: MOV EAX, [EBP + 14];X86指令
 LDR R0, [R12, #14];ARM指令
  都可以很好的解决这个问题.
  但51缺少这样的指令.
  其实,51中还是有2个可变址寻址的指令的,但不适合访问堆栈的局部变量这样的场合.
  MOVC A, @A+DPTR
  MOVC A, @A+PC
  所以,C51有个特别的关键字: reentrant 用来解决函数重入的问题.
keilc51的“覆盖技术”。
  (1)局部变量存储在全局RAM空间(不考虑扩展外部存储器的情况);
  (2)在编译链接时,即已经完成局部变量的定位;
  (3)如果各函数之间没有直接或间接的调用关系,则其局部变量空间便可覆盖。
  正是由于以上的原因,在Keil C51环境下,纯粹的函数如果不加处理(如增加一个模拟栈),是无法重入的。
&C51编译器采用了一个扩展关键字reentrant作为定义函数时的选项,需要将一个函数定义为可重入函数时,只要在函数后面加上关键字reentrant即可。
  与非可重入函数的参数传递和局部变量的存储分配方法不同,C51编译器为可重入函数生成一个模拟栈(相对于系统堆栈或是硬件堆栈来说),通过这个模拟栈来完成参数传递和存放局部变量。模拟栈以全局变量?C_IBP、?C_PBP和?C_XBP作为栈指针(系统堆栈栈顶指针为SP),这些变量定义在DATA地址空间,并且可在文件startup.a51中进行初始化。根据编译时采用的存储器模式,模拟栈区可位于内部(IDATA)或外部(PDATA或XDATA)存储器中。
<img src="/blog7style/images/common/sg_trans.gif" real_src ="/images/article/00bc17e7-75ef-48df-bb64-ae/3.jpg" ALT="根据编译时采用的存储器模式"
TITLE="***&WARNING&L15:&MULTIPLE&CALL&TO&SEGMENT[整理与网上资料]" />
注意:51系列单片机的系统堆栈(也叫硬件堆栈或常规栈)总是位于内部数据存储器中(SP为
8位寄存器,只能指向内部),而且是“向上生长”型的(从低地址向高地址),而模拟栈是“向下生长”型的。
c51函数调用时参数主要是通过寄存器R1~R7来传递的,如果在调用时,参数无寄存器可用或是采用了编译控制指令“NOREGPARMS”,则参数的传递将发生在固定的存储器区域,该存储器区域称为参数传递段,其地址空间取决于编译时所选择的存储器模式。利用51单片机的工作寄存器最多传递3个参数,
<img src="/blog7style/images/common/sg_trans.gif" real_src ="/images/article/00bc17e7-75ef-48df-bb64-ae/4.jpg" ALT="利用51单片机的工作寄存器最多传递3个参数"
TITLE="***&WARNING&L15:&MULTIPLE&CALL&TO&SEGMENT[整理与网上资料]" />
用固定存储区传递参数给汇编程序,参数用段名?function_name?BYTE和?function_na-
me?BIT保存传递给函数function_name的参数。位参数在调用函数前复制到?function_n-
ame?BIT段,别的参数复制到?function_name?BYTE段。即使通过寄存器传递参数,在这些段中也给所有的参数分配空间,参数按每个段中的声明的顺序保存。用做参数传递的固定存储区在内部数据区还是在外部数据区,由存储模式决定。SMALL模式参数段用内部数据区,而且是最有效的,COMPACT和LARGE模式用外部数据区。函数返回值通常用CPU寄存器传递
<img src="/blog7style/images/common/sg_trans.gif" real_src ="/zyi531/pic/item/6ce2715dece00c6efaf2c0b4.jpg"
ALT="***&WARNING&L15:&MULTIPLE&CALL&TO&SEGMENT[整理与网上资料]"
TITLE="***&WARNING&L15:&MULTIPLE&CALL&TO&SEGMENT[整理与网上资料]" />
任务传参是通过任务堆栈来实现的,即将任务的参数从相应的寄存器中保存到任务堆栈中,在任务出栈时将参数传给相应的寄存器,这样也就是通过寄存器传参。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。}

我要回帖

更多关于 yield to call 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信