FreeRtos同步互斥与通信

news2024/11/15 22:31:21

                        前言:本篇笔记参考韦东山老师,视屏教程,连接放在最后。

同步与互斥的基本概念

        同步:Task_a执行完成之后Task_b才能执行,让任务按照特定的顺序去执行。

        互斥:当Task_a访问临界资源进行执行,Task_b就不能执行,反之也成立。

这两个概念的主要区别就是,同步是有特定顺序的,互斥不是,互斥是谁访问到临界资源谁就执行,没有访问到的就等待,执行结束释放资源,在此访问执行。

Task同步代码体现

static int g_LCDCanUse = 1;
static voltile 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;//更新标志位 允许task2跑
	g_time = system_get_ns() - g_time;
 
	vTaskDelete(NULL);
}
 
 
void LcdPrintTask(void *params)
{
	int len;
	while (1)
	{
		LCD_PrintString(0, 0, "Waiting");
		
		vTaskDelay(3000);
		
		while (g_calc_end == 0);//判断task1,完成没
		
		/* 打印信息 */
		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);
	}
}
xTaskCreate(CalcTask, "task1", 128, NULL, osPriorityNormal, NULL);
xTaskCreate(LcdPrintTask, "task2", 128, &g_Task2Info, osPriorityNormal, NULL);

        这里task1和task2两个任务实现了同步,task2的执行必须在task1后面,但是这里其实还是有一点问题的,task2在等待static int  g_calc_end 标志位的时候,是有cpu分配时间的,如果想让任务执行更快,可以估算Task1的执行时间,将Task2使用vTaskDelay()进行延时

Task互斥代码体现

01 int LCD_PrintString(int x, int y, char *str) 
02 { 
03 static int bCanUse = 1; 
04 if (bCanUse) 
05 { 
06 bCanUse = 0; 
07 /* 使用LCD */ 
08 bCanUse = 1; 
09 return 0; 
10 } 
11 return -1; 
12 } 

xTaskCreate(LcdPrintTask, "task1", 128, &g_Task1Info, osPriorityNormal, NULL);
xTaskCreate(LcdPrintTask, "task2", 128, &g_Task2Info, osPriorityNormal, NULL);
xTaskCreate(LcdPrintTask, "task3", 128, &g_Task3Info, osPriorityNormal, NULL);

        在文件中,三个task任务使用 LcdPrintTask函数作为执行函数,但是OLED屏幕是一种互斥资源,在这里代码里面使用了标志位   g_LCDCanUse  ,来防止使用Oled的过程被其他Task打断,这里通过堆标志位,进行赋值可以防止大部分情况下的Task进行切换,但是当Task1,执行到if语句,也就是第10行,这个时候切换为Task2,发现Task2也是能够正常执行的,这就会造成IIC通信时序混乱,但是这种概率很小。      

01 int LCD_PrintString(int x, int y, char *str) 
02 { 
03 static int bCanUse = 1; 
04 bCanUse--; 
05 if (bCanUse == 0) 
06 { 
07 /* 使用LCD */ 
08 bCanUse++; 
09 return 0; 
10 } 
11 else 
12 { 
13 bCanUse++; 
14 return -1; 
15 } 
16 }

        第一段代码中实现资源互斥,有小概率出现没有效果,是因为标志位,判断还有赋值占用时间太长了,第二段代码中,将标志位的赋值放在进入判断之前,相对于第一段代码的效果好很多,但是仍然会导致,访问Oled资源的时候无法实现互斥访问。

01 int LCD_PrintString(int x, int y, char *str) 
02 { 
03 static int bCanUse = 1; 
04 disable_irq(); 
05 if (bCanUse) 
06 { 
07 bCanUse = 0; 
08 enable_irq(); 
09 /* 使用LCD */ 
10 bCanUse = 1; 
11 return 0; 
12 } 
13 enable_irq(); 
14 return -1; 
15 }

        上面两段代码,无法完全实现互斥访问oled资源的很大一部分原因,是因为Task之间的切换运行,也就是多Task运行,在进项判断的时候如果可以将中断关闭,不在进行Task切换,就能够完全实现,对Oled资源的互斥访问

        最后这一段代码,可以实现对Oled资源互斥,没有任何漏洞,但是在Task_b使用cpu资源进行判断是否能够执行OLed任务的时候,是一种对cpu资源的浪费,和上面同步的缺陷一样。

        有没有一种办法,在task-a执行的时候,让Task_b进入阻塞状态放弃cpu资源,加快Task_a的执行,同时也可以完成Oled资源访问的互斥。

