困扰半个月的问题:ucOS中,第2次调用OSTimeDly()死机

jianshe999 2008-04-15 12:17:36
我按照步骤把 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 就死机了,不知道为什么。


跪求高手指点迷津????
...全文
2138 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
华仔0322 2012-03-10
  • 打赏
  • 举报
回复
目前正因在...Hook函数中调用OSTimeDlyHMSM()函数而死机中 不知是否是因为如此 学习!!
jianshe999 2008-06-03
  • 打赏
  • 举报
回复
谢谢大家的支持!总于解决了。原因是 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();
}
}
杨帆_8318 2008-06-03
  • 打赏
  • 举报
回复
恭喜啊,终于解决完了

论坛就应该这样,大家积极探讨
同时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是否此意?
kimishen 2008-05-06
  • 打赏
  • 举报
回复
继续
meiZiNick 2008-05-01
  • 打赏
  • 举报
回复
什么呀
UltraBejing 2008-05-01
  • 打赏
  • 举报
回复
接分是王道!
zhujinqiang 2008-04-22
  • 打赏
  • 举报
回复
中断优先级?
ivylang 2008-04-22
  • 打赏
  • 举报
回复
因为 LED 2 能亮第二次,所以说明时间中断应该是没有问题
应该是LED2第二次亮后,接着调OSTimeDly(OS_TICKS_PER_SEC),发生任务切换时发生的错误,所以觉得这个问题归根结底是移植代码出现问题,特别是堆栈处理。
写移植代码经常会看到这样的情况:刚开始程序好像运行得很正常,但不久就跑飞了,也就是上面说的死机
manji520 2008-04-21
  • 打赏
  • 举报
回复
初学者呢 最近也有挺多麻烦的问题,想高人指点指点。不闲我麻烦就加QQ:946402368
杨帆_8318 2008-04-21
  • 打赏
  • 举报
回复
你在void IRQ_Timer0(void) 里面重新启动了中断么?
jianshe999 2008-04-18
  • 打赏
  • 举报
回复
几个函数的实现如下:

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
sherlock_lai1 2008-04-18
  • 打赏
  • 举报
回复
是不是定时器0占用了系统时钟?
杨帆_8318 2008-04-17
  • 打赏
  • 举报
回复
中断中 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其才能进入就绪态啊
withoneheart 2008-04-17
  • 打赏
  • 举报
回复
fighting
jianshe999 2008-04-17
  • 打赏
  • 举报
回复
高手都藏在哪啊?????
jianshe999 2008-04-16
  • 打赏
  • 举报
回复
请问中断为什么不来了?哪些地方会影响?
谢谢!
nancyk2h 2008-04-15
  • 打赏
  • 举报
回复
我觉得是不是中断不来了?
因为OSTimeDly是按照多少个tick后允许任务切换。
并且你的TimeTisk是挂在IRQ0上的。
所以是不是中断不来。造成任务没有切换?

21,597

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