RTOS中的任务通知
任务通知之前我们使用队列、信号量、事件组等方法来控制任务在这个过程当中我们都需要实现创建对应的结构体双方通过结构体来进行交流。同时我们还可以使用任务通知的方式来进行控制。优势效率更高使用任务通知来发送事件、数据给某个任务时效率更高。比队列、信号量、事件组都有大的优势。更节省内存使用其他方法时都要先创建对应的结构体使用任务通知时无需额外创建结构缺点不能发送数据给 ISR因为ISR没有任务结构体但是ISR可以使用任务通知的功能数据只能该任务独享无法缓冲数据任务结构体只有一个任务通知值只能保持一个数据无法广播给多个任务任务通知可以多对一但不能一对多如果发送受阻发送方不会进入阻塞状态等待对应代码已知任务都有对应的结构体TCB里面的两个数据一个是 uint8_t 类型用来表示通知状态一个是 uint32_t 类型用来表示通知值typedef struct tskTaskControlBlock { ...... /* configTASK_NOTIFICATION_ARRAY_ENTRIES 1 */ volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; ...... } tskTCB;其中的ucNotifyState有3种取值taskNOT_WAITING_NOTIFICATION任务没有在等待通知taskWAITING_NOTIFICATION任务在等待通知taskNOTIFICATION_RECEIVED任务接收到了通知也被称为 pending(有数据了待处理)任务通知的使用任务通知函数主要分为简化版和专业版简化版专业版发出通知xTaskNotifyGivevTaskNotifyGiveFromISRxTaskNotifyxTaskNotifyFromISR取出通知ulTaskNotifyTakexTaskNotifyWait简化版其中简化版当中发出通知可以使TCB当中的val加一并使通知状态变为pending取出通知则需要判断val的值如果为0则阻塞大于0则从阻塞态进入就绪态。函数原型BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify ); void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTa skWoken ); uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );主要讲解一下Take函数中参数的含义参数说明xClearCountOnExit函数返回前是否清零pdTRUE把通知值清零pdFALSE如果通知值大于 0则把通知值减一xTicksToWait任务进入阻塞态的超时时间它在等待通知值大于 0。0不等待即刻返回portMAX_DELAY一直等待直到通知值大于 0其他值Tick Count可以用 pdMS_TO_TICKS()把 ms 转换为 Tick Count返回值函数返回之前在清零或减一之前的通知值。如果 xTicksToWait 非 0则返回值有 2 种情况1. 大于 0在超时前通知值被增加了2. 等于 0一直没有其他任务增加通知值最后超时返回 0专业版xTaskNotify 函数功能更强大可以使用不同参数实现各类功能。BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyActio n eAction ); BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken ); BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );案例整体思路先让小车1动然后到达终点后同时2和3分别使用xTaskNotifyGive 和 xTaskNotify。小车1static void Car1Task (void *params) { struct car *car (struct car *) params; //直接右移小汽车 while(1) { if(car - x g_xres - CAR_LENGTH) { hideCar(car); car-x 1; if (car-x g_xres - CAR_LENGTH) { car-x g_xres - CAR_LENGTH; } showCar(car); } vTaskDelay(50); if(car -x g_xres - CAR_LENGTH) { /* 发送事件 */ //xEventGroupSetBits(g_xEventCar, 10); //发出通知 xTaskNotifyGive(g_TaskHandleCar2); xTaskNotify(g_TaskHandleCar3, 100, eSetValueWithOverwrite); vTaskDelete(NULL); } } }小车2static void Car2Task (void *params) { struct car *car (struct car *) params; //等待事件信号 //xEventGroupWaitBits(g_xEventCar, 1 0, pdTRUE, pdFALSE, portMAX_DELAY); //等待通知 ulTaskNotifyTake(pdTRUE, portMAX_DELAY); //直接右移小汽车 while(1) { if(car - x g_xres - CAR_LENGTH) { hideCar(car); car-x 1; if (car-x g_xres - CAR_LENGTH) { car-x g_xres - CAR_LENGTH; } showCar(car); } vTaskDelay(50); if(car -x g_xres - CAR_LENGTH) { /* 释放信号量 */ // xSemaphoreGive(g_xSemTicks); vTaskDelete(NULL); } } }完整代码/* * Project: N|Watch * Author: Zak Kemble, contactzakkemble.co.uk * Copyright: (C) 2013 by Zak Kemble * License: GNU GPL v3 (see License.txt) * Web: http://blog.zakkemble.co.uk/diy-digital-wristwatch/ */ #include stdlib.h #include stdio.h #include string.h #include cmsis_os.h #include FreeRTOS.h // ARM.FreeRTOS::RTOS:Core #include task.h // ARM.FreeRTOS::RTOS:Core #include event_groups.h // ARM.FreeRTOS::RTOS:Event Groups #include semphr.h // ARM.FreeRTOS::RTOS:Core #include draw.h #include resources.h #include driver_lcd.h #include driver_ir_receiver.h #include driver_rotary_encoder.h #include driver_mpu6050.h #define CAR_COUNT 3 #define CAR_WIDTH 12 #define CAR_LENGTH 15 #define ROAD_SPEED 6 #define NOINVERT false #define INVERT true #define key1 0 #define key2 1 #define key3 2 static uint32_t g_xres, g_yres, g_bpp; static uint8_t *g_framebuffer; static SemaphoreHandle_t g_xSemTicks; static EventGroupHandle_t g_xEventCar; static TaskHandle_t g_TaskHandleCar2; static TaskHandle_t g_TaskHandleCar3; struct car{ int x; int y; int control_key; }; struct car cars[3] { {0, 0, key1}, {0, 17, key2}, {0, 34, key3} }; static const byte carImg[] PROGMEM { 0x40,0xF8,0xEC,0x2C,0x2C,0x38,0xF0,0x10,0xD0,0x30,0xE8,0x4C,0x4C,0x9C,0xF0, 0x02,0x1F,0x37,0x34,0x34,0x1C,0x0F,0x08,0x0B,0x0C,0x17,0x32,0x32,0x39,0x0F, }; static const byte roadMarking[] PROGMEM { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, }; static const byte clearImg[30] {0}; static void showCar(struct car *car) { draw_bitmap(car-x, car-y, carImg, 15, 16, NOINVERT, 0); draw_flushArea(car-x, car-y, 15, 16); } static void hideCar(struct car *car) { draw_bitmap(car-x, car-y, clearImg, 15, 16, NOINVERT, 0); draw_flushArea(car-x, car-y, 15, 16); } # if 0 static void CarTask(void *params) { struct car *car (struct car *)params; //获得信号量 xSemaphoreTake(g_xSemTicks, portMAX_DELAY); while(1) { if(car-x g_xres - CAR_LENGTH) { hideCar(car); car-x 1; if (car-x g_xres - CAR_LENGTH) { car-x g_xres - CAR_LENGTH; } showCar(car); } vTaskDelay(50); if(car-x g_xres - CAR_LENGTH) { /* 释放信号量 */ xSemaphoreGive(g_xSemTicks); vTaskDelete(NULL); } } } #endif static void Car1Task (void *params) { struct car *car (struct car *) params; //直接右移小汽车 while(1) { if(car - x g_xres - CAR_LENGTH) { hideCar(car); car-x 1; if (car-x g_xres - CAR_LENGTH) { car-x g_xres - CAR_LENGTH; } showCar(car); } vTaskDelay(50); if(car -x g_xres - CAR_LENGTH) { /* 发送事件 */ //xEventGroupSetBits(g_xEventCar, 10); //发出通知 xTaskNotifyGive(g_TaskHandleCar2); xTaskNotify(g_TaskHandleCar3, 100, eSetValueWithOverwrite); vTaskDelete(NULL); } } } static void Car2Task (void *params) { struct car *car (struct car *) params; //等待事件信号 //xEventGroupWaitBits(g_xEventCar, 1 0, pdTRUE, pdFALSE, portMAX_DELAY); //等待通知 ulTaskNotifyTake(pdTRUE, portMAX_DELAY); //直接右移小汽车 while(1) { if(car - x g_xres - CAR_LENGTH) { hideCar(car); car-x 1; if (car-x g_xres - CAR_LENGTH) { car-x g_xres - CAR_LENGTH; } showCar(car); } vTaskDelay(50); if(car -x g_xres - CAR_LENGTH) { /* 释放信号量 */ // xSemaphoreGive(g_xSemTicks); vTaskDelete(NULL); } } } static void Car3Task (void *params) { struct car *car (struct car *) params; //等待事件信号 //xEventGroupWaitBits(g_xEventCar, 1 0, pdTRUE, pdFALSE, portMAX_DELAY); int val; xTaskNotifyWait(~0, ~0, val, portMAX_DELAY); //直接右移小汽车 while(1) { if(car - x g_xres - CAR_LENGTH) { hideCar(car); car-x 1; if (car-x g_xres - CAR_LENGTH) { car-x g_xres - CAR_LENGTH; } showCar(car); } vTaskDelay(50); if(car -x g_xres - CAR_LENGTH) { /* 释放信号量 */ //xSemaphoreGive(g_xSemTicks); vTaskDelete(NULL); } } } void car_test(void) { g_framebuffer LCD_GetFrameBuffer(g_xres, g_yres, g_bpp); draw_init(); draw_end(); //绘制路标 for(int i 0; i 3; i) { for(int j 0; j 8; j) { draw_bitmap(16 * j, 16 i * 17, roadMarking, 8, 1, NOINVERT, 0); draw_flushArea(16 * j, 16 i * 17, 8, 1); } } //测试显示三辆汽车 for(int i 0; i 3; i) { showCar(cars[i]); } /* g_xSemTicks xSemaphoreCreateCounting(3, 2); xTaskCreate(CarTask, Car1, 128, cars[0], osPriorityNormal, NULL); xTaskCreate(CarTask, Car2, 128, cars[1], osPriorityNormal, NULL); xTaskCreate(CarTask, Car3, 128, cars[2], osPriorityNormal, NULL); */ //创建事件组 //g_xEventCar xEventGroupCreate(); xTaskCreate(Car1Task, car1, 128, cars[0], osPriorityNormal, NULL); xTaskCreate(Car2Task, car2, 128, cars[1], osPriorityNormal2, g_TaskHandleCar2); xTaskCreate(Car3Task, car3, 128, cars[2], osPriorityNormal2, g_TaskHandleCar3); }
上一篇/下一篇内容由系统自动关联
返回资讯列表 →