10610|15

61

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

困扰半个月的问题:ucOS中,第2次调用OSTimeDly()死机 [复制链接]

 我按照步骤把 ucos 移植到 ZLG 的 easyARM 开发板上,前面工作进行的挺顺利,但最近被这个问题给卡住了,半个月了,还没有搞定。
请求高手解疑释惑啊:

在一些初始化工作之后,创建了两个任务:

void main(void)

{

    OSInit();
    (void)OSTaskCreate(task_idle, (void *)0, &TaskIdleStk[TASK_STK_SIZE - 1], OS_LOWEST_PRIO - 4);
    (void)OSTaskCreate(task_handset, (void *)0, &TaskHandsetStk[TASK_STK_SIZE - 1], 5);
    OSStart();
}

两个 task 代码如下:

void task_idle(void * pdata)
{
    for (;;)
    {
        LED_flash(1);
        delay_NS(LED_FLASH_KEEP_TIME);
    }
}

void task_handset(void * pdata)
{
    timer_init();

    for (;;)
    {
        LED_flash(2);
        OSTimeDly(OS_TICKS_PER_SEC);
    }
}

其中 task_handset 的优先级比 task_idle 的优先级高,所以我在 task_handset 中启动时钟中断定时器。
时钟中断处理函数是按照 easyARM 开发版的标准模板写的,其中通过如下函数调用 ucos 的 tick 函数:

void IRQ_Timer0(void)
{
    T0IR = 0x01;        // Clear IR flag.
    VICVectAddr = 0x00; // Notify VIC work has done.

    LED_flash(7);

    OSTimeTick();
}

由于笔记本上没有并口,不能用 ZLG 带的 easyJTAG,只能用 LED 指示;
运行现象如下:

1. LED 2 亮一下,说明 task_hanset 启动了,同时 delay;

2. LED1 闪烁,同时 LED 7 闪烁,说明 task_idle 运行正常,时钟中断函数运行正常;

3. 过一会 LED 2 亮一下,之后就死机了。

应该是 task_handset delay 时间到,由于其优先级高,所以抢占执行,LED 2 亮一下是正常的,但是之后第二次调用 OSTimeDly 就死机了,不知道为什么。


跪求高手指点迷津????

最新回复

恭喜啊,终于解决完了 论坛就应该这样,大家积极探讨 同时lz自己解决完了问题,也能把解决过程说出来 这样后来人在看到这个帖子的时候,才有它的价值 而不是仅仅为lz解决了个实际问题 更多的是这个帖子对于他人的借鉴意义 简单总结下就是 task_handset任务延时,普通切换 idle任务运行 第一次时钟中断,会尝试进行中断级的切换,但由于task_handset任务尚未就绪 中断返回至idle任务 第OS_TICKS_PER_SEC次时钟中断时, 假设ZLG 的定时中断程序先进行中断级切换 当前sp和pc入idle任务栈 弹出task_handset的sp和pc OSIntExit 中再次进行切换,此时却将task_handset的sp和pc压入了idle任务中 当task_handset第二次运行完毕后,普通切换 但sp和pc却是handle的,因此出现问题 不知lz是否此意?   详情 回复 发表于 2008-6-3 19:25
点赞 关注
 

回复
举报

74

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
我觉得是不是中断不来了?
因为OSTimeDly是按照多少个tick后允许任务切换。
并且你的TimeTisk是挂在IRQ0上的。
所以是不是中断不来。造成任务没有切换?
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
请问中断为什么不来了?哪些地方会影响?
谢谢!
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

4
 
高手都藏在哪啊?????
 
 
 

回复

65

帖子

0

TA的资源

一粒金砂(初级)

5
 
fighting
 
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

6
 
中断中 LED_flash(7)实现是什么?其占用多少时间?

timer_init()如何实现的?目前定时器是自动重装载的么?
也就是说进入IRQ_Timer0后退出时有没有再次启动定时器?

在OSTimeTick中会将OSTimeDly的任务的延时减1
通过减少至0来决定是否进行任务切换
同时会判断当前是否有其更高优先级任务进入就绪状态,若有则进行任务切换

delay_NS(LED_FLASH_KEEP_TIME)是否调用了OSTimeDly?

从现象看好像是没有进行任务
但感觉有点矛盾,若定时器没有正常工作那么 task_handset是怎么进入就绪状态的呢?
“3. 过一会 LED 2 亮一下”是怎么产生的呢?
只有task_handset的延时减为0其才能进入就绪态啊
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

7
 
几个函数的实现如下:

void LED_flash(uint8 index)
{
    LED_on(index);
    delay_NS(LED_FLASH_KEEP_TIME);
    LED_off(index);
}

void delay_NS (uint32 delay)
{
    uint32 i;

    for (; delay > 0; delay--)
    {
        for (i = 0; i < NOP_WAIT; i++);
    }
}

