加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

【RTX操作系统教程】第13章 事件标志组(下)

(2015-12-30 16:55:28)
标签:

cosiii

emwin

rtx

stm32f407

安富莱

分类: RTX及其中间件

第13章     事件标志组

前面的章节我们已经讲解了任务管理和时间管理,从本章节开始讲解任务间的通信和同步机制。首先讲解任务间的通信和同步机制之一,事件标志组。

本章教程配套的例子含Cortex-M3内核的STM32F103Cortex-M4内核的STM32F407

13.1 事件标志组

13.2 事件标志组API函数

13.3 实验例程说明(任务间通信)

13.4 实验例程说明(中断方式通信)

13.5       总结

13.4 实验例程说明(中断方式通信)

13.4.1  STM32F103开发板实验

配套例子:

V4-410_RTX实验_事件标志组(中断方式)

实验目的:

1. 学习RTX的事件标志组(中断方式)

实验内容:

1.     K1按键按下,串口打印。

2.     K2键按下,启动单次定时器中断,50ms后在定时器中断给任务AppTaskMsgPro发送事件标志,设置bit0

3.     K3键按下,启动单次定时器中断,50ms后在定时器中断给任务AppTaskMsgPro发送事件标志,设置bit1

4. 任务AppTaskMsgPro只有接收到bit0bit1都被设置了才执行串口打印信息。               

5. 各个任务实现的功能如下:

AppTaskUserIF任务  :按键消息处理。

AppTaskLED任务     LED闪烁。

AppTaskMsgPro任务 :消息处理,等待定时器中断发来的事件标志。

AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。

RTX配置:

RTX配置向导详情如下:

【RTX操作系统教程】第13章 <wbr>事件标志组(下)

 

u  Task Configuration

l  Number of concurrent running tasks

允许创建4个任务,实际创建了如下四个任务

              AppTaskUserIF任务   :按键消息处理。

              AppTaskLED任务     LED闪烁。

              AppTaskMsgPro任务 :消息处理,等待定时器中断发来的事件标志。

              AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。

l  Number of tasks with user-provided stack

创建的4个任务都是采用自定义堆栈方式。

RTX任务调试信息:

【RTX操作系统教程】第13章 <wbr>事件标志组(下)

 

u  Event Value:任务AppTaskMsgPro当前的事件标志数值。

u  Event Mask:任务AppTaskMsgPro等待的事件标志数值。

程序设计:

u  任务栈大小分配:

static uint64_t AppTaskUserIFStk[512/8];   

static uint64_t AppTaskLEDStk[256/8];      

static uint64_t AppTaskMsgProStk[512/8];  

static uint64_t AppTaskStartStk[512/8];     

将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。

u  系统栈大小分配:

【RTX操作系统教程】第13章 <wbr>事件标志组(下)

 

u  RTX初始化:

 

int main (void)

  

     

     bsp_Init();

    

     

     os_sys_init_user (AppTaskStart,             

                       4,                        

                       &AppTaskStartStk,         

                       sizeof(AppTaskStartStk));

     while(1);

}

u  RTX任务创建:

 

static void AppTaskCreate (void)

{

     HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             

                                          1,                         

                                          &AppTaskUserIFStk,         

                                           sizeof(AppTaskUserIFStk));

    

     HandleTaskLED = os_tsk_create_user(AppTaskLED,              

                                       2,                       

                                        &AppTaskLEDStk,          

                                        sizeof(AppTaskLEDStk));  

    

     HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             

                                          3,                         

                                          &AppTaskMsgProStk,         

                                           sizeof(AppTaskMsgProStk));

}

u  四个RTX任务的实现:

 

__task void AppTaskUserIF(void)

