内核移植笔记 Cortex-M移植

常用寄存器

PRIMASK寄存器
为1位宽的中断屏蔽寄存器。在置位时,它会阻止不可屏蔽中断(NMI)和HardFault异常之外的所有异常(包括中断)。
实际上,它是将当前异常优先级提升为0,这也是可编程异常/中断的最高优先级。

FAULTMASK寄存器
FAULTMASK与PRIMASK相类似,但同时它能屏蔽HardFault异常,它实际上是将异常优先级提升到了-1。

程序状态寄存器(xPSR)
xPSR包含:

  • 应用PSR(APSR)
  • 执行PSR(EPSR)
  • 中断PSR(IPSR)

在这里插入图片描述
注:GE 在 Cortex-M4 等 ARMv7E-M 处理器中存在,在 Cortex-M3 处理器中则不可用。

  • N:负标志
  • Z:零标志
  • C:进位(或者非借位)标志
  • V:溢出标志
  • Q:包含标志
  • GE:大于或等于标志
  • ICI/IT:中断继续指令位
  • T:Thumb状态,总是1,清除此位会引起错误异常
  • 异常变化:表示处理器正在处理的异常

中断向量表
Cortex-M系列处理器的中断向量表位于0x00000000,单Cortex-M3/4系列提供了SCB_VTOR,所以中断向量表的位置位于0x00000000+SCB_VTOR。

异常相关指令

  • CPSIE I:使能中断(清除PRIMASK)
  • CPSID I:禁止中断(设置PRIMASK),NMI和HardFault不受影响
  • CPSIE F:使能中断(清除FAULTMASK)
  • CPSID F:禁止中断(设置FAULTMASK),NMI不受影响

移植过程

在嵌入式领域有多种不同CPU架构,例如Cortex-M,ARM920T、MIPS、RISC-V等等。
为了使RT-Thread能够在不同CPU架构的芯片上运行,RT-Thread提供了一个libcpu抽象层适配不同的CPU架构

libcpu层向上对内核提供统一的接口,包括全局中断的开关,线程栈的初始化,上下文切换等。

libcpu抽象层向下提供了一套统一的CPU架构移植接口,这部分接口包含了全局中断开关函数,线程上下文切换函数,时钟节拍的配置和中断函数、Cache等等内容。

libcpu移植相关API,要对CPU进行移植只需要实现这些接口

关闭全局中断

/*rt_base_t rt_hw_interrupt_disable(void);*/.global rt_hw_interrupt_disable
.type rt_hw_interrupt_disable,%functionrt_hw_interrupt_disable:MRS R0,PRIMASK ;将PRIMASK关中断前的状态存入R0,并作为函数返回值返回CPSID I	;关闭中断BX LR
/*void rt_hw_interrupt_enable(rt_base_t level); level是调用关中断函数时的返回值,代表关中断前PRIMASK的值*/
.global rt_hw_interrupt_enable
.type rt_hw_interrupt_enable,%functionrt_hw_interrupt_enable:MSR PRIMASK,R0 ;将level写入PRIMASK寄存器,恢复关中断前的状态BX LR

实现线程栈初始化

在动态创建线程和初始化线程的时候,会使用到内部的线程初始化函数_rt_thread_init(),_rt_thread_init()函数会调用栈初始化函数rt_hw_stack_init(),在栈初始化函数里会手动构造一个上下文内容,这个上下文内容将被作为每个线程第一次执行的初始值。
上下文在栈里的排布如图:
在这里插入图片描述

