打印
[uCOS/RTOS]

亮点的UCOS中断中POST到任务中处理的时间计算实验

[复制链接]
1558|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
llpanda|  楼主 | 2013-12-31 20:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
对于RTOS来说,当外部事件发生的时候,触发中断,而从中断中通过POST信号量或消息等事件来让任务处理,是保证系统实时性的关键所在!我测试了这个时间是3-4微秒,一般的实时性足够了!有些话哪一本书都没有说,但是我想LABROSS老先生是很清楚的。

实验的平台是亮点STM32开发板
关键:中断服务程序运行在系统模式,特权级别;任务是用户程序,线程模式,可以是特权级别也可以是用户级别
/*实验
需求说明:从串口1采集数据 数据格式 0XFA 10个数据值 0XFF
       例如 FA 01 02 03 04 05 06 07 08 09 0A FF
  将采集到的10组数据送回串口,并显示在屏幕上
  要求:因为数据采集速度要求很快,不能等待
    分析:方法2:可采用双缓冲完成该需求,采集数据采用DMA方式,DMA中断服务程序中提交信号量给任务
        创建一个任务用于处理和显示数据
  优点:CPU占用率更低,基本在跑空闲任务
  亮点嵌入式 UCOS实验
  请将 FA 01 02 03 04 05 06 07 08 09 0A FF 发送到串口,将显示在屏幕上!
  附加功能:从系统模式下的中断中提交到线程模式下的用户任务处理,到底要多久呢?
  在这个例程中做了一个测试,测试的结果是3微妙
  方法:中断ISR中POST后设置定时器计数频率1微秒
        PEND信号量的任务在复活后马上关闭定时器,取计数值      
*/
主程序代码:
int main(void)
{               
INT8U  os_err;
os_err=os_err;
bpboard_init();//初始化硬件
   //bp_selfcheck(1);
OSInit(); //初始化UCOS
os_err = OSTaskCreate((void (*)(void *)) App_TaskStart,  // 创建启动任务
                          (void          * ) 0,     
                          (OS_STK        * )&App_TaskStartStk[APP_TASK_START_STK_SIZE - 1],    //堆栈地址
                          (INT8U           ) APP_TASK_START_PRIO); //优先级3,最高
os_err = OSTaskCreate((void (*)(void *)) App_TaskProc,  /* 处理任务  */
                          (void          * ) 0,
                          (OS_STK        * )&App_TaskProcStk[APP_TASK_PROC_STK_SIZE - 1],
                          (INT8U           ) APP_TASK_PROC_PRIO);
    FontSize(32);
LcdPrintStr("亮点嵌入式学习平台STM32/UCOS/UCGUI",10,50,RED,WHITE,1);
LcdPrintStr("请将 FA 01 02 03 04 05 06 07 08 09 0A FF 发送到串口,将显示在屏幕上!",10,80,RED,WHITE,1);
LcdPrintStr("会自动计算中断到来到处理的时间间隔!",10,80,RED,WHITE,1);
     FontSize(16);
OSStart();  
return(0);
}


处理任务代码:
static  void  App_TaskProc(void *p_arg)
{
INT8U err;
uint16_t Counter;
u8 i;
u16 line=10;
   MyEventSem=OSSemCreate(0);
    if (MyEventSem==(OS_EVENT *)0)
{
  printf("task rece failed to create sem!\r\n");
  OSTaskDel(OS_PRIO_SELF);
     return;
}
dma5_configuration();
while(1)
{
  OSSemPend(MyEventSem,0,&err);
  //这里获得计数器值,然后关闭计数器
  TIM_Cmd(TIM1, DISABLE);
  Counter=TIM1->CNT;
  LcdClear(WHITE);
  LcdPrintf(10,10,RED,WHITE,"从中断发生到离开中断到此处处理时间是:%d微秒",Counter);
  led_on2;
  if (USART1_BUF[PROCBUF][0]!=0xFA)
  {
   printf("the start byte is not 0xFA!\r\n");
  }
  line=20;
  for(i=1;i<11;i++)
  {   
   printf("%d ",USART1_BUF[PROCBUF][i]);
    if (TFT_SUPPORT)
   { LcdPrintf(10,30+line,RED,WHITE,"NO %i is:%d",i,USART1_BUF[PROCBUF][i]);
    line+=20;}   
      }
  printf("\r\n");
  led_off2;
}
}
中断ISR代码:
void DMA1_Channel5_IRQHandler(void)
{
    u8 t;
if(DMA_GetITStatus(DMA1_IT_TC5)) //通道5传输完成中断
     {
  DMA_ClearITPendingBit(DMA1_IT_GL5);    //清除中断等待标志  
  OSIntEnter();
        t=RECEBUF;   //交换缓冲区指针
  RECEBUF=PROCBUF;
  PROCBUF=t;            
     DMA_InitStructure5.DMA_MemoryBaseAddr = (u32)(&(USART1_BUF[RECEBUF][0]));
        DMA_Init(DMA1_Channel5, &DMA_InitStructure5); //重新配置缓冲区
  OSSemPost(MyEventSem);//修改为提交信号量 DMARECE=1;通知主程序,该发送数据了!
  TIM1_Int_Init(1000000);//启动定时器1,用来做计数器,以微秒为单位
  //65535微秒才记满
  OSIntExit();    //有信号量提交,因此该中断服务程序需包含  OSIntEnter();  OSIntExit();
     }
}

这样,屏幕上打印出3微妙,实际是计数3次,未到第4次,就是4微妙以内!


相关帖子

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

本版积分规则

6

主题

38

帖子

1

粉丝