{

     uint8_t ucKeyCode;

 

    while(1)

    {

         ucKeyCode = bsp_GetKey();

        

         if (ucKeyCode != KEY_NONE)

         {

              switch (ucKeyCode)

              {

                   

                   case KEY_DOWN_K1:

                       printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");

                       break;  

                  

                   

                   case KEY_DOWN_K2:

                       printf("K2键按下,启动单次定时器中断,50ms后在定时器中断给任务AppTaskMsgPro发送事

件标志\r\n");

 

                       bsp_StartHardTimer(1 ,50000, (void *)TIM_CallBack1);

                       break;

                  

                   

                   case KEY_DOWN_K3:

                       printf("K3键按下,启动单次定时器中断,50ms后在定时器中断给任务AppTaskMsgPro发送事

件标志\r\n");

 

                       bsp_StartHardTimer(1 ,50000, (void *)TIM_CallBack2);

                       break;

 

                   

                   default:                    

                       break;

              }

         }

        

         os_dly_wait(20);

     }

}

 

 

__task void AppTaskLED(void)

{

     const uint16_t usFrequency = 200;

    

     

     os_itv_set(usFrequency);

    

    while(1)

    {

         bsp_LedToggle(2);

         bsp_LedToggle(3);

 

         

          os_itv_wait();

    }

}

 

 

__task void AppTaskMsgPro(void)

{

     OS_RESULT xResult;

     const uint16_t usMaxBlockTime = 500;

    

    while(1)

    {

         

         xResult = os_evt_wait_and (BIT_ALL, usMaxBlockTime);

        

         switch (xResult)

         {

              

              case OS_R_EVT:

                   printf("接收到bit0bit1都被设置的消息\r\n");

                   break;  

 

              

              case OS_R_TMO:

                   bsp_LedToggle(1);

                   bsp_LedToggle(4);

                   break;

             

              

              default:                    

                   break;

           

    }

}

 

 

__task void AppTaskStart(void)

{

     

     AppTaskCreate();

    

    while(1)

    {

         

         bsp_KeyScan();

        os_dly_wait(10);

    }

}

u  定时器中断回调函数中发送事件标志:

定时器中断的初始化和中断函数在bsp_timer.c文件中实现,这个不是教程的重点,故不作介绍。这里主要关心RTX的事件标志函数在中断服务程序中的使用方法。

 

static void TIM_CallBack1(void)

{

     

     isr_evt_set (BIT_0, HandleTaskMsgPro);

}

 

static void TIM_CallBack2(void)

{

     

     isr_evt_set (BIT_1, HandleTaskMsgPro);

}

13.4.2 STM32F407开发板实验

配套例子:

V5-410_RTX实验_事件标志组(中断方式)

实验目的:

1. 学习RTX的事件标志组(中断方式)

实验内容:

1.     K1按键按下,串口打印。

2.     K2键按下,启动单次定时器中断,50ms后在定时器中断给任务AppTaskMsgPro发送事件标志,设置bit0

3.     K3键按下,启动单次定时器中断,50ms后在定时器中断给任务AppTaskMsgPro发送事件标志,设置bit1

4.     任务AppTaskMsgPro只有接收到bit0bit1都被设置了才执行串口打印信息。               

5.     各个任务实现的功能如下:

AppTaskUserIF任务  :按键消息处理。

AppTaskLED任务     LED闪烁。

AppTaskMsgPro任务 :消息处理,等待定时器中断发来的事件标志。

AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。

RTX配置:

RTX配置向导详情如下:

【RTX操作系统教程】第13章 <wbr>事件标志组(下)

 

u  Task Configuration

l  Number of concurrent running tasks

允许创建4个任务,实际创建了如下四个任务

              AppTaskUserIF任务   :按键消息处理。

              AppTaskLED任务     LED闪烁。

              AppTaskMsgPro任务 :消息处理,等待定时器中断发来的事件标志。

              AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。

l  Number of tasks with user-provided stack

创建的4个任务都是采用自定义堆栈方式。

RTX任务调试信息:

【RTX操作系统教程】第13章 <wbr>事件标志组(下)

 

u  Event Value:任务AppTaskMsgPro当前的事件标志数值。

u  Event Mask:任务AppTaskMsgPro等待的事件标志数值。

程序设计:

u  任务栈大小分配:

static uint64_t AppTaskUserIFStk[512/8];   

static uint64_t AppTaskLEDStk[256/8];      

static uint64_t AppTaskMsgProStk[512/8];  

static uint64_t AppTaskStartStk[512/8];     

将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。

u  系统栈大小分配:

【RTX操作系统教程】第13章 <wbr>事件标志组(下)

 

u  RTX初始化:

 

int main (void)

  

     

     bsp_Init();

    

     

     os_sys_init_user (AppTaskStart,             

                       4,                        

                       &AppTaskStartStk,         

                       sizeof(AppTaskStartStk));

     while(1);

}

u  RTX任务创建:

 

static void AppTaskCreate (void)

{

     HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             

                                          1,                         

                                          &AppTaskUserIFStk,         

                                           sizeof(AppTaskUserIFStk));

    

     HandleTaskLED = os_tsk_create_user(AppTaskLED,              

                                       2,                       

                                        &AppTaskLEDStk,          

                                        sizeof(AppTaskLEDStk));  

    

     HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             

                                          3,                         

                                          &AppTaskMsgProStk,         

                                           sizeof(AppTaskMsgProStk));

}

