FreeRtos----------- 同步互斥

一、同步的缺陷:全局变量协同两个任务

1.建立两个任务:CalcTask 、LcdPrintTask

  xTaskCreate(CalcTask, "task1", 128, NULL, osPriorityNormal, NULL);
  xTaskCreate(LcdPrintTask, "task2", 128, &g_Task2Info, osPriorityNormal, NULL);
  1. LcdPrintTask:

    • 类型TaskFunction_t
    • 含义: 任务的入口函数,也就是任务的执行代码的起点。在这个例子中,LcdPrintTask 是一个函数指针,指向任务的实现函数。
  2. "task2":

    • 类型const char *
    • 含义: 任务的名称,用于调试和管理。这里 task2 是任务的名字。
  3. 128:

    • 类型uint16_t
    • 含义: 为任务分配的堆栈大小(以字节为单位)。这里 128 表示任务的堆栈大小为 128 字节。
  4. &g_Task2Info:

    • 类型void *
    • 含义: 传递给任务的参数。在这个例子中,&g_Task2Info 是一个指向任务参数的指针,任务运行时可以通过这个指针来获取任务相关的数据。
  5. osPriorityNormal:

    • 类型UBaseType_t
    • 含义: 任务的优先级。osPriorityNormal 是任务的优先级,这个值决定了任务在系统中的调度优先级。
  6. 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)可以使用中断的开关解决互斥问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值