RTT学习 cortex-m移植

Cortex-M移植

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

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

程序状态寄存器(xPSR)

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

在这里插入图片描述

GE在Cortex-M4等ARMv7E-M处理器中存在,在Cortex-M3处理器中则不可用。

  • N:负标志
  • Z:零标志
  • C:进位标志
  • V:溢出标志
  • Q:饱和标志
  • GE:大于或等于标志
  • ICI/IT:IF_THEN指令状态位用于条件执行
  • T:THUMB状态,总是1,清除此位会引起错误异常
  • 异常编号:标识处理器正在处理的异常

中断向量表
Cortex-M系列处理器的中断向量表位于0x00000000,但Cortex-M3/4系列提供了Vector table offset register(SCB_VTOR),所以,中断向量表的位置位于0x00000000 + SCB_VTOR。

异常相关指令

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

移植过程

在嵌入式领域有多种不同CPU架构,例如Cortex-M、ARM920T、MIPS32、RISC-V等等。
为了使RTT能够在不同CPU架构的芯片上运行,RTT提供了一个libcpu抽象层来适配不同的CPU架构。libcpu层向上对内核提供统一的接口,包括全局中断的开关,线程栈的初始化,上下文切换等。

RTT的libcpu抽象层向下提供了一套统一的CPU架构移植接口,这部分接口包含了全局中断开关函数、时钟节拍的配置和中断函数、Cache 等等内容。下表是 CPU 架构移植需要实现的接口和变量。

在这里插入图片描述
要对CPU进行移植,只需实现上述接口。

rt_hw_interrupt_disable PROC
	EXPORT rt_hw_interrupt_disable
	MRS r0,PRIMASK
	CPSID I
	BX LR
	ENDP
rt_hw_interrupt_enable PROC
	EXPORT rt_hw_interrupt_enable
	MSR PRIMASK, r0
	BX LR
	ENDP

实现线程栈初始化

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

struct exception_stack_frame
{
	rt_uint32_t r0;
	rt_uint32_t r1;
	rt_uint32_t r2;
	rt_uint32_t r3;
	rt_uint32_t r12;
	rt_uint32_t lr;
	rt_uint32_t pc;
	rt_uint32_t psr;
};
struct stack_frame
{
	/* r4 ~ r11 register */
    rt_uint32_t r4;
    rt_uint32_t r5;
    rt_uint32_t r6;
    rt_uint32_t r7;
    rt_uint32_t r8;
    rt_uint32_t r9;
    rt_uint32_t r10;
    rt_uint32_t r11;

	struct exception_stack_frame exception_stack_frame;
};

这段代码定义了两个结构体:exception_stack_frame 和 stack_frame。这些结构体的目的是为了在嵌入式系统中有效地管理和保存堆栈信息。

  1. exception_stack_frame结构体包含了在发生异常时需要保存的寄存器的值,这些寄存器包括r0到psr,分别是 ARM Cortex-M 架构中的通用寄存器和程序状态寄存器。这些寄存器保存了在异常发生时的现场信息,对于异常处理和调试非常重要。
  2. stack_frame 结构体是嵌套在其中的,它除了包含了用于存储通用寄存器的值的字段外,还包含了一个 exception_stack_frame 结构体的实例。这样设计的目的是为了在发生异常时,能够将 exception_stack_frame 结构体中的内容一并保存到 stack_frame 中,以便于整个堆栈帧的管理和处理。
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;

	/*初始化所有寄存器*/
	for(i=0; i<sizeof(struct stack_frame)/sizeof(rt_uint32_t); i++){
		((rt_uint32_t *)stack_frame)[i] = 0xdeadbeef;
	}

	stack_frame->exception_stack_frame.r0 = (unsigned long)parameter;
	/* 其他参数寄存器初始化为 0 */
    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;                        /* r12 */
    stack_frame->exception_stack_frame.lr = (unsigned long)texit;
    stack_frame->exception_stack_frame.pc = (unsigned long)tentry;
    stack_frame->exception_stack_frame.psr = 0x01000000L;   

	return stk;
}

实现上下文切换

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

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

PendSV_Handler

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

实现时钟节拍

