一、同步的缺陷:全局变量协同两个任务
1.建立两个任务:CalcTask 、LcdPrintTask
xTaskCreate(CalcTask, "task1", 128, NULL, osPriorityNormal, NULL);
xTaskCreate(LcdPrintTask, "task2", 128, &g_Task2Info, osPriorityNormal, NULL);
-
LcdPrintTask:- 类型:
TaskFunction_t - 含义: 任务的入口函数,也就是任务的执行代码的起点。在这个例子中,
LcdPrintTask是一个函数指针,指向任务的实现函数。
- 类型:
-
"task2":- 类型:
const char * - 含义: 任务的名称,用于调试和管理。这里
task2是任务的名字。
- 类型:
-
128:- 类型:
uint16_t - 含义: 为任务分配的堆栈大小(以字节为单位)。这里
128表示任务的堆栈大小为 128 字节。
- 类型:
-
&g_Task2Info:- 类型:
void * - 含义: 传递给任务的参数。在这个例子中,
&g_Task2Info是一个指向任务参数的指针,任务运行时可以通过这个指针来获取任务相关的数据。
- 类型:
-
osPriorityNormal:- 类型:
UBaseType_t - 含义: 任务的优先级。
osPriorityNormal是任务的优先级,这个值决定了任务在系统中的调度优先级。
- 类型:
-
NULL:- 类型:
TaskHandle_t * - 含义: 用于接收任务的句柄。如果不需要获取任务句柄,可以传入
NULL。任务句柄可以用来控制任务,比如删除任务或获取任务的状态。
- 类型:
解释:
这行代码的作用是创建一个新的任务 LcdPrintTask,任务的名字为 "task2",堆栈大小为 128 字节,任务在启动时会接收到参数 g_Task2Info,并且该任务的优先级是 osPriorityNormal。任务句柄被设为 NULL,表示我们不需要保存这个任务的句柄信息。
一旦任务创建成功,它会被添加到调度器中,并在合适的时机由操作系统调度执行。
//全局变量
static int g_LCDCanUse = 1;
static volatile int g_calc_end = 0;
static uint64_t g_time = 0;
static uint32_t g_sum = 0;
void CalcTask(void *params)
{
uint32_t i = 0;
LCD_PrintString(0, 0, "Waiting");
g_time = system_get_ns();
for (i = 0; i < 10000000; i++)
{
g_sum += i;
}
g_calc_end = 1;
g_time = system_get_ns() - g_time;
vTaskDelete(NULL);
}
void LcdPrintTask(void *params)
{
int len;
while (1)
{
LCD_PrintString(0, 0, "Waiting");
vTaskDelay(3000); //让此任务进入阻塞,3毫秒后执行while (g_calc_end == 0);减少cpu的使用
while (g_calc_end == 0);
/* 打印信息 */
if (g_LCDCanUse)
{
g_LCDCanUse = 0;
LCD_ClearLine(0, 0);
len = LCD_PrintString(0, 0, "Sum: ");
LCD_PrintHex(len, 0, g_sum, 1);
LCD_ClearLine(0, 2);
len = LCD_PrintString(0, 2, "Time(ms): ");
LCD_PrintSignedVal(len, 2, g_time/1000000);
g_LCDCanUse = 1;
}
vTaskDelete(NULL);
}
}
void LcdPrintTask(void *params)
{
int len;
while (1)
{
LCD_PrintString(0, 0, "Waiting");
vTaskDelay(3000); //让此任务进入阻塞,3毫秒后执行while (g_calc_end == 0);减少cpu的使用
while (g_calc_end == 0);
/* 打印信息 */
if (g_LCDCanUse)
{
g_LCDCanUse = 0;
LCD_ClearLine(0, 0);
len = LCD_PrintString(0, 0, "Sum: ");
LCD_PrintHex(len, 0, g_sum, 1);
LCD_ClearLine(0, 2);
len = LCD_PrintString(0, 2, "Time(ms): ");
LCD_PrintSignedVal(len, 2, g_time/1000000);
g_LCDCanUse = 1;
}
vTaskDelete(NULL);
}
}
注意:static volatile int g_calc_end = 0;使用volatile让编译器不要去优化,否则在执行任务的时候g_calc_end时刻等于0,不执行后面的代码。
二、互斥的缺陷--同时访问一个资源
1.同时有两个任务要使用lcd

进行优化代码如下:但是在微观条件下,也有可能发送任务切换。
(1)可以使用中断的开关解决互斥问题














![[Linux]如何在Ubuntu中安装Docker,并且学习基本操作?](https://i-blog.csdnimg.cn/direct/60775586f962460890203a7c5f095208.png)





