这是我的移植心得:
单片机使用R7传参数,在调用任务函数时,提前把R7里放上该传的参数值,等到调用任务函数时,编译器自动到R7里把参数取出放到任务函数的形参里。
本人在做传参时,在main()里声明int8u idata dat = 0x05;注意是idata。在Create()任务时传过去的参数是地址&dat,然后初始堆栈时也应该是地址,在然后是OSStart()调用Taskrdy(),他是个汇编程序,在里面POP R7
这时R7里是地址;完了是开始任务函数了把R7赋给pd(形参),pd是地址
在函数里面处理*pd = dat了,就行了。
但犯了点毛病:
犯错:第一,osinitstack时初始化堆栈对应R7的堆栈里放了*(INT8U *)ppdata,这是dat这个数不是地址,然后R7赋给pd,pd = dat,*pd = ???。
第二,R7传参数时只能传8位的,我在Task()任务函数的形参处这样声明的Task(void *pd)
编译器默认的是大模式,在Xdata里给pd开辟内存单元,这时一个8位的给一个多位的赋值当然不对了哈,必须声明成idata即(void idta *pd)
在任务函数里也能传数组,即把数组的地址放到R7里面
/*
void Task1(INT8U idata *pd)
{
for(;;)
{
P1 = *pd;
OSTimeDly(10);
}
}
void main()
{
INT8U idata dat = 0x05;
OSInit();
OSTaskCreate(Task1,(void *)&dat,TaskStk,1);
OSStart();
}
传数组的:
void Task1(void idata *pd)
{
for(;;)
{
P1 = *(INT8U *)(pd + 1);
OSTimeDly(10);
}
}
void main()
{
INT8U idata dat[3] = {0x05,0x06,0x07};
OSInit();
OSTaskCreate(Task1,(void *)&dat,TaskStk,1);
OSStart();
}
*/
在这里只能是idata 因为早晚这个地址得给R7,而R7是个八位的,如果是Xdata 的话,这个地址是大于8位的肯定装不下了,就错了 哈;这里如果系统中不传地址而直接传值的话,那样倒可以在内存的任何地方申请单元放变量,因为这个数肯定是unsigned char的,但这样又不能传数组了,因为不传地址的缘故。
关于重入问题:keil把重入函数的临时变量放在?C_XBP这个寄存器所指向的内存单元中,即?C_XBP里放的内容如:X:0x02F1,则临时变量压在从X:0x02F1单元开始往下的单元:如:
第一个要保存的重入参数是uchar c ,第二个参数是uchar b,则在X:0x02F0单元里放c,在X:0x02EF单元里放b。这个指针指的单元不用而用下个单元。
?C_XBP寄存器的地址是0x08,初始化时?C_XBP里放的是0x02F1这个数, X:0x02F1里放临时变量。