keil中 如何解决warning L13:Recursive call to Function 及overlay解释

最近编译keil项目时,遇到一个比较奇怪的link warning,如下所示。

keil中 如何解决warning L13:Recursive call to Function 及overlay解释_第1张图片

根据这个warning,容易知道这两个函数存在递归(相互)调用关系。其实在源代码中不存在直接递归调用关系,而是间接地调用,从map文件摘出这个calltree如下

+--> _CBUSMSCREADECBUSSPEEDSDONE/SI_DRVCBUSRX
|  | _CBUSMSCREADTMDSSPEEDSDONE/SI_DRVCBUSRX
|  | _CBUSMSCREADECBUSDEVROLESDONE/SI_DRVCBUSRX
|  | _CBUSMSCREADLOGDEVMAPDONE/SI_DRVCBUSRX
|  | _CBUSMSCREADBANDWIDTHDONE/SI_DRVCBUSRX
|  | _CBUSMSCREADFEATUREFLAGDONE/SI_DRVCBUSRX
|  | _CBUSMSCREADDEVICEIDHDONE/SI_DRVCBUSRX
|  | _CBUSMSCREADDEVICEIDLDONE/SI_DRVCBUSRX
|  | _CBUSMSCREADSCRATCHPADSIZEDONE/SI_DRVCBUSRX
<--+ _CBUSMSCREADINTSTATSIZEDONE/SI_DRVCBUSRX

简单梳理一下上面的调用树,就是CBUSMSCREADECBUSSPEEDSDONE调用了CBUSMSCREADTMDSSPEEDSDONE, CBUSMSCREADECBUSDEVROLESDONE调用了CBUSMSCREADECBUSDEVROLESDONE。。。 。。。最后CBUSMSCREADINTSTATSIZEDONE又调用了CBUSMSCREADECBUSSPEEDSDONE

众所周知,Keil51由于内存资源比较紧张,函数的参数及局部变量一般地放在data segment, 为了避免一个函数的变量被另外一个函数的变量覆盖,keil会分析函数之间的相互调用关系,对于没有相互调用的关系的函数变量就可以重叠在一起,即overlay。  对于存在调用关系的函数,则变量存放在data区间的不同地址。但是,递归调用是一种例外,由于

是同一个函数,所以变量都会重叠在一起,这样会造成变量还没用完就被覆盖了。  基于此,原则上,keil51是不允许递归调用的。

 

关键点:如何解决这类问题?

1)如果是直接递归调用, 如下所示

void B(void)

{

... ...

   B()

... ....

}

就将B函数申明为void B(void) reentrant, 这样就会生成模拟栈来储存自动变量和参数,以避免变量被覆盖。

 

2)如果是间接递归调用,如我的项目遇到的case,怎么办?

在option->LX51 Misc->Misc controls中,有一个Overlay的空白框,这个是干什么用的呢? 查阅LX51 user guide,知道Overlay是link的一个指示符,我们可以利用它来手动

修改或标明call tree关系。比方说,A通过函数指针调用B,为安全起见,可以增加一条OVERLAY(A!(B))    又比如A和B其实不存在调用关系,如我的项目中遇到的case,这种情况下,只需要增加OVERLAY(A~(B))

其实LX51指示符除了Overlay外还有很多,如removeunused, disablewarning等。如不把它们弄清楚 就很容易造成项目的各种不稳定性。

你可能感兴趣的:(嵌入式驱动开发杂记)