• STM32F4X UCOSIII 事件集



    事件在RTOS中也是一种任务间同步的机制,事件不能传递数据。跟信号量不同的是,事件可以实现一对多,多对多的同步,也就是一个事件可以唤醒多个任务,一个任务也可以等待多个事件,也可以是几个事件都发生后才唤醒任务进行事件处理。同样,也可以是多个任务同步多个事件。

    事件的应用场景

    • 场景1:P1需要坐公交车去某地,只有A公交可以去目的地,此时P1必须等到A公交到达后才可以出发。
    • 场景2:P1需要坐公交车去某地,有A公交和B公交可以去目的地,此时P1只需等到A公交或者B公交到达后才可以出发。
    • 场景3:P1约定和P2一起去某地,可以乘坐A公交和B公交去目的地,此时P1必须等待P2和公交到达才可以出发

    在上述的几个场景中,我们可以将P1当做任务1,乘坐公交为事件1,同伴P2为事件2。则场景1为特定事件唤醒任务,场景2为任意事件唤醒任务,场景3为多个事件同时发生唤醒任务。

    UCOSIII事件工作机制

    在UCOSIII中每一个事件对象都定义了一个32位的事件标志位,也就是说每一个事件对象最多可以产生32个事件。当事件标志位为1时,则代表该事件发生,当事件标志位为0时,则代表该事件没有发生。下图就是一个事件对象里面的事件表示位,bit1/4/6/31被置1,则代表事件1、事件4、事件6和事件31发生。
    在这里插入图片描述
    假设现在有两个任务,任务1的唤醒条件是事件3或者事件5中的任意一个被置位,而任务2的唤醒条件是事件3和事件5同时发生。当事件3发生时,任务1会被唤醒,此时因为事件5还没发生,所以任务2没有被唤醒。当任务5发生时,任务2才会被唤醒。当任务接收到事件后,可以选择清除或者不清除事件标志位,当选择清除事件标志位后,改事件标志位就会被清0,如果选择不清除事件标志位,则该事件会一直存在。
    在这里插入图片描述

    UCOSIII事件操作函数

    事件创建函数

    /*
    *p_grp:事件类型对象
    *p_name:事件对象名字
    *flags:初始化的事件标志位,通常为0
    *p_err:错误代码
    */
    void  OSFlagCreate (OS_FLAG_GRP  *p_grp,
                        CPU_CHAR     *p_name,
                        OS_FLAGS      flags,
                        OS_ERR       *p_err)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    事件删除函数

    /*
    *p_grp:事件类型对象
    *opt:用户选项
    *p_err:错误代码
    */
    OS_OBJ_QTY  OSFlagDel (OS_FLAG_GRP  *p_grp,
                           OS_OPT        opt,
                           OS_ERR       *p_err)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    opt可以选择OS_OPT_DEL_NO_PENDOS_OPT_DEL_ALWAYS

    • OS_OPT_DEL_NO_PEND:删除事件,如果该事件上有挂起的任务,则等待挂起的任务恢复才删除
    • OS_OPT_DEL_ALWAYS:不管该事件上是否有挂起的任务,直接删除事件

    事件发送函数

    /*
    *p_grp:事件类型对象
    *flags:需要发送的事件
    *opt:用户选项
    *p_err:错误代码
    返回值:返回事件标志位的值
    */
    OS_FLAGS  OSFlagPost (OS_FLAG_GRP  *p_grp,
                          OS_FLAGS      flags,
                          OS_OPT        opt,
                          OS_ERR       *p_err)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    opt可以选择OS_OPT_POST_FLAG_SET、OS_OPT_POST_FLAG_CLR和OS_OPT_POST_NO_SCHED

    • OS_OPT_POST_FLAG_SET:设置事件为置1触发
    • OS_OPT_POST_FLAG_CLR:设置事件为清0触发
    • OS_OPT_POST_NO_SCHED:发生事件后不调度

    事件接收函数

    /*
    *p_grp:事件类型对象
    *flags:需要接收的事件
    *timeout:超时等待时间
    *opt:用户选项
    *p_ts:时间戳
    *p_err:错误代码
    返回值:返回接收到的事件标志位的值
    */
    OS_FLAGS  OSFlagPend (OS_FLAG_GRP  *p_grp,
                          OS_FLAGS      flags,
                          OS_TICK       timeout,
                          OS_OPT        opt,
                          CPU_TS       *p_ts,
                          OS_ERR       *p_err)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    opt可以选择OS_OPT_PEND_FLAG_CLR_ALL、OS_OPT_PEND_FLAG_CLR_ANY、OS_OPT_PEND_FLAG_SET_ALL、OS_OPT_PEND_FLAG_SET_ANY、OS_OPT_PEND_FLAG_CONSUME、OS_OPT_PEND_NON_BLOCKING和OS_OPT_PEND_BLOCKING

    • OS_OPT_PEND_FLAG_CLR_ALL:等待事件中所有位被清除
    • OS_OPT_PEND_FLAG_CLR_ANY:等待事件中任意的位被清除
    • OS_OPT_PEND_FLAG_SET_ALL:等待事件中所有位被置1
    • OS_OPT_PEND_FLAG_SET_ANY:等待事件中任意的位被置1
    • OS_OPT_PEND_FLAG_CONSUME:任务被唤醒后是否将标志位清除
    • OS_OPT_PEND_BLOCKING:阻塞等待事件,除非事件发生,否则任务不会恢复
    • OS_OPT_PEND_NON_BLOCKING:不阻塞等待事件,如果任务等待时间超过设定的超时时间,任务会恢复并返回一个错误代码

    UCOSIII事件例程

    /*
    *********************************************************************************************************
    *                                              EXAMPLE CODE
    *
    *                             (c) Copyright 2013; Micrium, Inc.; Weston, FL
    *
    *                   All rights reserved.  Protected by international copyright laws.
    *                   Knowledge of the source code may not be used to write a similar
    *                   product.  This file may only be used in accordance with a license
    *                   and should not be redistributed in any way.
    *********************************************************************************************************
    */
    
    /*
    *********************************************************************************************************
    *
    *                                            EXAMPLE CODE
    *
    *                                       IAR Development Kits
    *                                              on the
    *
    *                                    STM32F429II-SK KICKSTART KIT
    *
    * Filename      : app.c
    * Version       : V1.00
    * Programmer(s) : YS
    *********************************************************************************************************
    */
    
    /*
    *********************************************************************************************************
    *                                             INCLUDE FILES
    *********************************************************************************************************
    */
    
    #include  
    
    /*
    *********************************************************************************************************
    *                                            LOCAL DEFINES
    *********************************************************************************************************
    */
    
    
    /*
    *********************************************************************************************************
    *                                       LOCAL GLOBAL VARIABLES
    *********************************************************************************************************
    */
    #define EVENT1_FLAG (1 << 0) // 事件1标志位
    #define EVENT2_FLAG (1 << 1) // 事件2标志位
    #define EVENT3_FLAG (1 << 2) // 事件3标志位
    #define EVENT4_FLAG (1 << 3) // 事件4标志位 
    /* ----------------- APPLICATION GLOBALS -------------- */
    static  OS_TCB   AppTaskStartTCB;
    static  CPU_STK  AppTaskStartStk[APP_CFG_TASK_START_STK_SIZE];
    
    #define APPTASK1NAME    "App Task1"
    #define APP_TASK1_PRIO          3   
    #define APP_TASK1_STK_SIZE 1024
    static OS_TCB AppTask1TCB;
    static void  AppTask1  (void *p_arg);
    static CPU_STK AppTask1Stk[APP_TASK1_STK_SIZE];
    
    #define APPTASK2NAME    "App Task2"
    #define APP_TASK2_PRIO          4   
    #define APP_TASK2_STK_SIZE 1024
    static OS_TCB AppTask2TCB;
    static void  AppTask2  (void *p_arg);
    static CPU_STK AppTask2Stk[APP_TASK2_STK_SIZE];
    
    #define APPTASK3NAME    "App Task3"
    #define APP_TASK3_PRIO          4   
    #define APP_TASK3_STK_SIZE 1024
    static OS_TCB AppTask3TCB;
    static void  AppTask3  (void *p_arg);
    static CPU_STK AppTask3Stk[APP_TASK3_STK_SIZE];
    static OS_FLAG_GRP grp;
    /*
    *********************************************************************************************************
    *                                         FUNCTION PROTOTYPES
    *********************************************************************************************************
    */
    
    static  void  AppTaskStart          (void     *p_arg);
    
    
    /*
    *********************************************************************************************************
    *                                                main()
    *
    * Description : This is the standard entry point for C code.  It is assumed that your code will call
    *               main() once you have performed all necessary initialization.
    *
    * Arguments   : none
    *
    * Returns     : none
    *********************************************************************************************************
    */
    
    int main(void)
    {
    
        OS_ERR  err;
    
    
        OSInit(&err);                                               /* Init uC/OS-III.                                      */
       
        OSTaskCreate((OS_TCB       *)&AppTaskStartTCB,              /* Create the start task                                */
                     (CPU_CHAR     *)"App Task Start",
                     (OS_TASK_PTR   )AppTaskStart,
                     (void         *)0u,
                     (OS_PRIO       )APP_CFG_TASK_START_PRIO,
                     (CPU_STK      *)&AppTaskStartStk[0u],
                     (CPU_STK_SIZE  )AppTaskStartStk[APP_CFG_TASK_START_STK_SIZE / 10u],
                     (CPU_STK_SIZE  )APP_CFG_TASK_START_STK_SIZE,
                     (OS_MSG_QTY    )0u,
                     (OS_TICK       )0u,
                     (void         *)0u,
                     (OS_OPT        )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                     (OS_ERR       *)&err);
    
        OSStart(&err);                                              /* Start multitasking (i.e. give control to uC/OS-III). */
    
    
    }
    
    
    /*
    *********************************************************************************************************
    *                                          STARTUP TASK
    *
    * Description : This is an example of a startup task.  As mentioned in the book's text, you MUST
    *               initialize the ticker only once multitasking has started.
    *
    * Arguments   : p_arg   is the argument passed to 'AppTaskStart()' by 'OSTaskCreate()'.
    *
    * Returns     : none
    *
    * Notes       : 1) The first line of code is used to prevent a compiler warning because 'p_arg' is not
    *                  used.  The compiler should not generate any code for this statement.
    *********************************************************************************************************
    */
    
    static  void  AppTaskStart (void *p_arg)
    {
        CPU_INT32U  cpu_clk_freq;
        CPU_INT32U  cnts;
        OS_ERR      err;
    
    
       (void)p_arg;
    
        BSP_Init();                      
        CPU_Init();                                                 /* Initialize the uC/CPU services                       */
    
        cpu_clk_freq = BSP_CPU_ClkFreq();                           /* Determine SysTick reference freq.                    */
        cnts         = cpu_clk_freq                                 /* Determine nbr SysTick increments                     */
                     / (CPU_INT32U)OSCfg_TickRate_Hz;
    
        OS_CPU_SysTickInit(cnts);                                   /* Init uC/OS periodic time src (SysTick).              */
    
        Mem_Init();                                                 /* Initialize memory managment module                   */
        Math_Init();                                                /* Initialize mathematical module                       */
    
    
    #if OS_CFG_STAT_TASK_EN > 0u
        OSStatTaskCPUUsageInit(&err);                               /* Compute CPU capacity with no task running            */
    #endif
    
    #ifdef CPU_CFG_INT_DIS_MEAS_EN
        CPU_IntDisMeasMaxCurReset();
    #endif
    
    
    #if (APP_CFG_SERIAL_EN == DEF_ENABLED)
        App_SerialInit();                                           /* Initialize Serial communication for application ...  */
    #endif
    	
    
    	OSTaskCreate((OS_TCB     *)&AppTask1TCB,  // 线程TCB              
    			 (CPU_CHAR   *)APPTASK1NAME, // 线程名字
    			 (OS_TASK_PTR ) AppTask1, // 线程入口函数
    			 (void       *) "TASK1", // 线程参数
    			 (OS_PRIO     ) APP_TASK1_PRIO, // 线程优先级
    			 (CPU_STK    *)&AppTask1Stk[0], // 线程栈起始地址
    			 (CPU_STK_SIZE) APP_TASK1_STK_SIZE / 10, // 栈深度的限制位置
    			 (CPU_STK_SIZE) APP_TASK1_STK_SIZE, // 栈大小
    			 (OS_MSG_QTY  ) 5u, // 最大的消息个数
    			 (OS_TICK     ) 0u, // 时间片
    			 (void       *) 0, // 向用户提供的内存位置的指针
    			 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), // 线程特定选项
    			 (OS_ERR     *)&err); // 错误标志
    	if(OS_ERR_NONE == err)
    		printf("%s Create Success\r\n",APPTASK1NAME);
    	else
    		printf("%s Create Error\r\n",APPTASK1NAME);
    	
    			 
    	OSTaskCreate((OS_TCB     *)&AppTask2TCB,  // 线程TCB              
    			 (CPU_CHAR   *)APPTASK2NAME, // 线程名字
    			 (OS_TASK_PTR ) AppTask2, // 线程入口函数
    			 (void       *) "TASK2", // 线程参数
    			 (OS_PRIO     ) APP_TASK2_PRIO, // 线程优先级
    			 (CPU_STK    *)&AppTask2Stk[0], // 线程栈起始地址
    			 (CPU_STK_SIZE) APP_TASK2_STK_SIZE / 10, // 栈深度的限制位置
    			 (CPU_STK_SIZE) APP_TASK2_STK_SIZE, // 栈大小
    			 (OS_MSG_QTY  ) 5u, // 最大的消息个数
    			 (OS_TICK     ) 0u, // 时间片
    			 (void       *) 0, // 向用户提供的内存位置的指针
    			 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), // 线程特定选项
    			 (OS_ERR     *)&err); // 错误标志
    	if(OS_ERR_NONE == err)
    		printf("%s Create Success\r\n",APPTASK2NAME);
    	else
    		printf("%s Create Error\r\n",APPTASK2NAME);
    	
    	OSTaskCreate((OS_TCB     *)&AppTask3TCB,  // 线程TCB              
    			 (CPU_CHAR   *)APPTASK3NAME, // 线程名字
    			 (OS_TASK_PTR ) AppTask3, // 线程入口函数
    			 (void       *) "TASK3", // 线程参数
    			 (OS_PRIO     ) APP_TASK3_PRIO, // 线程优先级
    			 (CPU_STK    *)&AppTask3Stk[0], // 线程栈起始地址
    			 (CPU_STK_SIZE) APP_TASK3_STK_SIZE / 10, // 栈深度的限制位置
    			 (CPU_STK_SIZE) APP_TASK3_STK_SIZE, // 栈大小
    			 (OS_MSG_QTY  ) 5u, // 最大的消息个数
    			 (OS_TICK     ) 0u, // 时间片
    			 (void       *) 0, // 向用户提供的内存位置的指针
    			 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), // 线程特定选项
    			 (OS_ERR     *)&err); // 错误标志
    	if(OS_ERR_NONE == err)
    		printf("%s Create Success\r\n",APPTASK3NAME);
    	else
    		printf("%s Create Error\r\n",APPTASK3NAME);
    			 
    	OSFlagCreate(&grp,"flag",0,&err);
    	if(OS_ERR_NONE == err)
    		printf("Flag Create Success\r\n");
    	else
    		printf("Flag Create Error\r\n");
    	
    	OSTaskDel ( & AppTaskStartTCB, & err );		 
    
    }
    
    static void  AppTask1  (void *p_arg)
    {
        OS_ERR      err;
    	static CPU_INT32U i = 0;
    	while(DEF_TRUE)
    	{
    		
    		OSTimeDly ( 1000, OS_OPT_TIME_DLY, & err ); // 1s运行一次
    		OSFlagPost(&grp,EVENT1_FLAG | EVENT2_FLAG,OS_OPT_POST_FLAG_SET,&err); // 将事件1和事件2设置为置1触发
    	
    		
    		
    		OSTimeDly ( 1000, OS_OPT_TIME_DLY, & err ); // 1s运行一次
    		if(i % 2 == 0)
    			OSFlagPost(&grp,EVENT3_FLAG,OS_OPT_POST_FLAG_CLR,&err); // 将事件3设置为清0触发
    		else
    			OSFlagPost(&grp,EVENT4_FLAG,OS_OPT_POST_FLAG_CLR,&err); // 将事件4设置为清0触发
    		i++;
    
    		
    		
    	}
    	
    }
    static void  AppTask2  (void *p_arg)
    {
        OS_ERR      err;
    	OS_FLAGS flag;
    	while(DEF_TRUE)
    	{
    		flag = OSFlagPend(&grp,EVENT1_FLAG | EVENT2_FLAG,0,OS_OPT_PEND_FLAG_SET_ALL | OS_OPT_PEND_FLAG_CONSUME | OS_OPT_PEND_BLOCKING,0,&err); // 同时接收事件1和事件2
    		if(OS_ERR_NONE == err)
    			printf("%s Flag Recv Success flag = %d\r\n",__func__,flag); // 接收成功打印出接收到事件值
    		else
    			printf("%s Flag Recv Error\r\n",__func__);
    		
    	}
    	
    }
    static void  AppTask3  (void *p_arg)
    {
        OS_ERR      err;
    	OS_FLAGS flag;
    	while(DEF_TRUE)
    	{
    		flag = OSFlagPend(&grp,EVENT3_FLAG | EVENT4_FLAG ,0,OS_OPT_PEND_FLAG_CLR_ANY | OS_OPT_PEND_FLAG_CONSUME | OS_OPT_PEND_BLOCKING,0,&err); // 接收事件3或者事件4
    		if(OS_ERR_NONE == err)
    			printf("%s Flag Recv Success  flag = %d\r\n",__func__,flag); // 接收成功打印出接收到事件值
    		else
    			printf("%s Flag Recv Error\r\n",__func__);
    	}
    	
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299

    在这里插入图片描述

  • 相关阅读:
    MySQL常用函数汇总(字符串、时间函数等)
    使用ollama分别在我的window、mac、小米手机上部署体验llama3-8b
    nginx的所有知识点以及使用
    makefile基础(构建多文件程序)
    Linux输出文件夹下所有文件的完整路径shell脚本
    【正点原子 linux 驱动编程】
    Echarts 配置项 series 中的 data 是多维度
    基于C51的中断系统控制
    GoLong的学习之路(四)语法之循环语句
    企业电子招投标采购系统源码之电子招投标的组成
  • 原文地址:https://blog.csdn.net/hwx1546/article/details/133157924