要实现时间片轮转调度、软定时器、,必须要保证 rt_tick_increase() 被周期性调用。在 Cortex-M 系列 MCU 中,可以使用系统滴答定时器来对其周期性调用。

void SysTick_Handler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();

    rt_tick_increase();

    /* leave interrupt */
    rt_interrupt_leave();
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Jenkins CI/CD 持续集成专题四 Jenkins服务器IP更换

一、查看brew 的 services brew services list 二、编辑 homebrew.mxcl.jenkins-lts.plist 将下面的httpListenAddress值修改为自己的ip 服务器&#xff0c;这里我是用的本机的ip 三 、重新启动 jenkins-lts brew services restart jenkins-lts 四 、浏览器访问 http://10.…

golang学习笔记(defer基础知识)

什么是defer defer语句用于golang程序中延迟函数的调用&#xff0c; 每次defer都会把一个函数压入栈中&#xff0c; 函数返回前再把延迟的函数取出并执行。 为了方便描述&#xff0c; 我们把创建defer的函数称为主函数&#xff0c; defer语句后面的函数称为延迟函数。延迟函数…

【Burpsuite靶场】XSS专题精讲

【个人】&#xff1a;NEUQ大一学生 【专业】&#xff1a;通信工程 (Communication Engineering) 【个人方向】&#xff1a;网安、开发双管齐下 【座右铭】&#xff1a;真正的英雄主义,就是看清生活的真相后依然热爱生活 -- 罗曼.罗兰 一、认识XSS&#xff08;跨站脚本攻击&…

fatal: unable to access ‘https://github.com/alibaba/flutter_boost.git/

Git error. Command: git fetch stdout: stderr: fatal: unable to access ‘https://github.com/alibaba/flutter_boost.git/’: Failed to connect to github.com port 443 after 75005 ms: Couldn’t connect to server exit code: 128 GitHub (国际型)代码 分发平台/托管平…

梯度下降法总是在同一点收敛吗?

梯度下降法总是在同一点收敛吗&#xff1f; 梯度下降法并不总是在同一点收敛。梯度下降法的收敛取决于多个因素&#xff0c;包括初始参数的选择、学习率的设置、损失函数的形状等。 以下是一些影响梯度下降法收敛行为的关键因素&#xff1a; 1.初始参数&#xff1a; 初始参数…

Json-server 模拟后端接口

json-server&#xff0c;模拟rest接口&#xff0c;自动生成增删改查接口。(官网地址&#xff1a;json-server - npm) 使用方法&#xff1a; 1. 安装json-server&#xff0c;npm i json-server -g 2. 创建json文件&#xff0c;文件中存储list数据&#xff0c;db.json {"…

图像超分辨率技术在AI去衣中的应用探索

在数字图像处理领域&#xff0c;图像超分辨率&#xff08;Super-Resolution, SR&#xff09;技术一直是研究的热点之一。该技术旨在从低分辨率的图像中恢复出高分辨率的图像&#xff0c;以提供更清晰、更丰富的细节信息。近年来&#xff0c;随着人工智能&#xff08;AI&#xf…

<计算机网络自顶向下> 路由器组成

路由器结构概况 路由&#xff1a;运行路由选择算法/协议&#xff08;RIP, OSPF, BGP&#xff09;生成路由表转发&#xff1a;从输入到输出链路交换数据包-根据路由表进行分组的转发中间的fabric是用来接收输入的分组交给输出端口的&#xff0c;完成局部的转发&#xff08;根据…

free 命令示例

目录 ⛳️推荐 前言 Linux 中如何使用 free 命令 1、以人类可读的形式显示信息 2、连续显示统计数据 3、定义显示统计数据的次数 4、指定输出数据类型 5、获取物理内存和交换内存的总和 总结 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&am…

掌握注册唤起应用的秘诀,Xinstall助你提升用户体验

在移动互联网时代&#xff0c;App已经成为我们日常生活中不可或缺的一部分。然而&#xff0c;随着App数量的激增&#xff0c;如何让自己的App在激烈的市场竞争中脱颖而出&#xff0c;成为开发者们关注的焦点。其中&#xff0c;注册唤起应用作为提升用户体验和转化率的关键环节&…

4- 24

