目录
- FreeRTOS学习第8篇--同步和互斥操作引子
- 同步和互斥概念
- 实现同步和互斥的机制
- PrintTask_Task任务相关代码片段
- CalcTask_Task任务相关代码片段
- 实验现象
- 本文中使用的测试工程
FreeRTOS学习第8篇–同步和互斥操作引子
本文目标:学习与使用FreeRTOS中的同步和互斥操作引子
按照本文的描述,应该可以跑通实验并举一反三。
本文实验条件:拥有C语言基础,装有编译和集成的开发环境,比如:Keil uVision5
同步和互斥概念
同步用于控制任务执行顺序和时间,例如等待其他任务完成某项操作。
互斥用于保护共享资源,确保一次只有一个任务能够修改或访问这些资源。
实现同步和互斥的机制
- 任务通知(task notification):用于任务之间的等待和唤醒,可以传递数据和状态。
- 队列(queue):用于传递数据,任务和ISR都可以放入数据,从中读出数据。
- 信号量(semaphore):用于维持资源的个数,生产者和消费者都可以使用。
- 互斥量(mutex):用于保护共享资源的访问,确保一次只有一个任务能够修改资源。
这些知识点,后续会继续进行学习。
基于上面的知识点,在我自己硬件板子上进行实验,完成这个实验的体验。在本次实验中,设计两个两个任务,任务PrintTask负责打印一些信息,任务CalcTask进行计算,当计算任务完成计算时,将结果传递给任务PrintTask进行显示。
PrintTask_Task任务相关代码片段
void PrintTask(void *params)
{
struct TaskPrintInfo *pInfo = params;
OLED_Init();
while (1)
{
// vTaskDelay(3000); // 进入block
while (g_calc_end == 0); // 等待计算任务完成
/* 打印信息 */
if (g_LCDCanUse)
{
g_LCDCanUse = 0;
OLED_ShowString(pInfo->x,pInfo->y,"Sum:",16);
OLED_ShowNum((pInfo->x + 8 * 6),pInfo->y,g_sum,10,16);
OLED_ShowString(pInfo->x,pInfo->y + 16,"Time(ms): ",16);
OLED_ShowNum((pInfo->x + 8 * 10),pInfo->y + 16,g_time / 1000000,4,16);
g_LCDCanUse = 1;
}
OLED_Refresh();
vTaskDelete(NULL);
}
}
xTaskCreate(PrintTask, "task1", 128, &g_Task1Info, osPriorityNormal, NULL);
static struct TaskPrintInfo g_Task1Info = {0, 0, "Task1"};
CalcTask_Task任务相关代码片段
void CalcTask(void *params)
{
uint32_t i = 0;
OLED_ShowString(0, 0, "Waiting",16);
OLED_Refresh();
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);
}
xTaskCreate(CalcTask, "task2", 128, &g_Task2Info, osPriorityNormal, NULL);
static struct TaskPrintInfo g_Task2Info = {0, 16, "Task2"};
实验现象
下载代码到板子上,可以看到计算的结果在第一行中进行显示,在第二行那里显示了计算这么多个数所需要的时间,打印任务PrintTask在计算任务CalcTask没计算完时也抢占cpu资源,导致计算会有些慢,这里我根据计算的结果,简单粗暴的加了相应的延迟vTaskDelay(3000); // 进入block,使打印任务一开始先阻塞着,不抢占cpu资源,计算速度会快一些。当然这只是一种例子,有一定的缺陷,当作学习使用。
本文完!