void timer_init(void)
{
    T0TC = 0;      // 定时器设置为 0.
    T0PR = 0;      // 定时器不分频.
    T0MCR = 0x03;  // 设置 T0MR0 匹配后复位 T0TC, 并产生中断标志.
    T0MR0 = Fpclk/OS_TICKS_PER_SEC; // 0.05 sec.
    T0TCR = 0x01;  // 启动定时器.
}

LED_flash() 和 delay_NS() 只是通过空转来延时,不会中断或者 Delay。

我感觉也是,开始“2. LED1 闪烁,同时 LED 7 闪烁,说明 task_idle 运行正常,时钟中断函数运行正常;” 。

    ORZ ORZ ORZ ORZ ORZ ORZ ORZ
    ORZ ORZ ORZ ORZ ORZ ORZ ORZ
    ORZ ORZ ORZ ORZ ORZ ORZ ORZ
    ORZ ORZ ORZ ORZ ORZ ORZ ORZ
_O_ ORZ ORZ ORZ ORZ ORZ ORZ ORZ
|  ORZ ORZ ORZ ORZ ORZ ORZ ORZ
/ \ ORZ ORZ ORZ ORZ ORZ ORZ ORZ
    ORZ ORZ ORZ ORZ ORZ ORZ ORZ
    ORZ ORZ ORZ ORZ ORZ ORZ ORZ
    ORZ ORZ ORZ ORZ ORZ ORZ ORZ
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

8
 
是不是定时器0占用了系统时钟?
 
 
 

回复

84

帖子

0

TA的资源

一粒金砂(初级)

9
 
初学者呢 最近也有挺多麻烦的问题,想高人指点指点。不闲我麻烦就加QQ:946402368
 
 
 

回复

117

帖子

0

TA的资源

一粒金砂(中级)

10
 
你在void IRQ_Timer0(void) 里面重新启动了中断么?
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

11
 
中断优先级?
 
 
 

回复

65

帖子

0

TA的资源

一粒金砂(中级)

12
 
什么呀
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

13
 
接分是王道!
 
 
 

回复

65

帖子

0

TA的资源

一粒金砂(初级)

14
 
继续
 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

15
 
谢谢大家的支持!总于解决了。原因是 ZLG 的定时中断程序中已经实现了任务切换,其中调用的 uCOS 的函数OSIntExit() 中就不需要 切换了,否则堆栈就乱套了。

修改如下,去掉对 OSIntCtxSw() 的调用。

void  OSIntExit (void)
{
    INT8U      y;
#if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
    OS_CPU_SR  cpu_sr;
   
   

    cpu_sr = 0;                                            /* Prevent compiler warning                 */
#endif   
    if (OSRunning == TRUE) {
        OS_ENTER_CRITICAL();
        if (OSIntNesting > 0) {                            /* Prevent OSIntNesting from wrapping       */
            OSIntNesting--;
        }
        if (OSIntNesting == 0) {                           /* Reschedule only if all ISRs complete ... */
            if (OSLockNesting == 0) {                      /* ... and not locked.                      */
                y             = OSUnMapTbl[OSRdyGrp];         
                OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
                if (OSPrioHighRdy != OSPrioCur) {          /* No Ctx Sw if current task is highest rdy */
                    OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy];
#if OS_TASK_PROFILE_EN > 0
                    OSTCBHighRdy->OSTCBCtxSwCtr++;         /* Inc. # of context switches to this task  */
#endif
                    OSCtxSwCtr++;                          /* Keep track of the number of ctx switches */
                    // OSIntCtxSw();                          /* Perform interrupt level ctx switch       */
                }
            }
        }
        OS_EXIT_CRITICAL();
    }
}
 
 
 

回复

84

帖子

0

TA的资源

一粒金砂(初级)

16
 
恭喜啊,终于解决完了

论坛就应该这样,大家积极探讨
同时lz自己解决完了问题,也能把解决过程说出来
这样后来人在看到这个帖子的时候,才有它的价值
而不是仅仅为lz解决了个实际问题
更多的是这个帖子对于他人的借鉴意义

简单总结下就是
task_handset任务延时,普通切换
idle任务运行
第一次时钟中断,会尝试进行中断级的切换,但由于task_handset任务尚未就绪
中断返回至idle任务

第OS_TICKS_PER_SEC次时钟中断时,
假设ZLG 的定时中断程序先进行中断级切换
当前sp和pc入idle任务栈
弹出task_handset的sp和pc
OSIntExit 中再次进行切换,此时却将task_handset的sp和pc压入了idle任务中
当task_handset第二次运行完毕后,普通切换
但sp和pc却是handle的,因此出现问题

不知lz是否此意?
 
 
 

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

随便看看
查找数据手册?

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
快速回复 返回顶部 返回列表