update: dnmmanager_getName函数的原型,codo询问。 Screenshot4
char* DNMManager_GetName(DNM_s* element)
{ //program stops here.
//link register : 0x805afed0
//program counter: 0x805cda64
return &element->Name[0];
}
DNMManager_GetName():
805cda64: E24DD008 sub sp, sp, #8
805cda68: E58D0000 str r0, [sp]
我通过使用IDE调试器提供的断点。在屏幕截图1中,我注意到在函数的输入点冻结程序时,链接寄存器包含0x805DCDA0,这是
main
的地址。
while(1)
不是函数的呼叫者,而是链接寄存器包含
while(1)
的地址。
为什么?
谁说的?Screenshot1
main
ScreenShot2下面是一个示例,显示链接寄存器的值已更改为正确的值,在这种情况下,在程序输入函数IntaintCinit()。Screenshot2
while(1)
秒问题
如何发生?在什么情况下?
Screenshot3
int main(void)
{ //program stops at here. link register: 0x805dcda0
OS_ERR err = OS_ERR_NONE;
IntAINTCInit(); //once program enters this function,
//the value of link register is changed
OS_Init(); //initialize OS
OSStart(&err); //start OS
if (err != OS_ERR_NONE)
{
printf("OS fails");
}
/*no return statement*/
}
start_boot():
805dcd94: E92D4008 push {r3, lr}
138 CopyVectorTable();
805dcd98: EB000001 bl CopyVectorTable
141 main();
805dcd9c: EB00001D bl main
143 while(1);
$C$L1:
805dcda0: EAFFFFFE b $C$L1
您只显示一些屏幕截图,而不是完整的代码,我只能推测...
Screenshot1:入口点
比Windows或Linux上的MicroController的程序不应从
main()返回。无处可去。为了防止进一步的损害,
lr指向无尽的循环。如果您意外地从
main().
Screenshot2:intaintcinit()Screenshot3:PC =lr
输入函数时,lr
包含返回地址。如果函数调用其他功能,则必须保存lr(通常在堆栈上)并为其分配一个新值。屏幕截图在语句之后显示状态:
OS_Init()
如果您查看汇编代码,则可以看到memset
memset返回后立即显示状态。每次函数刚刚返回时,PC
都必须等于lr
,因为这是返回的工作方式。所以这里一切都还好。Screenshot4:dnmmanager_getname
输入DNMMANAGER_GEGNAME()时,屏幕截图显示了正确的状态。该功能的呼吁是由该声明进行的:
void IntAINTCInit(void)
{ //program stops here. link register: 0x805dce28
/*pseudo code*/
!!Reset the ARM interrupt controller
!!Wait for the reset to complete
!!Enable any interrupt generation by setting priority threshold
!!Register the default handler for all interrupts
}
44 OS_Init(); //initialize OS
805dce28: EBFF30EA bl CPU_Init
通话后的语句(需要返回的地方)为0x805AFED0,Exacytlylr
在屏幕截图上包含的内容。 注意C代码中的单行会导致两个函数调用,一个函数为DNMMANAGER_GEGNAME(),一条to totomemcpy。 0x805afee4将是第二个功能调用的返回地址。但是屏幕截图4显示了第一个功能调用的状态。