开发快捷键

        这里记录一个开发快捷键技巧,当在开发的时候,需要看函数原型定义,理解这个函数干什么的时候,可以使用 ctrl+f 快捷键查找函数原型,但是这种方法会找所有相同函数名出现的地方,知道找到函数原型定义在停止,比较慢。

        首先

         然后直接鼠标右键,看里面的选项注释,里Go To Definition of  "ADC_NTC_Temperature",跳转到函数定义,然后后面有快捷键F12,或者直接点击这个选型就可以了,这里点击这个选型进行跳转。

        这个时候发现就已经跳转过来了。很实用的一个小技巧。

                                        感谢阅读,如有错误,欢迎指正!!!

[6-1]_同步互斥与通信_有缺陷的同步示例_哔哩哔哩_bilibili

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2154569.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(done) 声音信号处理基础知识(2) (重点知识:pitch)(Sound Waveforms)

来源&#xff1a;https://www.youtube.com/watch?vbnHHVo3j124 复习物理知识&#xff1a; 声音由物体的振动产生 物体振动会导致空气分支振荡 某一处的空气气压变化会创造一个波 声音是机械波 空气的振荡在空间中传递 能量从空间中的一个点到另一个点 机械波需要媒介&#x…

LabVIEW编程能力如何能突飞猛进

要想让LabVIEW编程能力实现突飞猛进&#xff0c;需要采取系统化的学习方法&#xff0c;并结合实际项目进行不断的实践。以下是一些提高LabVIEW编程能力的关键策略&#xff1a; 1. 扎实掌握基础 LabVIEW的编程本质与其他编程语言不同&#xff0c;它是基于图形化的编程方式&…

【Taro】初识 Taro

笔记来源&#xff1a;编程导航。 概述 Taro 官方文档&#xff1a;https://taro-docs.jd.com/docs/ &#xff08;跨端开发框架&#xff09; Taro 官方框架兼容的组件库&#xff1a; taro-ui&#xff1a;https://taro-ui.jd.com/#/ &#xff08;最推荐&#xff0c;兼容性最好&…

第四范式发布AIGS Builder企业级软件重构助手,以生成式AI重构企业软件

产品上新 Product Release 今天&#xff0c;第四范式发布企业级软件重构助手——AIGS Builder&#xff0c;可快速重构软件交互体验。传统的企业软件开发&#xff0c;每次迭代通常要以月计。基于第四范式AIGS Builder大模型&#xff0c;用生成式Agent替代复杂的界面&#xff0c;…

为什么 AVIF 将成为下一代图片格式之王

AVIF的卓越优势 AVIF&#xff08;AV1 Image File Format&#xff09;正在迅速崛起&#xff0c;成为下一代网络图片格式的有力竞争者。作为基于AV1视频编码技术的图像格式&#xff0c;AVIF在多个方面展现出了令人瞩目的性能。 1. 卓越的压缩效率 与JPEG和WebP相比&#xff0c…

torch模型量化方法总结

0.概述 模型训练完成后的参数为float或double类型&#xff0c;而装机&#xff08;比如车载&#xff09;后推理预测时&#xff0c;通常都会预先定点&#xff08;量化&#xff09;为int类型参数&#xff0c;相应的推理的精度会有少量下降&#xff0c;但不构成明显性能下降&#…

CO-锁存器(Latch)

1.描述 锁存器(Latch)&#xff0c;是数字电路中的一种具有记忆功能的逻辑元件&#xff0c;是一种对脉冲电平敏感的存储单元电路&#xff0c;可以在特定输入脉冲电平作用下改变状态&#xff0c;利用电平控制数据的输入&#xff0c;包括不带使能控制的锁存器和带使能控制的锁存器…

sql执行流程经典案例分析

现在有联合索引(a,b),select* form tb where b xx group by a执行流程是什么样子的? CREATE TABLE IF NOT EXISTS test(id INT(10) NOT NULL AUTO_INCREMENT COMMENT主键,a INT(10) NULL,b INT(10) NULL,PRIMARY KEY(id),INDEX idx_a_b(a,b))ENGINE INNODB;INSERT INTO test…

