[uCOS/RTOS] OSTimeDly在ucos最高优先级任务中,多次使用,有什么说法?

[复制链接]
 楼主| guozhongwei 发表于 2015-11-17 17:31 | 显示全部楼层 |阅读模式
ucos, TI, ST, os, FOR
最近弄得一个小模块,出现这么个情况(在最高优先级任务中):一个设备上电保持:OSTimeDly(500),没有动作。然而for(u16 i=0;i<50000;i++);(大概4--5ms),完成动作,也就是我要的效果。

实测,如果将代码放到其他的用户任务中(相对来说算是低优先级任务),一切安好.....

模块图:这东西控制电流方向可做活塞运动,,,

环境:IAR+cortex-M3+ucos   
其中:
1ms进入一次sysTick异常处理程序:#define OS_TICKS_PER_SEC       1000    /* Set the number of ticks in one second */--
内核时钟频率64MHz:
使用内部高速晶振HSI 提供时钟源动力:
  • RCC_HSICmd(ENABLE);  //使能内部高速晶振

           while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)== RESET);//等待HSI就绪

  • RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_16);/*设置PLL时钟源及倍频系数,频率为8/2*16=64Mhz*/
也就是说:OSTimeDly(500)---时机等待500ms


下边上测试代码:
app.c:
  1. /*通信..交互*/
  2. static void  App_Task_Agreement(void *p_arg)
  3. {
  4.   while(1)
  5.   {
  6.     drawerStateCtr(DRV_Unlock,0);//给设备0上电并保持x时间
  7.     if(FRAME_OK()){
  8.       HandleCommand();
  9.     }
  10.     //test();
  11.     OSTimeDly(10);
  12.   }
  13. }


设备驱动 opticalcoupler.c:
莫名其妙没效果的写法:
  1. /*
  2. 功能:锁定和解锁指定的电磁铁
  3. 参数:
  4. state:DRV_Lock/DRV_Unlock  锁定/解锁
  5. num:磁铁驱动编号
  6. */
  7. //u32 DRV_Lock   =0x01;
  8. //u32 DRV_Unlock  =0x02;

  9. void drawerStateCtr(u32 state,u8 num) //num:0--5 01
  10. {
  11.   //num=num-UnknownChange;//当UnknownChange=0,样品抽拉条编号[0--5];  UnknownChange=1,则编号[1--6]
  12.   u32 tmpVal = 0;
  13.   bitsClear(num);  //清除相应位
  14.   
  15.   tmpVal = ~(0xfffffffc | state);//
  16.   
  17.   state <<= (num*2);
  18.   tmpVal <<= (num*2+12);
  19.   drawerLock_UnlockState |= (tmpVal | state);
  20. <span style="background-color: lime;">  OC_DCT_DRV(drawerLock_UnlockState);//写控制,理解成给设备上电就好</span>
  21.   u32 cur1=OSTimeGet();
  22. <span style="background-color: red;">  OSTimeDly(500);//for(u16 i=0;i<50000;i++);//OSTimeDly(500);</span>
  23.   u32 cur2=OSTimeGet();
  24.   u32 diff= cur2-cur1; //<span style="background-color: red;">测试</span><span style="background-color: rgb(255, 0, 0);">OSTimeDly(500);的具体时间:结果确实是500ms</span>
  25.   bitsClear(num); //完成动作后,清除位置 防止持续供电发热
  26. }
drawerStateCtr函数中使用OSTimeDly延时等待,情况便是:叫电磁铁往上--不动,往下--不动。
感觉就像没收到OC_DCT_DRV指令一样,因为打上断点OSTimeDly,效果ok;当然咱说OSTimeDly没起作用,也挺像。


效果正常的代码:
  1. void drawerStateCtr(u32 state,u8 num) //num:0--5 01
  2. {
  3.   //num=num-UnknownChange;//当UnknownChange=0,样品抽拉条编号[0--5];  UnknownChange=1,则编号[1--6]
  4.   u32 tmpVal = 0;
  5.   bitsClear(num);  //清除相应位
  6.   
  7.   tmpVal = ~(0xfffffffc | state);//
  8.   
  9.   state <<= (num*2);
  10.   tmpVal <<= (num*2+12);
  11.   drawerLock_UnlockState |= (tmpVal | state);
  12.   OC_DCT_DRV(drawerLock_UnlockState);
  13.   u32 cur1=OSTimeGet();
  14. <span style="background-color: lime;">  for(u16 i=0;i<50000;i++);</span>//OSTimeDly(500);<span style="background-color: lime;">//看着反汇编代码,应该4--5ms的等待时间,效果正常</span>
  15.   u32 cur2=OSTimeGet();
  16.   u32 diff= cur2-cur1;
  17.   bitsClear(num); //完成动作后,清除位置 防止持续供电发热
  18. }
效果正常。

问题:
  • 出现上边这状况的原因?
  • 在写驱动程序时,是否应该脱离操作系统?(不使用操作系统的的资源,如OSTimeDly)
  • 在写ad驱动程序时,不可避免的要while(),如:
    1. void Set_Ads1256_Reset(void)
    2. {
    3.         Write_SPI_One_Byte(ADS1256_RESET);//Reset to Power-Up Values
    4.         while (GPIO_ReadInputDataBit(GPIOB,ADDRDY));//DRDY信号为高 开始自校验,为低表示自校验完成       
    5. }
    有一天ad烧了或是咋啦滴,咋办?大伙是怎么处理这类条件等待的?
