3944|8

80

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

ucos移植过程中的用户堆栈地址问题 [复制链接]

 我建立一个任务MyTask,代码如下:



void MyTask(void *data)
{
    data = data;



    psem = OSSemCreate(0); // 创建一个信号量



    while(1)
{
     transData(0x55);  //通过串口发送数据55
     OSSemPend(psem,0,error);  //等待信号量
     transData(0x33); //通过串口发送数据33

}
}



程序发送数据55后,执行等待信号量函数,



但是一旦进入OSSemPend,R0的地址就立即减少4,例如任务堆栈地址是51EA(采用16位寻址方式,数据页指针是DPP1),R0的正确地址是51EA,一旦进入OSSemPend,R0的地址就减去4,变成了51E6。再往下执行一步,R0又减去8,最终是51DE,以后再执行程序保持该值不变。



这样就导致了进行任务调度时,保存context时出现错误,因此切换到其他任务后,就再不能正确切换到MyTask了,



请问高手,这是什么原因。



我的qq是57109527,希望能和大家探讨一下

最新回复

有点难度哦  详情 回复 发表于 2008-5-1 07:20
点赞 关注
 

回复
举报

60

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
R0中保存的是任务堆栈的地址?还是任务堆栈中保存了R0? C调用任务时一般会用R0-R4传递参数。 问题再详细点,不是很明白你的意思
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
我用的Cl67CR的单片机,编译器是tasking 7.5 v2。
现在做的工作是将ucosII v200 移植到此单片机上。
每当运行一个任务,R0就指向该任务堆栈,
在进行任务切换时,通过R0来保存和恢复CPU的相关寄存器。
现在不清楚的问题有两个,一是通过什么机制,让R0指向了当前运行任务的堆栈?
                        二是上面的问题,是什么原因导致R0的值发生了改变,以致不能正常的进行任务切换?
呵呵,希望能和你探讨一下。
 
 
 

回复

63

帖子

0

TA的资源

一粒金砂(初级)

4
 
今天发现真正的问题不在指向任务堆栈的指针,而是进行任务切换时保存的返回地址有问题。

函数的调用关系如下:MyTask() -> OSSemPend() -> OSSched(),OSSched() 代码如下:

void OSSched (void)
{
    INT8U y;


    OS_ENTER_CRITICAL();
    if ((OSLockNesting | OSIntNesting) == 0) {   /* Task scheduling must be enabled and not ISR level  */
        y             = OSUnMapTbl[OSRdyGrp];    /* Get pointer to highest priority task ready to run  */
        OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
  transData(OSPrioHighRdy);
  transData(OSPrioCur);
        if (OSPrioHighRdy != OSPrioCur) {         /* No context switch if current task is highest ready */
            OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
            OSCtxSwCtr++;                        /* Increment context switch counter                   */
   transData(0x99);
            OS_TASK_SW();                        /* Perform a context switch                           */
        }
    }
    OS_EXIT_CRITICAL();
}

调试的时候发现,当运行到OS_TASK_SW()时,IP的值是0CEA。

然后进入到 OS_TASK_SW(),此函数是用汇编写的,做任务切换。

在 OS_TASK_SW()中,要保存程序的返回地址,此时保存的0CEC,也就是OSSched()中OS_EXIT_CRITICAL();的地址。

在OS_TASK_SW()中成功跳转到另一个任务MyTask1(),该任务中函数调用关系是:MyTask1() -> OSSemPost() -> OSSched(),

在OSSched()中调用OS_TASK_SW(),返回到地址0CEC处,这时候不是返回到MyTask()中,而是在MyTask1() 中顺序执行下面的语句。



唉,不知道有什么好的解决方法。

希望大家探讨一下。
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

5
 
1.在移植代码中,将任务堆栈地址保存在了R0寄存器中。
2.我想根本原因是任务切换时候的返回地址出错。
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

6
 
"返回到地址0CEC处,这时候不是返回到MyTask()中,而是在MyTask1() 中顺序执行下面的语句。"这句话什么意思?
MyTask1() -> OSSemPost() -> OSSched()后返回的地方应该是上一次OSSemPend()中调用的OSSched()中  的OS_EXIT_CRITICAL()处,过程如下:
OSSched()中  的OS_EXIT_CRITICAL()->OSSemPend()中的 OS_Sched()的下一句,执行完OSSemPend()中的剩余代码后就回到了你的MyTask()中。
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

7
 
因为0CEC是OSSched()中OS_EXIT_CRITICAL();语句的存放的地址,
返回时有什么机制确保是在上次调用OSSemPend()中调用的OSSched()中  的OS_EXIT_CRITICAL()处,
而不是本次调用OSSemPost() 中调用的OSSched()中  的OS_EXIT_CRITICAL()处呢?
从实际的运行结果来看,是返回到了本次调用OSSemPost() 中调用的OSSched()中  的OS_EXIT_CRITICAL()处。
这样就导致了任务不能正确的切换。

多谢Cifeng_Liang!
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

8
 
当在Mytask中调用Pend函数而发生任务切换时,进入任务切换函数,在此函数中保存Mytask的上下文到与Mytask相应的堆栈中,那么当Mytask1调用Post函数而使Mytask就绪,且Mytask的优先级比Mytask1的优先级高,则再次进行一次调度,这时就把上一次保存在Mytask堆栈中的内容恢复过来就好了。
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

9
 
有点难度哦
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表