day02 1.100个英语单词 2.vp div3 不过有点小悲惨&#xff0c;第一题正常的直接看出来答案。第二题其实是map模拟&#xff0c;一直没有读懂题目的意思&#xff0c;题目给的序列是打乱的。找出最小的&#xff0c;讲原来的序列补全&#xff0c;如果mp中没有这个数字&#xff0c;…

Linux网络-DHCP原理与配置

目录 一.DHCP工作原理 1.了解DHCP服务 1.1.使用DHCP的好处 1.2.DHCP的分配方式 2.DHCP的租约过程 2.1.DHCP工作原理 2.2.DHCP交互过程 二.DHCP服务器的配置 1.关闭防火墙 2.检查并且安装DHCP有关软件包 3.查看系统的配置文件 3.1.设置参数 4.修改网络 4.1.修改虚…

python高级进阶(一)[str字符串、set集合、dict字典]

目录 一、str字符串 1. 字符串的概念 2.字符串的特点 3. 定义字符串 4. 获取字符串中的某个元素 5. 遍历字符串 6. 字符串的常用方法 6.1 判断 6.2 转换 6.3 查找 6.4 切割 6.5 去空白 7. 小案例【用户名和密码合法校验】 8. 常用方法中 isdecimal() 和 isdigi…

前端开发攻略---封装calendar日历组件,实现日期多选。可根据您的需求任意调整,可玩性强。

1、演示 2、简介 1、该日历组件是纯手搓出来的&#xff0c;没依赖任何组件库&#xff0c;因此您可以随意又轻松的改变代码&#xff0c;以实现您的需求。 2、代码清爽干净&#xff0c;逻辑精妙&#xff0c;您可以好好品尝。 3、好戏开场。 3、代码&#xff08;Vue3写法&#xff…

分布式与一致性协议之CAP(一)

CAP理论 概述。 在开发分布式系统的时候&#xff0c;会遇到一个非常棘手的问题&#xff0c;那就是如何根据业务特点&#xff0c;为系统设计合适的分区容错一致性模型&#xff0c;以实现集群能力。这个问题棘手在当发生分区错误时&#xff0c;应该如何保障系统稳定运行而不影响…

C++多态(个人笔记)

C多态 1.多态的定义以及实现1.1多态的构成条件1.2虚函数1.3虚函数的重写1.4override和final1.5函数重载&#xff0c;覆盖&#xff08;重写&#xff09;&#xff0c;隐藏&#xff08;重定义&#xff09;区别 2.抽象类2.1接口继承和实现继承的区别 3.多态原理3.1虚函数表3.2多态的…

SpringBoot整合七牛云实现图片的上传管理

唠嗑部分 各位小伙伴大家好&#xff0c;我是全栈小白&#xff0c;今天我们来分享一下SpringBoot如何整合七牛云存储实现图片的上传与存储 首先我们来说说图片存储&#xff0c;在项目中图片几乎是必不可少的&#xff0c;那么大家会选择怎样存储呢&#xff0c;当然有几种方案 …

软件游戏缺失d3dcompiler_43.dll怎么修复?分享多种靠谱的解决方法

在我们日常频繁地操作和使用电脑的过程中&#xff0c;时常会遇到一些突发的技术问题。其中一种常见的情况是&#xff0c;在尝试启动或运行某个应用程序时&#xff0c;系统会弹出一个错误提示窗口&#xff0c;明确指出当前电脑环境中缺少了一个至关重要的动态链接库文件——d3dc…

算法学习笔记Day9——动态规划初探

一、介绍 本文解决几个问题&#xff1a;动态规划是什么&#xff1f;解决动态规划问题有什么技巧&#xff1f;如何学习动态规划&#xff1f; 1. 动态规划问题的一般形式就是求最值。动态规划其实是运筹学的一种最优化方法&#xff0c;只不过在计算机问题上应用比较多&#xff…

STM32cubemx和HAL库的使用入门--点亮一颗LED

一&#xff1a;流程介绍 &#xff08;1&#xff09;环境搭建 1 &#xff1a;stm32cubemx安装 2 &#xff1a;stm32xxFW安装 3 &#xff1a;MDK5安装 4 &#xff1a;生成MDK版本project &#xff08;2&#xff09;stm32cubemx创建工程&#xff0c;选择芯片型…