之前我们已经知道,优先级比较高的任务会把优先级比较低的认为短路掉,导致优先级低的任务无法执行,然而就有了改变优先级的方法.当然,也有获取优先级的方法,分别是vTaskPrioritySet和vTaskPriorityGet,接下来我们实验一下.
先创建两个任务,其中任务1的优先级比较高.使用最土的for循环大法,可以塞着任务.如果忘了,请看这个代码段:
static void LED1_Task( void *pvParameters ) { uint32_t i = 0; for( ;; ) { GPIO_ToggleBits(GPIOG, GPIO_Pin_13); for(i = 0; i < 0x5FFFFF; i++) { } } }
创建任务是否,LED1的等级比较高:
xTaskCreate( LED1_Task, ( const char * ) "LED1_Task", 1000, NULL, 2, NULL ); xTaskCreate( LED2_Task, ( const char * ) "LED2_Task", 1000, NULL, 1, &xTask2Handle );
然后在任务1返回自己的优先级:
static void LED1_Task( void *pvParameters ) { portBASE_TYPE uxPriority; uint32_t i = 0; uxPriority = uxTaskPriorityGet( NULL ); for( ;; ) { GPIO_ToggleBits(GPIOG, GPIO_Pin_13); for(i = 0; i < 0x5FFFFF; i++) { } } }
然后把任务2提升到自己的上面(先忽略xTask2Handle是怎么来的):
static void LED1_Task( void *pvParameters ) { portBASE_TYPE uxPriority; uint32_t i = 0; uxPriority = uxTaskPriorityGet( NULL ); for( ;; ) { GPIO_ToggleBits(GPIOG, GPIO_Pin_13); for(i = 0; i < 0x5FFFFF; i++) { } vTaskPrioritySet( xTask2Handle, ( uxPriority + 1 ) ); } }
LED2_Task一旦拥有最高优先级便启动执行(进入运行态),由于任何时候只可能有一个任务处于运行态,所以当LED2_Task运行时,LED1_Task处于就绪态.所以,执行LED2_Task时候,可以把优先级调回去.
static void LED2_Task( void *pvParameters ) { portBASE_TYPE uxPriority; uint32_t i = 0; uxPriority = uxTaskPriorityGet( NULL ); for( ;; ) { GPIO_ToggleBits(GPIOG, GPIO_Pin_14); for(i = 0; i < 0x5FFFFF; i++) { } vTaskPrioritySet( NULL, ( uxPriority - 2 ) ); } }
如此反复,那么xTask2Handle是什么,其实是一个预定义的变量(句柄变量).
xTaskHandle xTask2Handle;
这个在创建任务时候,以最后一个参数传递进去了.
xTaskCreate( LED2_Task, ( const char * ) "LED2_Task", 1000, NULL, 1, &xTask2Handle );
然后发现两个任务都在轮流执行,而不是"同时"执行了.再来说说删除,先把初始化时候大家优先级调整成一样的.并且执行任务1时,会把任务2删掉,如果删除命令传入NULL是删除自身.
static void LED1_Task( void *pvParameters ) { uint32_t i = 0; vTaskDelete(xTask2Handle); for( ;; ) { GPIO_ToggleBits(GPIOG, GPIO_Pin_13); for(i = 0; i < 0x5FFFFF; i++) { } } }
编译运行后灰发现LED2没任何反应,因为... 他已经被删掉了.任务基础管理,就到这里告一段落,这里就能基本地使用系统的最基础功能了.