u  四个RTX任务的实现:

 

__task void AppTaskUserIF(void)

{

     uint8_t ucKeyCode;

 

    while(1)

    {

         ucKeyCode = bsp_GetKey();

        

         if (ucKeyCode != KEY_NONE)

         {

              switch (ucKeyCode)

              {

                   

                   case KEY_DOWN_K1:

                       printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");

                       break;  

                  

                   

                   case KEY_DOWN_K2:

                       printf("K2键按下,启动单次定时器中断,50ms后在定时器中断给任务AppTaskMsgPro发送事

件标志\r\n");

 

                       bsp_StartHardTimer(1 ,50000, (void *)TIM_CallBack1);

                       break;

                  

                   

                   case KEY_DOWN_K3:

                       printf("K3键按下,启动单次定时器中断,50ms后在定时器中断给任务AppTaskMsgPro发送事

件标志\r\n");

 

                       bsp_StartHardTimer(1 ,50000, (void *)TIM_CallBack2);

                       break;

 

                   

                   default:                    

                       break;

              }

         }

        

         os_dly_wait(20);

     }

}

 

 

__task void AppTaskLED(void)

{

     const uint16_t usFrequency = 200;

    

     

     os_itv_set(usFrequency);

    

    while(1)

    {

         bsp_LedToggle(2);

         bsp_LedToggle(3);

 

         

         os_itv_wait();

    }

}

 

 

__task void AppTaskMsgPro(void)

{

     OS_RESULT xResult;

     const uint16_t usMaxBlockTime = 500;

    

    while(1)

    {

         

         xResult = os_evt_wait_and (BIT_ALL, usMaxBlockTime);

        

         switch (xResult)

         {

              

              case OS_R_EVT:

                   printf("接收到bit0bit1都被设置的消息\r\n");

                   break;  

 

              

              case OS_R_TMO:

                   bsp_LedToggle(1);

                   bsp_LedToggle(4);

                   break;

             

              

              default:                    

                   break;

           

    }

}

 

 

__task void AppTaskStart(void)

{

     

     AppTaskCreate();

    

    while(1)

    {

         

         bsp_KeyScan();

        os_dly_wait(10);

    }

}

u  定时器中断回调函数中发送事件标志:

定时器中断的初始化和中断函数在bsp_timer.c文件中实现,这个不是教程的重点,故不作介绍。这里主要关心RTX的事件标志函数在中断服务程序中的使用方法。

 

static void TIM_CallBack1(void)

{

     

     isr_evt_set (BIT_0, HandleTaskMsgPro);

}

 

static void TIM_CallBack2(void)

{

     

     isr_evt_set (BIT_1, HandleTaskMsgPro);

}

13.5总结

本章节就为大家讲解了任务间的通信和同步机制之一,事件标志组,初学者要稍花些时间将其掌握。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有