1.故障描述
今天在学习FreeRTOS操作系统关于计数量信号实验这一块的时候遇到了一个非常有意思的实验现象。
就是程序任务的启动流程都是设置正确的,但是两任务会有一个任务进不去。
程序代码如下
#include "bsp_config.h"
#include "bsp_led.h"
#include "bsp_usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "bsp_key.h"
#include "semphr.h"
void BSP_Init(void);
void AppTaskCreate(void* pvParameters);
void Take_Task(void* pvParameters);
void Give_Task(void* pvParameters);
TaskHandle_t AppTaskCreate_Handle;
TaskHandle_t Take_Task_Handle;
TaskHandle_t Give_Task_Handle;
SemaphoreHandle_t CountSem_Handle;
int main(void)
{
float image_y, image_x, image_a;
BSP_Init();
for (image_y = 1.5f;image_y > -1.5f;image_y -= 0.1f)
{
for (image_x = -1.5f;image_x < 1.5f;image_x += 0.05f)
{
image_a = image_x*image_x + image_y*image_y - 1;
putchar(image_a*image_a*image_a - image_x*image_x*image_y*image_y*image_y <= 0.0f ? '*' : ' ');
}
putchar('\n');
}
xTaskCreate ((TaskFunction_t )AppTaskCreate,
(const char * )"AppTaskCreate",
(uint16_t )512,
(void * )NULL,
(UBaseType_t )1,
(TaskHandle_t * )&AppTaskCreate_Handle);
vTaskStartScheduler();
}
void AppTaskCreate(void* pvParameters)
{
taskENTER_CRITICAL();
CountSem_Handle=xSemaphoreCreateCounting( 5, 5 );
xTaskCreate ((TaskFunction_t )Take_Task,
(const char * )"Take_Task",
(uint16_t )512,
(void * )NULL,
(UBaseType_t )2, //*******
(TaskHandle_t * )&Take_Task_Handle);
xTaskCreate ((TaskFunction_t )Give_Task,
(const char * )"Give_Task",
(uint16_t )512,
(void * )NULL,
(UBaseType_t )2, //*******
(TaskHandle_t * )&Give_Task_Handle);
vTaskDelete(AppTaskCreate_Handle);
taskEXIT_CRITICAL();
}
void Give_Task(void* pvParameters)
{
uint8_t backUpKey1 = 0;
BaseType_t xReturn = pdTRUE;
while(1)
{
if(KEY1 != backUpKey1)
{
if(KEY1 == 1)
{
xReturn = xSemaphoreTake( CountSem_Handle, 0);
if(pdTRUE == xReturn)
printf("成功申请到车位\r\n");
else
printf("未成功申请到车位(车位已满)\r");
}
backUpKey1=KEY1;
}
//vTaskDelay(10);//***
}
}
void Take_Task(void* pvParameters)
{
uint8_t backUpKey2 = 0;
BaseType_t xReturn = pdTRUE;
while(1)
{
if(KEY2 != backUpKey2)
{
if(KEY2 == 1)
{
xReturn = xSemaphoreGive( CountSem_Handle);
if(pdTRUE == xReturn)
printf("已释放一个车位\r\n");
}
backUpKey2=KEY2;
}
//vTaskDelay(10);//***
}
}
void BSP_Init()
{
InitLED();
USART_Config();
InitKey();
}
2.程序详解
以上程序就是野火教程里面一个关于计数信号量的一个计数实验。用来模拟停车场的实验,具体程序我做了一些精简与修改。
可以看到这两个按键检测任务:
就是很普通的检测按键是否被按下,但是这里有一个延时代码被我注释掉了,这是为什么呢。很明显,在硬件消抖电路中我们完全不需要添加延时消抖程序,但是我发现这样做就会出现这两个任务有一个运行不了,经过我对程序的反复查看,终于发现怎样修改这个程序。
3.修改方法
需要注意的行数我在那一行添加了一行醒目的行注释
1.在调用这两个任务的时候,和主任务一样都会设置这个中断优先级,而问题恰恰出现在这个中断优先级,由于我没有添加这个延时函数,在程序初始化的时候由于中断优先级的设置,这个程序始终跑不到低优先级的这个按键任务中(一直死循环在优先级高的按键任务中)。所以我的修改方法就是将这两个按键的任务函数的优先级设置为一样的。
2.如果说需要设置不同的优先级,那么就需要添加这个延时函数。
4.结尾
通过这个实验我终于认识到了一个知识盲区,就是野火的板子明明就设置了硬件消抖,但为什么还需要添加这么长的延时函数(10个系统节拍)。现在我了解到因为设置了不同的优先级,如果没有这个延时那么系统运行的时候就会一直卡在优先级较高的任务中。