先这些问题,,,大伙帮忙分析下,谢啦。





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| guozhongwei 发表于 2015-11-17 17:38 | 显示全部楼层
哪块没描述清楚,知会下..麻烦.  
littler 发表于 2015-11-18 22:49 | 显示全部楼层
不明白两个延时时间好像不一样呀,一个延时500ms,一个延时4~5ms。

AD坏了,整个功能估计也不正常了,最多给个错误提示。可以将GPIO信号改为中断方式,然后通过信号量控制。

ucos中使用for循环延时也不是好办法,比较使用ucos是为了提高效率
john_lee 发表于 2015-11-18 23:37 | 显示全部楼层
延时函数不管在任何优先级的任务中都应该正常工作。看你的场景,我觉得最有可能的应该是移植的系统本身就有问题,也不排除有些你没有交代清楚的地方有问题。
 楼主| guozhongwei 发表于 2015-11-19 14:55 | 显示全部楼层
littler 发表于 2015-11-18 22:49
不明白两个延时时间好像不一样呀,一个延时500ms,一个延时4~5ms。

AD坏了,整个功能估计也不正常了,最多 ...

问题:
1、OSTimeDly(500),只是为了突出下问题,延时等待本身就是为了上电保持,来完成动作。OSTimeDly(500)---500ms等待来完成动作,相对for()--实现5ms的等待,更能够凸显问题的所在:5ms完成,给500ms则肯定能够完成。然 结果很意外。
2、drawerStateCtr 这个函数 如果算在驱动程序部分,不应该使用操作系统提供的接口;不是驱动程序,应该随意使用操作系统提供的接口。----个人理解,各位评判。
3、写驱动程序,总会需要等待某些状态位。考虑到程序整体的健壮性,这里的等待,怎样处理更合适?
 楼主| guozhongwei 发表于 2015-11-19 15:19 | 显示全部楼层
john_lee 发表于 2015-11-18 23:37
延时函数不管在任何优先级的任务中都应该正常工作。看你的场景,我觉得最有可能的应该是移植的系统本身就有 ...

如果是---“移植的系统本身就有问题”  ---有什么测试方法不?

描述的只是我调试看到的现象:
1、drawerStateCtr测试函数 放到其他的任务中(非最高优先权的任务),正常。
2、drawerStateCtr测试函数 放到最高优先权的任务中,不正常。
我再琢磨琢磨,实在不行 上图。。。
w_乐天 发表于 2015-11-19 17:16 | 显示全部楼层
guozhongwei 发表于 2015-11-19 15:19
如果是---“移植的系统本身就有问题”  ---有什么测试方法不?

描述的只是我调试看到的现象:

我调试驱动程序时也用了OSTimeDly()没有出现像楼主一样的问题(可能和优先级有关),还需要认真研究下使用OSTimeDly任务切换机制
john_lee 发表于 2015-11-19 22:37 | 显示全部楼层
创建两个任务,每个任务都这样做:while (1) { 翻转一个IO; 延时半秒; }
两个IO都接上LED。
 楼主| guozhongwei 发表于 2015-11-20 08:57 | 显示全部楼层
找到问题了,谢谢楼上的两位。
 楼主| guozhongwei 发表于 2015-11-20 09:30 | 显示全部楼层
本帖最后由 guozhongwei 于 2015-11-20 09:34 编辑

自己的问题,与ucos系统无关。
我这个驱动板有一个通信接口,控制两个不同的片子74lv165和74HC595:

接口图

并转串 读数据 图

串转并写数据 图

在串转并写数据控制磁铁动作时,相关任务一但交出使用权,会在过程中调度另一个任务 并转串 读数据  读取 (我这边是一组光耦)数据,

  1. u8 OC_Read_Byte(void)
  2. {
  3.   u8 n=0;
  4.   u8 ocdata=0;
  5.   SEL1_L;
  6.   delay(10);
  7.   ocdata |= GPIO_ReadInputDataBit(GPIOB,SPI_SDO)<<7;
  8.   for(n=0;n<7;n++) //7¸
  9.   {
  10.     SCL_L;
  11.     delay(10);
  12.     SCL_H;
  13.     ocdata |= GPIO_ReadInputDataBit(GPIOB,SPI_SDO)<<(6-n);
  14.     delay(10);
  15.   }
  16.   SEL1_H;
  17.   return ocdata;
  18. }

这两个操作都会使用DCT_SCK时钟,导致drawerLock_UnlockState变量值没变动,而相应的 串转并写数据  的输出确向后移位啦。也就是造成上边提到的现象的主要原因。
另,至于将磁铁控制部分放于其他的任务中(非最高优先权任务)可行原因,目测:任务交出cpu,然后可能经过最高优先权的任务(如果就绪),其他....然后切换到读光耦任务时(会把串转并写数据 移位啦),上电保持已经足够完成电磁铁动作,至少大部分情况是这样,导致没有应有的现象。


ps:
事出必有因,看到的未必是真的。。。。
当初看到上边的现象,直观反映:“这不科学啊”。切换任务并没有造成drawerLock_UnlockState变化,为啥子就不行呢?原来,原来.....




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

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

本版积分规则

2

主题

29

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部