rt_uint8_t *rt_hw_stack_init(void *tentry,void *parameter,rt_uint8_t *stack_addr,void *texit)
{struct stack_frame *stack_frame;rt_uint8_t         *stk;unsigned long       i;stk  = stack_addr + sizeof(rt_uint32_t);stk  = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stk, 8);stk -= sizeof(struct stack_frame);stack_frame = (struct stack_frame *)stk;/* init all register */for (i = 0; i < sizeof(struct stack_frame) / sizeof(rt_uint32_t); i ++){((rt_uint32_t *)stack_frame)[i] = 0xdeadbeef;}/* 根据 ARM  APCS 调用标准,将第一个参数保存在 r0 寄存器 */stack_frame->exception_stack_frame.r0  = (unsigned long)parameter; stack_frame->exception_stack_frame.r1  = 0;                        /* r1 */stack_frame->exception_stack_frame.r2  = 0;                        /* r2 */stack_frame->exception_stack_frame.r3  = 0;                        /* r3 *//* 将 IP(Intra-Procedure-call scratch register.) 设置为 0 */stack_frame->exception_stack_frame.r12 = 0;    //将线程退出函数的地址保存在lr寄存器stack_frame->exception_stack_frame.lr = (unsigned long) texit;//将线程入口函数的地址保存在pc寄存器stack_frame->exception_stack_frame.pc = (unsigned long) tentry;/* 设置 psr 的值为 0x01000000L,表示默认切换过去是 Thumb 模式 */stack_frame->exception_stack_frame.psr = 0x01000000L;              /* PSR */return stk;
}

实现上下文切换

在Cortex-M里面上下文切换都是统一使用PendSV异常来完成。
为了能适应不同的CPU架构,RT-Thread的libcpu抽象层需要实现三个线程相关的函数:

  1. rt_hw_context_switch_to():没有来源线程,切换到目标线程,在调度器启动第一个线程的时候被调用。
  2. rt_hw_context_switch():在线程环境下,从当前线程切换到目标线程。
  3. rt_hw_context_switch_intrrupt():在中断环境下,从当前线程切换到目标线程。

PendSV_Handler

产生PendSV异常时,Cortex-M系列处理器硬件会自动将from线程的PSR、PC、LR、R12、R3-R0压栈,因此在PendSV_Handler中,我们需要把from线程的R11-R4压栈,并把to线程的R11-R4弹出。修改PSP为to线程的栈地址,在退出PendSV中断时,硬件会自动弹出R3-R0、R12、LR、PC、PSR寄存器。

/*R0->保存from线程的栈,R1->保存to线程的栈*/
/*PSR PC LR...被放入from线程的栈*/
.global PendSV_Handler
.type PendSV_Handler, %functionPendCV_Handler:MRS R2,PRIMASKCPSID	ILDR R0, =rt_thread_switch_interrupt_flagLDR R1,[R0]CBZ R1,pendsv_exit MOV R1,#0STR R1,[R0]LDR R0,=rt_interrupt_from_threadLDR R1,[R0]CBZ R1,switch_to_threadMRS R1,PSPSTMFD R1!,{R4-R11} //将from线程的数据寄存器R4-R11压栈LDR R0,[R0] STR R1,[R0]switch_to_thread:LDR R1,=rt_interrupt_to_threadLDR R1,[R1]LDR R1,[R1]LDMFD R1!,{R4-R11} //将to线程寄存器弹出MSR PSP,R1 //更新栈指针pendsv_exit:MSR PRIMASK,R2ORR LR,LR,#0X4BX LR

rt_hw_context_switch_to

在这里插入图片描述

.global rt_hw_context_switch_to
.type rt_hw_context_switch_to,%functionrt_hw_context_switch_to:LDR R1,=rt_interrupt_to_threadSTR R0,[R1]LDR R1,=rt_interrupt_from_threadMOV R0,#0STR R0,[R1]LDR R1,=rt_thread_switch_interrupt_flagMOV R0,#1STR R0,[R1]LDR R0,=SHPR3LDR R1,=PENDSV_PRI_LOWESTLDR.W R2,[R0,#0]ORR     R1, R1, R2              /* modify */STR     R1, [R0]                /* write-back */LDR     R0, =ICSR               /* trigger the PendSV exception (causes context switch) */LDR     R1, =PENDSVSET_BIT        ;0x10000000,ICSR 的第 28 位为 PendSV set-pending bit.STR     R1, [R0]                ;Writing 1 to this bit is the only way to set the PendSV exception state to pending.//恢复MSP LDR R0,=SCB_VTORLDR R0,[R0] //读取中断向量表的位置LDR R0,[R0] //读取 SP初始值NOPMSR MSP,R0 ;将SP初始值赋给MSP/* enable interrupts at processor level */CPSIE   FCPSIE   I

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

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

