FreeRTOS简单内核实现4 临界段

news2025/4/21 4:48:57

文章目录

  • 0、思考与回答
    • 0.1、思考一
    • 0.2、思考二
    • 0.3、思考三
  • 1、关中断
    • 1.1、带返回值
    • 1.2、不带返回值
  • 2、开中断
  • 3、临界段
  • 4、应用


0、思考与回答

0.1、思考一

为什么需要临界段?

有时候我们需要部分代码一旦这开始执行,则不允许任何中断打断,这段代码称为临界段

0.2、思考二

如何实现临界段?

  1. 关中断
  2. 执行临界区代码
  3. 开中断

0.3、思考三

对于 Cotex-M4 内核的处理器如何方便的控制其中断开关?

使用 BASEPRI 寄存器,当该寄存器中的值不为 0 时,处理器将不会处理优先级值大于或等于 BASEPRI 的任何异常,该寄存器相关信息可以在 Cortex-M4 Devices Generic User Guide 手册中找到,具体如下图所示

![[Kernel_4.1.png]]

值得注意的是 STM32 的 BASEPRI 寄存器做了一些修改,只使用了其高 4 位,低 4 位的数据没有使用,所以对于 STM32 在使用 BASEPRI 寄存器对中断进行屏蔽时,需要考虑到写入的高 4 位数据才是正确的数据,感兴趣的可以阅读 为何修改BASEPRI寄存器无效? 这篇文章

1、关中断

1.1、带返回值

Keil 版本

/* portMacro.h */
#define portSET_INTERRUPT_MASK_FROM_ISR()       ulPortRaiseBASEPRI()
// 带返回值关中断,将当前中断状态作为返回值返回
static __inline uint32_t ulPortRaiseBASEPRI(void)
{
	uint32_t ulReturn,ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
	__asm 
	{
		mrs ulReturn,basepri        // 保存中断时 BASEPRI 寄存器的值
		msr basepri,ulNewBASEPRI    // 屏蔽 优先级值 大于等于 11 的中断
		dsb
		isb
	}
	return ulReturn;
}

CLion 版本

static __inline uint32_t ulPortRaiseBASEPRI(void)  
{  
    uint32_t ulReturn,ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;  
    __asm volatile  
    (  
        "mrs ulReturn,basepri        \n"  
        "msr basepri,ulNewBASEPRI    \n"  
        "dsb                         \n"  
        "isb                         \n"  
    );  
    return ulReturn;  
}

1.2、不带返回值

Keil 版本

/* portMacro.h */
#define portDISABLE_INTERRUPTS()                vPortRaiseBASEPRI()
// 不带返回值关中断
static __inline void vPortRaiseBASEPRI(void)
{
	uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
	__asm 
	{
		msr basepri,ulNewBASEPRI
		dsb
		isb
	}
}

CLion 版本

static __inline void vPortRaiseBASEPRI(void)  
{  
    uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;  
    __asm volatile  
    (  
        "msr basepri, %0    \n"
        "isb                \n"
        :
        : "r" (ulNewBASEPRI)
        : "memory"
    );  
}

2、开中断

Keil 版本

/* portMacro.h */
// 设置 BASEPRI 为 0 开所有中断
#define portENABLE_INTERRUPTS()                 vPortSetBASEPRI(0)
// 设置 BASEPRI 为进入中断时的值则恢复原来的中断状态
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)    vPortSetBASEPRI(x)
// 开中断
static __inline void vPortSetBASEPRI(uint32_t ulBASEPRI)
{
	__asm volatile
	{
		msr basepri,ulBASEPRI       
	}
}

CLion 版本

static __inline void vPortSetBASEPRI(uint32_t ulBASEPRI)  
{
    __asm volatile  
    (
        "msr basepri, %0    \n"
        : "r" (ulBASEPRI)
        : "memory"
    );
}

3、临界段

/* task.h */
#define taskENTER_CRITICAL()           portENTER_CRITICAL()
#define taskEXIT_CRITICAL()            portEXIT_CRITICAL()