【Unity-UGUI组件拓展】| Image 组件拓展,支持FIlled和Slice功能并存

🎬【Unity-UGUI组件拓展】| Image 组件拓展,支持FIlled和Slice功能并存一、组件介绍二、组件拓展方法三、完整代码💯总结🎬 博客主页:https://xiaoy.blog.csdn.net 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉 🎄 学习专栏推荐:Unity系统学习专栏 🌲 游戏…

Linux:login shell和non-login shell以及其配置文件

相关阅读 Linuxhttps://blog.csdn.net/weixin_45791458/category_12234591.html?spm1001.2014.3001.5482 shell是Linux与外界交互的程序&#xff0c;登录shell有两种方式&#xff0c;login shell与non-login shell&#xff0c;它们的区别是读取的配置文件不同&#xff0c;本…

TypeScript入门 (三)数据类型

引言 大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年9月学习赛的TypeScript学习总结文档。本文旨在全面介绍 TypeScript 中的各种数据类型&#xff0c;帮助读者深入理解每种数据类型的用法、内置属性…

LabVIEW提高开发效率技巧----自动化测试和持续集成

在大型项目中&#xff0c;自动化测试和持续集成是提高开发效率和代码质量的关键手段。通过这些技术&#xff0c;开发者能够在开发的早期阶段快速发现问题&#xff0c;减少后期调试的工作量&#xff0c;并且能够确保代码的稳定性和可维护性。以下是这两个概念如何在LabVIEW开发中…

Docker Networking Tutorial (Bridge - None - Host - IPvlan - Macvlan )

In this article, We will talk about the network of docker. Therere have five types of docker network. 一、Bridge The default network of docker network type. You can use : docker network ls docker network create --driver bridge my_bridge_network ##The CID…

什么是 GPT?通过图形化的方式来理解 Transformer 架构

Predict, sample, repeat 预测、取样、重复 GPT 是 Generative Pre-trained Transformer 的缩写。首个单词较为直接&#xff0c;它们是用来生成新文本的机器人。“Pre-trained” 指的是模型经历了从大量数据中学习的过程&#xff0c;这个词暗示了该模型还有进一步在特定任务中…

移动技术开发:ListView水果列表

1 实验名称 ListView水果列表 2 实验目的 掌握自定义ListView控件的实现方法 3 实验源代码 布局文件代码&#xff1a; activity_main.xml: <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.androi…

Java 中Lock接口锁的使用

一. Lock接口下的实现类 在Java中&#xff0c;Lock 接口是 java.util.concurrent.locks 包中的一部分&#xff0c;它提供了比 synchronized 更丰富的锁操作。Lock 接口的实现类包括 ReentrantLock&#xff08;可重入锁&#xff09;、ReadWriteLock&#xff08;读写锁&#xff…

从零开始学习TinyWebServer

写在前面 项目参考&#xff1a;https://github.com/qinguoyi/TinyWebServer 写作框架/图参考&#xff1a;https://blog.csdn.net/qq_52313711/article/details/136356042?spm1001.2014.3001.5502 原本计划是&#xff0c;先将项目代码大概看一遍&#xff0c;然后再着手实现一下…

【hot100-java】【组合总和】

R8-回溯篇 印象题&#xff0c;很基本的回溯 class Solution {void backtrack(List<Integer> state,int target,int[] choices,int start,List<List<Integer>> ret){//子集和等于target&#xff0c;记录解if (target0){ret.add(new ArrayList<>(state)…

LeetCode讲解篇之1343. 大小为 K 且平均值大于等于阈值的子数组数目

文章目录 题目描述题解思路题解代码 题目描述 题解思路 题目让我们求长度为k的子数组并且该子数组的平均值大于threshold&#xff0c;对于这题&#xff0c;我们可以考虑维护一个长度为k的窗口&#xff0c;窗口不断向右滑动&#xff0c;遍历所有长度为k的子数组&#xff0c;我们…

低版本SqlSugar的where条件中使用可空类型报语法错误

SQLServer数据表中有两列可空列&#xff0c;均为数值类型&#xff0c;同时在数据库中录入测试数据&#xff0c;Age和Height列均部分有值。   使用SqlSugar的DbFirst功能生成数据库表类&#xff0c;其中Age、Height属性均为可空类型。   开始使用的SqlSugar版本较低&…