声明:本专栏参考韦东山,野火,正点原子以及其他博主的FreeRTOS教程,如若侵权请告知,马上删帖致歉,个人总结,如有不对,欢迎指正。
互斥量理论
实验一:互斥信号量基本使用
互斥信号量本使用与二进制信号量无太大差别,二进制信号量需要先释放,互斥信号量不用,直接调用函数即可
调用函数创建互斥信号量
打开宏开关
创建任务
该实验任务创建与前一节二进制信号量的任务创建一样
实验仿真
任务交替执行
实验二:优先级反转实验
实验描述
创建三个任务,分别为Flag1_Task,Flag2_Task,Flag3_Task ,优先级分别为1,2,3
按照时序来看看任务怎么执行,首先是任务3先执行,flag3标志置1后阻塞10个tick,接着执行任务2,任务2的flag2标志置1后阻塞30个tick,接着执行任务一,任务一的flag1标志置1后获得锁,10个tick后任务三执行,flag3标志置1后也获得锁,但是此时锁没有被释放,这时候任务三就一直处于阻塞的状态,这时候任务二的阻塞时间还没有到,任务1继续执行,到40个tick后任务二执行,这时候任务2进入循环且一直没有放弃cpu资源,
实验仿真
实验三:优先级继承
对于上述实验二的情况,为了解决这一问题,提出了优先级继承的方法,大概是在实验二的条件下,任务三的优先级会被任务一继承,这时候任务1的优先级就是3,就可以抢占任务2
在上一个实验的基础上,只把二进制信号量改为互斥量看看会发生什么
实验仿真
实验四:互斥量的缺陷(可由别人释放锁)
互斥量的本意是,谁持有,就由谁来释放,但是在freeRTOS这里并没有实现,递归锁实现了这一意思,谁持有,就由谁来释放,先来看看这一实验
实验概述
创建三个任务,任务1与任务2共用串口资源,互斥执行,任务三来释放这个锁,在其中捣蛋
实验仿真
任务在运行一段时间之后,由于任务三把锁释放掉了,导致错误产生
实验五:递归锁
打开宏开关
主函数创建递归信号量
创建任务
xReturn = xTaskCreate((TaskFunction_t )Flag1_Task,
(const char* )"Flag1_Task",
(uint16_t )512,
(void* )"Task 1 is running",
(UBaseType_t )1,
(TaskHandle_t* )&Task1_Handle);
if(pdPASS == xReturn)
printf("创建Flag1_Task任务成功!\r\n");
xReturn = xTaskCreate((TaskFunction_t )Flag2_Task,
(const char* )"Flag2_Task",
(uint16_t )512,
(void* )"Task 2 is running",
(UBaseType_t )1,
(TaskHandle_t* )&Task2_Handle);
if(pdPASS == xReturn)
printf("创建Flag2_Task任务成功!\r\n");
xReturn = xTaskCreate((TaskFunction_t )Flag3_Task,
(const char* )"Flag3_Task",
(uint16_t )512,
(void* )"Task 3 is running",
(UBaseType_t )1,
(TaskHandle_t* )&Task3_Handle);
if(pdPASS == xReturn)
printf("创建Flag3_Task任务成功!\r\n");
以下代码可以看出,使用递归锁可以有效保护资源,不会被别的任务开锁
static void Flag1_Task(void * param)
{
int i;
while (1)
{
xSemaphoreTakeRecursive(xSemUART, portMAX_DELAY);
printf("%s\r\n", (char *)param);
for (i = 0; i < 10; i++)
{
xSemaphoreTakeRecursive(xSemUART, portMAX_DELAY);
printf("%s in loop %d\r\n", (char *)param, i);
xSemaphoreGiveRecursive(xSemUART);
}
xSemaphoreGiveRecursive(xSemUART);
vTaskDelay(1);
}
}
static void Flag2_Task(void * param)
{
int i;
while (1)
{
xSemaphoreTakeRecursive(xSemUART, portMAX_DELAY);
printf("%s\r\n", (char *)param);
for (i = 0; i < 10; i++)
{
xSemaphoreTakeRecursive(xSemUART, portMAX_DELAY);
printf("%s in loop %d\r\n", (char *)param, i);
xSemaphoreGiveRecursive(xSemUART);
}
xSemaphoreGiveRecursive(xSemUART);
vTaskDelay(1);
}
}
static void Flag3_Task(void * param)
{
vTaskDelay(10);
while (1)
{
while (1)
{
if (xSemaphoreTakeRecursive(xSemUART, 0) != pdTRUE)
{
xSemaphoreGiveRecursive(xSemUART);
}
else
{
break;
}
}
printf("%s\r\n", (char *)param);
xSemaphoreGiveRecursive(xSemUART);
vTaskDelay(1);
}
}
实验仿真
git仓库源码地址:https://gitee.com/he-dejiang/free-rtos.git
|