#define taskENTER_CRITICAL_FROM_ISR()  portSET_INTERRUPT_MASK_FROM_ISR()
#define taskEXIT_CRITICAL_FROM_ISR(x)  portCLEAR_INTERRUPT_MASK_FROM_ISR(x)
/* portMacro.h */
extern void vPortEnterCritical(void);
extern void vPortExitCritical(void);
#define portENTER_CRITICAL()         vPortEnterCritical()
#define portEXIT_CRITICAL()          vPortExitCritical()
/* port.c */
// 中断嵌套计数器
static UBaseType_t uxCriticalNesting = 0xAAAAAAAA;
// 进入临界区
void vPortEnterCritical(void)
{
	portDISABLE_INTERRUPTS();
	uxCriticalNesting++;
	if(uxCriticalNesting==1)
	{
		// configASSERT((portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK) == 0);
	}
}
// 退出临界区
void vPortExitCritical(void)
{
	// configASSERT(uxCriticalNesting);
	uxCriticalNesting--;
	if(uxCriticalNesting == 0)
	{
		portENABLE_INTERRUPTS();
	}
}

4、应用

普通场合

// 进入临界区直接屏蔽优先级号大于 11 的中断
taskENTER_CRITICAL();
// 退出时直接设置 BASEPRI 寄存器的值为 0 
taskEXIT_CRITICAL();

中断场合

uint32_t ulReturn;
// 进入临界区前保存 BASEPRI 寄存器的值
ulReturn = taskENTER_CRITICAL_FROM_ISR();
// 退出临界区时恢复 BASEPRI 寄存器的值
taskEXIT_CRITICAL_FROM_ISR(ulReturn);

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

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

相关文章

GMT6绘制北半球

设置绘制区域及投影方式 投影方式选择立体等角投影,在GMT6中的命令是-Js # 定义区域变量和投影变量,纬度从北纬30度到极点 region-180/180/30/90 projection0/90/1:60000000 gmt set PROJ_ELLIPSOID WGS-84定义CPT及地形展示 现在定义一个CPT用于显示…

彻底理解 C 语言的数组在内存中到底是怎么存放的!

在C语言中,数组是经常被用到的重要数据类型,但在实际使用时,往往有很多工程师会出现各种各样的问题,如内存越界、错误的访问、初始化不当等。这其中有很大一个原因是没有彻底理解数组的存储机制,出现了一些非法地址或者…

基于springboot实现农产品直卖平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现农产品直卖平台系统的设计演示 摘要 计算机网络发展到现在已经好几十年了,在理论上面已经有了很丰富的基础,并且在现实生活中也到处都在使用,可以说,经过几十年的发展,互联网技术已经把地域信息的隔…

英语学习笔记36——Where ... ?

Where … ? ……在哪里? 词汇 Vocabulary beside prep. 在……旁边 同义词: near by 构成:be side side n. 边 搭配:side walk 人行道 例句:Bobby在我旁边。    Bobby is beside me. off prep. 离开&#xff…

Excel使用技巧(一)

一. 快速调整数据位置 已经录入数据的表格,要调整某一列的位置怎么办? 只要选中要调整的数据区域,然后按住Shift键不放,光标放到绿色边框位置后,按下鼠标左键不放拖动即可: 二. 取消合并单元格并恢复数据…

java反序列化---cc6链

目录 Transformer[]数组分析 链条代码跟进 ChainedTransformer.transform() LazyMap.get() TiedMapEntry.getValue() TiedMapEntry.hashCode() HashMap.hash() HashMap.put()的意外触发 LazyMap.get()中key的包含问题 cc6的payload如下 import org.apache.commons.co…

AI绘画入门教学:ComfyUI工作流安装教程

ComfyUI 是专为 Stable Diffusion 打造的图形用户界面(GUI),采用了基于节点的操作方式。用户可以通过连接不同的模块(即节点)来创建复杂的图像生成流程。这些节点涵盖了多样的功能,包括加载检查点模型、输入…

CSS从入门到精通——背景样式

目录 背景颜色 任务描述 相关知识 背景色 编程要求 背景图片 任务描述 相关知识 背景图片 设置背景图片 平铺背景图像 任务要求 背景定位与背景关联 任务描述 相关知识 背景定位 背景关联 简写背景 编程要求 背景颜色 任务描述 本关任务:在本关…

在不损失质量的情况下减小PDF 文件大小的 6 种方法