相关文章

49.批处理命令(1/2)

目录 一批处理。 &#xff08;1&#xff09;批处理定义。 &#xff08;2&#xff09;常见命令。 &#xff08;2.1&#xff09;rem和:: &#xff08;2.2&#xff09;echo和。 &#xff08;2.3&#xff09;pause。 &#xff08;2.4&#xff09;errorlevel。 &#xff08;…

Halcon WPF 开发学习笔记(2):Halcon导出c#脚本

文章目录 前言HalconC#教学简单说明如何二开机器视觉 前言 我目前搜了一下我了解的机器视觉软件&#xff0c;有如下特点 优点缺点兼容性教学视频(B站前三播放量)OpenCV开源&#xff0c;免费&#xff0c;因为有源码所以适合二次开发学习成本极高&#xff0c;卡学历。研究生博士…

【Java】Netty创建网络服务端客户端(TCP/UDP)

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍Netty创建网络服务端客户端示例。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更…

再聊canal的FlatMessage和事务之间的关系

背景 近期得益于项目上的技改推动,我对canal又有了进一步的认识。 最开始我以为flatMassage的id代表的是binlog的唯一id,随着对canal的使用深度不断加深,我逐渐认识到原先认为的是错误的。 你是否有过这样的疑问: 事务与FlatMessage的id是什么关系?不同事务的FlatMessa…

Java线程池——Executor框架

文章目录 一、Executor接口二、ExecutorService接口三、ThreadPoolExecutor类1、状态2、Worker3、扩展 四、ForkJoinPool类1、工作窃取算法2、Fork/Join的设计3、执行原理 五、ScheduledThreadPool类1、ScheduledExecutorService2、比较Timer 六、Executors类 Executor 框架是 …

Windows系统安装2个版本得的MySQL

一、MySQL官网下载对应版本的zip文件 最新版本8.0.34下载链接&#xff1a;https://dev.mysql.com/downloads/mysql/ MySQL 5.7下载链接&#xff1a;https://downloads.mysql.com/archives/community/ 二、将下载到的压缩包解压到指定目录 使用解压工具将下载到的压缩包解…

智安网络|探索人机交互的未来:自然语言处理的前沿技术

自然语言处理是人工智能领域中研究人类语言和计算机之间交互的一门学科。它涉及了语言的理解、生成、翻译、分类和摘要等多个方面。随着人们对自然语言处理的重视和需求不断增长&#xff0c;成为了热门的研究方向。 首先&#xff0c;我们需要了解自然语言处理的基本概念。自然…

Learning an Animatable Detailed 3D Face Model from In-The-Wild Images论文笔记

Learning an Animatable Detailed 3D Face Model from In-The-Wild Images论文笔记 论文目标:提出一个端到端的框架,可以从非受控的图片中学习高质量、可动画的3D人脸模型。论文方法:论文结果:论文意义: 论文目标:提出一个端到端的框架,可以从非受控的图片中学习高质量、可动画…

js实现定时刷新,并设置定时器上限

定时器 在js中&#xff0c;有两种定时器&#xff1a; 倒计时定时器 倒计时定时器&#xff0c;也叫延时定时器或一次性定时器 功能&#xff1a;倒计时多长时间后执行某个动作 语法&#xff1a;setTimeout(function, timeout); 返回值&#xff1a;int类型&#xff0c;当前定时器…

Transforme原理--全局解读

文章目录 作用全局解读 作用 Transformer最初设计用于处理序列数据&#xff0c;特别在NLP(自然语言处理)领域取得了巨大成功 全局解读 Transformer来源于谷歌的一篇经典论文Attention is All you Need 在此使用Transformer在机器翻译中的运用来讲解Transformer。 其中Tran…

Scrum Master 如何更好的支持PO?

