STM32FreeRtos入门(五)——同步互斥与通信

文章目录


前言

前面包含了任务创建,任务删除,任务状态等

用到实际,如果通过串口发送数据,发到一半的过程中被打断了,过了一段时间再恢复,是不是通讯数据的错乱了,并且接受的串口数据的没法保证完整性。所以,要在部分情况下加个锁,此时就用到了互斥。如果发送是数据还没准备好,是不是发送指令要等待发送数据,这就是同步。


提示:以下是本篇文章正文内容,下面案例可供参考

一、非Freertos的同步通信

简单来说,中间增加

while (g_calc_end == 0);

来等待通信

c 复制代码
static StackType_t g_pucStackOfLightTask[128];
static StaticTask_t g_TCBofLightTask;
static TaskHandle_t xLightTaskHandle;

static StackType_t g_pucStackOfColorTask[128];
static StaticTask_t g_TCBofColorTask;
static TaskHandle_t xColorTaskHandle;

/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
struct TaskPrintInfo {
	uint8_t x;
	uint8_t y;
	char name[16];
};

static struct TaskPrintInfo g_Task1Info = {0, 0, "Task1"};
static struct TaskPrintInfo g_Task2Info = {0, 3, "Task2"};
static struct TaskPrintInfo g_Task3Info = {0, 6, "Task3"};
//static int g_LCDCanUse = 1;
//static volatile int g_Calc_end = 0;
//static uint64_t g_Calc_time = 0;
//static uint32_t g_sum = 0;

static int g_LCDCanUse = 1;
static volatile int g_calc_end = 0;
static uint64_t g_Calc_time = 0;
static uint64_t g_sum = 0;

//void CalcTask(void *params)
//{
//	uint32_t i = 0;
//	LCD_PrintString(0, 0, "Waiting");
//	g_Calc_time=system_get_ns();
//   for (i=0;i<10000000;i++)
//	{
//		g_sum += i;
//	}
//	g_calc_end = 1;
//	g_Calc_time=system_get_ns() - g_Calc_time;
//	vTaskDelete(NULL);
//}


void CalcTask(void *params)
{
	uint32_t i = 0;
	
	LCD_PrintString(0, 0, "Waiting");

	g_Calc_time = system_get_ns();
	for (i = 0; i < 10000000; i++)
	{
		g_sum += i;
	}
	g_calc_end = 1;
	g_Calc_time = system_get_ns() - g_Calc_time;

	vTaskDelete(NULL);
}




void LcdPrintTask(void *params)
{
	int len;
	while (1)
	{
		LCD_PrintString(0, 0, "Waiting");
		
		vTaskDelay(3000);
		
		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);
			
			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(ns):");
			LCD_PrintSignedVal(len, 2, g_Calc_time);
			
			g_LCDCanUse = 1;
		}
		vTaskDelete(NULL);
	}
}

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

二、非Freertos的互斥通信

非 FreeRTOS 环境下的互斥通信,核心是通过软件算法或硬件机制,确保多个执行单元(如任务、中断)安全访问共享资源,避免数据竞争。

常用例子;标志位

举例:

禁止中断(Disable Interrupts)

在访问共享资源前,关闭所有可能抢占当前执行流程的中断。

完成资源操作后,重新使能中断。

适用场景:单 CPU、对实时性要求不高的简单场景,如裸机中任务与中断的资源共享。

测试并置位(Test-and-Set, TAS)

借助 CPU 指令(如XCHG、BTS),原子性地检查并设置一个标志位。

若标志位为 "未占用",则置位并获取资源;若已占用,则循环等待(忙等)。

适用场景:多任务环境,依赖 CPU 的原子指令支持。

三、Freertos的同步与互斥函数以及通信

具体历程下一章写


总结

这些实现不依赖 FreeRTOS 的osMutex等 API,而是基于底层硬件特性或通用编程范式,适用于裸机(Bare-metal)、RT-Thread、μC/OS 等其他系统或无操作系统场景。

在系统中,如果不依靠FreeRTOS的osMutex等 API,互斥会极大的浪费时间,同步有小概率会出现问题,任务被切换等。

相关推荐
你不是我我3 小时前
【Java 开发日记】我们来讲一讲阻塞队列及其应用
java·开发语言
互联网中的一颗神经元3 小时前
小白python入门 - 9. Python 列表2 ——从基础操作到高级应用
java·开发语言·python
大厂码农老A3 小时前
我带的外包兄弟放弃大厂转正,薪资翻倍入职字节
java·后端·面试
摇滚侠3 小时前
Spring Boot3零基础教程,生命周期监听,自定义监听器,笔记59
java·开发语言·spring boot·笔记
凯子坚持 c3 小时前
Llama-2-7b在昇腾NPU上的六大核心场景性能基准报告
java·开发语言·llama
百锦再3 小时前
国产数据库替代MongoDB的技术实践:金仓数据库赋能浙江省人民医院信息化建设新展望
java·开发语言·数据库·mongodb·架构·eclipse·maven
武子康3 小时前
Java-160 MongoDB副本集部署实战 单机三实例/多机同法 10 分钟起集群 + 选举/读写/回滚全流程
java·数据库·sql·mongodb·性能优化·系统架构·nosql
稚辉君.MCA_P8_Java4 小时前
Bash 括号:()、{}、[]、$()、$(() )、${}、[[]] 到底有什么区别?
开发语言·jvm·后端·容器·bash
sinat_286945194 小时前
Java事故排查
java·开发语言