PDF 文件通常带有大量图形和图像,这可能会使 PDF 文件大小相当大。而当我们通过电子邮件上传或发送具有大小限制的 PDF 时,大型 PDF 经常会带来麻烦,或者大文件占用了太多空间。在这种情况下,在不损失质量的情况下减小 PDF 文件大…

文章MSM_metagenomics(一):介绍

介绍 欢迎大家关注全网生信学习者系列: WX公zhong号:生信学习者Xiao hong书:生信学习者知hu:生信学习者CDSN:生信学习者2 用于复现Huang et al. [huang2024establishment]研究分析的计算工作流程,所有复…

基于51单片机的智能水表

一.硬件方案 本设计主要以51单片机作为主控处理器的智能水表,该水表能够记录总的用水量和单次用水量,当用水量超出设定值时系统发出声光报警提醒,水量报警值能够通过按键进行自行设置,并且存储于AT24C02中,并且可以测…

法国恐脱欧、陷金融危机!股指本周跌6.2%,创三年多最大跌幅

内容提要 法国财政部长警告称,左翼政党联盟若上台可能导致法国脱欧,而且无论极右翼还是左翼上台,都可能导致法国爆发金融危机。由于政坛风险高企,法国股市周五延续跌势,本周已经抹掉2100亿美元市值,几乎回…

RabbitMQ实践——利用一致性Hash交换器做带权重的调度

在《RabbitMQ实践——利用一致性Hash交换器做负载均衡》一文中,我们介绍了如何开启一致性hash交换器,并实现了消息的负载均衡,以达到横向扩展消费者数量的能力。 但是现实中,可能存在这样的场景:一些队列所在的机器配置…

ComfyUI 宝藏插件之辅助工具

今天我们就来分享下这个 ComfyUI 辅助脚本工具的功能。 插件安装,小伙伴们直接在管理器里搜索「ComfyUI-Custom-Scripts」,点击安装就可以了,这里再告诉小伙伴们一个小技巧,点击名称可以跳转到插件所在的官网哦。 没有安装管理器…

linux中DNS域名解析服务(后续补充)

分离解析简介: 分离解析的域名服务器实际也是主域名服务器,这里主要是指根据不同的客户端提供不同的域名解析记录。比如来自内网和外网的不同网段地址的客户机请求解析同一域名时,为其提供不同的解析结果。 实验要求:防火墙要么关…

【第10章】Vue之Element Plus常用组件

文章目录 前言一、表格1. 带斑马纹表格2. 展示 二、分页1.国际化(中文)2.分页代码3. 展示 三、表单1. 表单代码2. 展示 四、卡片1. 卡片代码2. 展示 总结 前言 通过上一章的快速入门,我们已经学习了按钮使用,接下来学习Element Plus的常用组件&#xff…

HTMLCSS详细总结(提高版)

HTML5的新特性 1. HTML5 新增的语义化标签 <div class“header”> </div> <div class“nav”> </div> <div class“content”> </div> <div class“footer”> </div> <header>&#xff1a;头部标签<nav>&#…

Stable Diffusion【应用篇】【艺术写真】:粘土风之后陶瓷风登场,来看看如何整合AI艺术写真吧

在国外的APP Remini引爆了粘土滤镜后&#xff0c;接着Remini又推出了瓷娃娃滤镜。相当粘土滤镜&#xff0c;个人更喜欢瓷娃娃滤镜&#xff0c;因为陶瓷工艺更符合东方艺术审美。 下面我们就来看看陶瓷特效在AI写真方面的应用。话不多说&#xff0c;我们直接开整。 关于粘土整…

day54 动态规划 part10 300.最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组

300.最长递增子序列 动规五部曲 1.dp[i]的定义 dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度 2.状态转移方程 位置i的最长升序子序列等于j从0到i-1各个位置的最长升序子序列 1 的最大值。 所以&#xff1a;if (nums[i] > nums[j]) dp[i] max(dp[i], dp…

Trumpf将携其用于光学传感的VCSEL紧凑型激光器精彩亮相

这款卓越的激光器将助力工业环境下的光学传感器焕发新活力。在即将到来的德国纽伦堡传感器测试盛会上&#xff08;6月11日至13日&#xff09;&#xff0c;通快光子元件将献上两场震撼的现场演示&#xff0c;全方位展示其单模VCSEL解决方案的卓越性能。 其中一场演示将深入浅出地…