在过去几年中&#xff0c;和许多Scrum Master交流时&#xff0c;我遇到一个令人担忧的模式。虽然我们有Scrum指南和其他补充资源&#xff0c;许多Scrum Master&#xff0c;特别是刚起步的Scrum Master们&#xff0c;还在日复一日的为如何帮助Product Owner而挣扎着。 以下是我…

88.Linux系统下关于fork的经典练习

题目描述 下列程序输出几个A&#xff1f; 运行结果 输出6个A 根据代码段仔细执行&#xff0c;注意for循环的i的值即可得出答案 下列程序输出几个A&#xff1f; (这个printf后面是不带\n也就是说不刷新缓冲区) 运行结果 输出8个A&#xff0c;要注意到此程序的printf语句没有…

数据分析实战 | K-means算法——蛋白质消费特征分析

目录 一、数据及分析对象 二、目的及分析任务 三、方法及工具 四、数据读入 五、数据理解 六、数据准备 七、模型训练 ​编辑 八、模型评价 九、模型调参与预测 一、数据及分析对象 txt文件——“protein.txt”&#xff0c;主要记录了25个国家的9个属性&#xff0c;主…

11月份 四川汽车托运报价已经上线

中国人不骗中国人!! 国庆小长假的高峰期过后 放假综合症的你还没痊愈吧 今天给大家整理了9条最新线路 广州到四川的托运单价便宜到&#x1f4a5; 核算下来不过几毛钱&#x1f4b0; 相比起自驾的漫长和疲惫&#x1f697; 托运不得不说真的很省事 - 赠送保险 很多客户第一次运车 …

【Android】Lombok for Android Studio 离线插件

下载地址 https://plugins.jetbrains.com/plugin/6317-lombok/versions/stable 安装方法 File - Settings - Plugins - 设置按钮 - Install Plugin from Disk - 选择插件包 添加依赖 //Lombokapi org.projectlombok:lombok:1.18.30annotationProcessor org.projectlombok:l…

管理能力测评,如何提升管理能力?

管理能力是综合能力的体现&#xff0c;通常也解读为组织管理能力&#xff0c;如果要再细分的话&#xff0c;可能还包括有沟通能力&#xff0c;协调能力&#xff0c;组织能力&#xff0c;执行力和专业能力等等。不过没有办法说的太细节&#xff0c;因为每个部分铺开了都是一个独…

【ARM Trace32(劳特巴赫) 使用介绍 3 - trace32 访问运行时的内存】

请阅读【ARM Coresight SoC-400/SoC-600 专栏导读】 文章目录 1.1 trace32 访问运行时的内存1.1.1 侵入式 运行时内存访问1.1.2 非侵入式运行时访问1.1.3 缓存一致性的非侵入式运行时访问 1.2 Trace32 侵入式和非侵入式 运行时访问1.2.1 侵入式访问1.2.2 非侵入式运行时访问 1…

多级缓存之缓存同步

缓存数据同步的常见方式有三种&#xff1a; 设置有效期&#xff1a;给缓存设置有效期&#xff0c;到期后自动删除。再次查询时更新 优势&#xff1a;简单、方便缺点&#xff1a;时效性差&#xff0c;缓存过期之前可能不一致场景&#xff1a;更新频率较低&#xff0c;时效性要…

1994-2021年分行业二氧化碳排放量数据

1994-2021年分行业二氧化碳排放量数据 1、时间&#xff1a;1994-2021年 2、来源&#xff1a;原始数据整理自能源年鉴 3、指标&#xff1a;统计年度、行业代码、行业名称、煤炭二氧化碳排放量、焦炭二氧化碳排放量、原油二氧化碳排放量、汽油二氧化碳排放量、煤油二氧化碳排放…

聊聊LogbackMDCAdapter

序 本文主要研究一下LogbackMDCAdapter MDCAdapter org/slf4j/spi/MDCAdapter.java public interface MDCAdapter {/*** Put a context value (the <code>val</code> parameter) as identified with* the <code>key</code> parameter into the cur…