将获取信号量函数xSemaphoreTake的阻塞时间改为0,也就是没获取到信号量,立即返回。
代码语言:javascript复制void vTask01_Code(void *para)
{
static unsigned int cnt = 0;
BaseType_t err = pdTRUE;
for (;;)
{
xSemaphoreTake(BinarySemaphore, 0);
PRINT(" task01 cnt %u...", cnt );
vTaskDelay(500);
}
}
编译,运行:
代码语言:javascript复制$ ./build/freertos-simulator
task01 cnt 0...
task00 cnt 0...
task01 cnt 1...
task01 cnt 2...
task01 cnt 3...
task01 cnt 4...
task00 cnt 1...
可以看出,任务task01不会等待信号量,而是继续执行。
9.1.4 优先级反转
使用二值信号量会出现优先级反转的问题,优先级反转在可剥夺内核中是常见的,但在实时系统中不允许出现这种现象。
上述图中,高任务H会晚于低优先级任务M执行,这就发生了优先级反转。
优先级反转实验设计:
实验设计:创建三个任务,高优先级任务获取二值信号量,获取成功后进行相应的处理,处理完之后释放信号量;中优先级任务简单运行;低优先级任务和高优先级任务一样,会获取二值信号量,获取成功后进行相应处理。
测试代码:
代码语言:javascript复制configSTACK_DEPTH_TYPE TaskLow_STACK_SIZE = 5;
UBaseType_t TaskLow_Priority = 2;
TaskHandle_t TaskLow_xHandle;
configSTACK_DEPTH_TYPE TaskMiddle_STACK_SIZE = 5;
UBaseType_t TaskMiddle_Priority = 3;
TaskHandle_t TaskMiddle_xHandle;
configSTACK_DEPTH_TYPE TaskHigh_STACK_SIZE = 5;
UBaseType_t TaskHigh_Priority = 4;
TaskHandle_t TaskHigh_xHandle;
//二值信号量
SemaphoreHandle_t BinarySemaphore;
void vTaskLow_Code(void *para)
{
static unsigned int times = 0;
BaseType_t err = pdTRUE;
for (;;)
{
xSemaphoreTake(BinarySemaphore, portMAX_DELAY);
PRINT(" low task running");
for (times = 0; times < 20000000; times )
taskYIELD();
err = xSemaphoreGive(BinarySemaphore);
if (err != pdTRUE)
PRINT("BinarySemaphore give failed!");
vTaskDelay(1000);
}
}
void vTaskMiddle_Code(void *para)
{
for (;;)
{
PRINT(" task middle running");
vTaskDelay(1000);
}
}
void vTaskHigh_Code(void *para)
{
for (;;)
{
vTaskDelay(500);
PRINT(" task high Pend Sem");
xSemaphoreTake(BinarySemaphore, portMAX_DELAY);
PRINT(" task high running!");
xSemaphoreGive(BinarySemaphore);
vTaskDelay(500);
}
}
void test_BinarySemaphore()
{
taskENTER_CRITICAL();
BinarySemaphore = xSemaphoreCreateBinary();
if (BinarySemaphore != NULL)
xSemaphoreGive(BinarySemaphore);
if (xTaskCreate(vTaskLow_Code, "taskLow task",
TaskLow_STACK_SIZE, NULL, TaskLow_Priority,
&TaskLow_xHandle) != pdPASS)
{
PRINT("creat taskLow failed!n");
}
if (xTaskCreate(vTaskMiddle_Code, "taskMiddle task",
TaskMiddle_STACK_SIZE, NULL, TaskMiddle_Priority,
&TaskMiddle_xHandle) != pdPASS)
{
PRINT("creat taskMiddle failed!n");
}
if (xTaskCreate(vTaskHigh_Code, "taskHigh task",
TaskHigh_STACK_SIZE, NULL, TaskHigh_Priority,
&TaskHigh_xHandle) != pdPASS)
{
PRINT("creat taskHigh failed!n");
}
taskEXIT_CRITICAL();
}
void creat_task(void)
{
test_BinarySemaphore();
}