打印
[uCOS/RTOS]

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

[复制链接]
3044|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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:
/*通信..交互*/
static void  App_Task_Agreement(void *p_arg)
{
  while(1)
  {
    drawerStateCtr(DRV_Unlock,0);//给设备0上电并保持x时间
    if(FRAME_OK()){
      HandleCommand();
    }
    //test();
    OSTimeDly(10);
  }
}


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

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


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

问题:
  • 出现上边这状况的原因?
  • 在写驱动程序时,是否应该脱离操作系统?(不使用操作系统的的资源,如OSTimeDly)
  • 在写ad驱动程序时,不可避免的要while(),如:
    void Set_Ads1256_Reset(void)
    {
            Write_SPI_One_Byte(ADS1256_RESET);//Reset to Power-Up Values
            while (GPIO_ReadInputDataBit(GPIOB,ADDRDY));//DRDY信号为高 开始自校验,为低表示自校验完成       
    }
    有一天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 | 只看该作者
延时函数不管在任何优先级的任务中都应该正常工作。看你的场景,我觉得最有可能的应该是移植的系统本身就有问题,也不排除有些你没有交代清楚的地方有问题。

使用特权

评论回复
5
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、写驱动程序,总会需要等待某些状态位。考虑到程序整体的健壮性,这里的等待,怎样处理更合适?

使用特权

评论回复
6
guozhongwei|  楼主 | 2015-11-19 15:19 | 只看该作者
john_lee 发表于 2015-11-18 23:37
延时函数不管在任何优先级的任务中都应该正常工作。看你的场景,我觉得最有可能的应该是移植的系统本身就有 ...

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

描述的只是我调试看到的现象:
1、drawerStateCtr测试函数 放到其他的任务中(非最高优先权的任务),正常。
2、drawerStateCtr测试函数 放到最高优先权的任务中,不正常。
我再琢磨琢磨,实在不行 上图。。。

使用特权

评论回复
7
w_乐天| | 2015-11-19 17:16 | 只看该作者
guozhongwei 发表于 2015-11-19 15:19
如果是---“移植的系统本身就有问题”  ---有什么测试方法不?

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

我调试驱动程序时也用了OSTimeDly()没有出现像楼主一样的问题(可能和优先级有关),还需要认真研究下使用OSTimeDly任务切换机制

使用特权

评论回复
8
john_lee| | 2015-11-19 22:37 | 只看该作者
创建两个任务,每个任务都这样做:while (1) { 翻转一个IO; 延时半秒; }
两个IO都接上LED。

使用特权

评论回复
9
guozhongwei|  楼主 | 2015-11-20 08:57 | 只看该作者
找到问题了,谢谢楼上的两位。

使用特权

评论回复
10
guozhongwei|  楼主 | 2015-11-20 09:30 | 只看该作者
本帖最后由 guozhongwei 于 2015-11-20 09:34 编辑

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

接口图

并转串 读数据 图

串转并写数据 图

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

u8 OC_Read_Byte(void)
{
  u8 n=0;
  u8 ocdata=0;
  SEL1_L;
  delay(10);
  ocdata |= GPIO_ReadInputDataBit(GPIOB,SPI_SDO)<<7;
  for(n=0;n<7;n++) //7¸
  {
    SCL_L;
    delay(10);
    SCL_H;
    ocdata |= GPIO_ReadInputDataBit(GPIOB,SPI_SDO)<<(6-n);
    delay(10);
  }
  SEL1_H;
  return ocdata;
}

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


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




使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

29

帖子

0

粉丝