棧在MCU中有著非常重要的作用。定義局部變量,函數(shù)跳轉(zhuǎn),寄存器保護(hù)都需要使用到棧。
但是在MCU中,只會(huì)默認(rèn)一定大小的棧給我們使用。那么多任務(wù)就需要多個(gè)棧了,那只能自己的創(chuàng)造棧了。
static unsigned int stkbuf[100]; //創(chuàng)造一個(gè)100個(gè)word的任務(wù)棧。這個(gè)是16位單片機(jī)寄存器要以16位為準(zhǔn)
void NewFunBuff(VOID_FUN_PTR task,unsigned int* opt)
{
*opt = (U16)(((U32)task) >> 8); //將任務(wù)的指針放到stkbuf中
opt--;
*opt = 0x80; //設(shè)置地址偏移
((U8*)opt)--;
*opt = 0x55; //設(shè)置地址偏移
asm{
lds opt /將最終的地址得到的指針放到sP中,這個(gè)時(shí)候系統(tǒng)的SP就會(huì)給改變
}
asm nop
這個(gè)最重要的地方就是在返回的時(shí)候需要從sp中取出進(jìn)入函數(shù)前的數(shù)據(jù)。這個(gè)時(shí)候也會(huì)取出PC指針。而在取值的過程中SP是自增的,我們需要保證取PC的時(shí)候就是取到stkbuf 中存task位置上。然后返回的時(shí)候就直接返回到了task中去了。
}
void InitSystem(void)
{
InitSystemClock();
InitSystemIo();
}
void main(void) {
/* put your own code here */
DisableInterrupts;
InitSystem();
EnableInterrupts;
//FunTask1();
NewFunBuff(FunTask1,&stkbuf[99]);
while(1) {
}
/* please make sure that you never leave main */
}
而task的指針就是Funtask1.那程序就會(huì)去跑Funtask1了、
有問題嗎?仿真吧,看看內(nèi)存的變化就知道為什么了。