RT-Thread内核机制 线程栈

int flag;

void cmp_val(int a,int b)
{
	volatile int tmp[10];
	tmp[0] = a;
	if(tmp[0] > b)
	{
		flag = 1;
	}else{
		flag = 0;
	}
}

int main()
{
	int a = 1;
	int b = ;
	cmp_val(a,b);
	return 0;
}

在这里插入图片描述
我们写好的程序会保存在Flash上。
在这里插入图片描述
其它类似汇编指令
SUB R0,R0,#4 R0 = R0-4
B LR 放入LR寄存器

局部变量保存在栈里。

在这里插入图片描述
SUB sp,sp,#0x28 sp=sp-40;
为什么要SP要减去40?数组是int类型,刚好有10个,所以是40。

STR r0,[sp,#0x00] 将r0的值保存进sp指针现在所指向的位置
C语言中的函数,传入的第一个参数就保存在R0中,第二个参数保存在R1中。

LDR r2,[sp,#0x00] 将sp指针现在指向的存储位置的值保存进入r2寄存器中。

CMP r2,r1 比较两个寄存器中的值,结果保存在PSR(程序状态寄存器)中。

BLE 0x08000166 如果比较结果小于等于,就跳转到地址0x08000166

MOVS r2,#0x00 把r2赋值为0
STR r2,[r3,#0x00] 把r2赋值给r3指向的变量(flag)

在这里插入图片描述
切换线程时要保存所有寄存器的值。
在这里插入图片描述
除了R13,其余都要保存,R13是栈,一般在其它地方中保存。(16个)

16个寄存器保存在栈中。

在这里插入图片描述

保存在线程的栈中。

在这里插入图片描述
线程A切换到线程B需要做的事情:

  1. 保存A的16个寄存器到A的栈。
  2. 从B的栈恢复16个寄存器到CPU。

发生Tick中断时,16个寄存器中有一些是硬件直接保存的,剩下的是软件保存。

上下文切换

rt_hw_context_switch((rt_ubase_t)&from_thread->sp, (rt_ubase_t)&to_thread->sp);
    .global rt_hw_context_switch_to
    .type rt_hw_context_switch_to, %function
rt_hw_context_switch_to:
    LDR     R1, =rt_interrupt_to_thread
    STR     R0, [R1]

    /* set from thread to 0 */
    LDR     R1, =rt_interrupt_from_thread
    MOV     R0, #0
    STR     R0, [R1]

    /* set interrupt flag to 1 */
    LDR     R1, =rt_thread_switch_interrupt_flag
    MOV     R0, #1
    STR     R0, [R1]

    /* set the PendSV exception priority */
    LDR     R0, =SHPR3
    LDR     R1, =PENDSV_PRI_LOWEST
    LDR.W   R2, [R0,#0]             /* read */
    ORR     R1, R1, R2              /* modify */
    STR     R1, [R0]                /* write-back */

    LDR     R0, =ICSR               /* trigger the PendSV exception (causes context switch) */ //触发一个PendSV异常,异常发生后,异常处理函数就会被调用
    LDR     R1, =PENDSVSET_BIT
    STR     R1, [R0]

    /* restore MSP */
    LDR     r0, =SCB_VTOR
    LDR     r0, [r0]
    LDR     r0, [r0]
    NOP
    MSR     msp, r0

    /* enable interrupts at processor level */
    CPSIE   F
    CPSIE   I
利用PendSV异常,来进行任务的切换
PendSV_Handler:
    /* disable interrupt to protect context switch */
    MRS     R2, PRIMASK
    CPSID   I

    /* get rt_thread_switch_interrupt_flag */
    LDR     R0, =rt_thread_switch_interrupt_flag
    LDR     R1, [R0]
    CBZ     R1, pendsv_exit         /* pendsv aLReady handled */

    /* clear rt_thread_switch_interrupt_flag to 0 */
    MOV     R1, #0
    STR     R1, [R0]

    LDR     R0, =rt_interrupt_from_thread
    LDR     R1, [R0]
    CBZ     R1, switch_to_thread    /* skip register save at the first time */

    MRS     R1, PSP                 /* get from thread stack pointer */ //获取线程A的栈
    STMFD   R1!, {R4 - R11}         /* push R4 - R11 register */ //软件保存剩余寄存器
    LDR     R0, [R0]
    STR     R1, [R0]                /* update from thread stack pointer */

switch_to_thread:
    LDR     R1, =rt_interrupt_to_thread
    LDR     R1, [R1]
    LDR     R1, [R1]                /* load thread stack pointer */ //获取线程B的栈

    LDMFD   R1!, {R4 - R11}         /* pop R4 - R11 register */ //从栈里恢复R4-R11,软件恢复
    MSR     PSP, R1                 /* update stack pointer */

STMFD:Store Multi Full Dec

中断时,硬件保存的寄存器
在这里插入图片描述
恢复时,软件恢复一部分寄存器,硬件恢复一部分寄存器。

在这里插入图片描述
创建线程时,分配一个栈空间,同时要为栈空间预存放的寄存器空间赋值。将PC寄存器存放的位置赋值为thread2_entry,当线程运行时,将栈空间存放的各个寄存器的值赋值到对应的寄存器,此时CPU就可以开始运行thread2_entry。

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); //stk-64

    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;
    }

    stack_frame->exception_stack_frame.r0  = (unsigned long)parameter; /* r0 : argument */ //参数
    stack_frame->exception_stack_frame.r1  = 0;                        /* r1 */
    stack_frame->exception_stack_frame.r2  = 0;                        /* r2 */
    stack_frame->exception_stack_frame.r3  = 0;                        /* r3 */
    stack_frame->exception_stack_frame.r12 = 0;                        /* r12 */
    stack_frame->exception_stack_frame.lr  = (unsigned long)texit;     /* lr */
    stack_frame->exception_stack_frame.pc  = (unsigned long)tentry;    /* entry point, pc */ //函数入口地址
    stack_frame->exception_stack_frame.psr = 0x01000000L;              /* PSR */

    /* return task's current stack address */
    return stk;
}

首先栈要先减去stack_frame的空间

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;
};

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;
};

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

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

相关文章

【Interaction交互模块】LinearTransformDrive线性变换驱动

文章目录 一、预设位置二、案例&#xff1a;建一个按下后可自动抬起的按钮三、留有疑问 一、预设位置 交互——可控制物体——变换——线性变换驱动 二、案例&#xff1a;建一个按下后可自动抬起的按钮 按钮的结构和设置如下图 为了让它碰触时&#xff0c;往下走——预设体…

spring boot 测试用例

依赖包 <dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.2.5.RELEASE</version><scope>compile</scope></dependency><dependency><groupId>ju…

CleanMyMac最新版4.14Mac清理软件下载安装使用教程

苹果电脑是很多人喜欢使用的一种电脑&#xff0c;它有着优美的外观&#xff0c;流畅的操作系统&#xff0c;丰富的应用程序和高效的性能。但是&#xff0c;随着时间的推移&#xff0c;苹果电脑也会产生一些不必要的文件和数据&#xff0c;这些文件和数据就是我们常说的垃圾。那…

ChatGPT辅助编写自动化测试

大家好&#xff0c;我是洋子&#xff0c;ChatGPT已经越来越火爆&#xff0c;国内百度、阿里等互联网大厂也纷纷投入大模型研究&#xff0c;OpenAI官网中提供了许多ChatGPT应用场景&#xff0c;例如SQL翻译、语言翻译、代码解释等 作为一名QA&#xff0c;我更关注ChatGPT生成的…

探索三丰云:免费虚拟主机与云服务器的新选择**

随着云计算技术的飞速发展&#xff0c;我们有了更多的选择来满足我们的在线业务需求。今天&#xff0c;我想向大家推荐一款我最近发现的优质服务——三丰云。 三丰云&#xff08;https://www.sanfengyun.com&#xff09;是一家提供免费虚拟主机和免费云服务器的公司&#xff0…

简易虚拟培训系统-UI控件的应用5

目录 Toggle控件简介 示例-使用Toggle组实现主轴速度选择 本篇介绍UI控件Toggle&#xff0c;尝试一个小示例-使用单选框实现速度的选择控制。 Toggle控件简介 1. Toggle的结构如下&#xff1a;最重要的Toggle组件挂在Toggle节点上&#xff0c;下面的Image组件用于显示单选框…

单元测试用例mock的使用方法

单元测试用例mock的使用方法 提升代码测试覆盖率的关键策略 为什么单元测试是如此重要&#xff1f; 在软件开发中&#xff0c;单元测试是一个关键的环节&#xff0c;可以确保代码的质量和稳定性。而在进行单元测试时&#xff0c;使用mock对象可以帮助我们更好地测试代码逻辑…

【办公自动化】使用Python批量处理Excel文件并转为csv文件

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

【CSS左右上角斜标签】CSS实现左右上角飘带功能,左右上角斜标签(附源码)

文章目录 写在前面涉及知识点实现效果1、实现过程1.1左上角飘带Html代码Css代码效果 1.2右上角飘带Html代码Css代码效果 2、源码分享2.1 百度网盘2.2 123网盘2.3 邮箱留言 总结 写在前面 其实在公司页面开发过程就遇到过&#xff0c;需要在方块右上角展示一个斜的文字或者告警…

elementUi中的el-table表格的内容根据后端返回的数据用不同的颜色展示

效果图如下&#xff1a; 首先 首先&#xff1a;需要在表格行加入 <template slot-scope"{ row }"> </template>标签 <el-table-column prop"usable" align"center" label"状态" width"180" ><templ…

TCP数据报结构分析(面试重点)

在传输层中有UDP和TCP两个重要的协议&#xff0c;下面将针对TCP数据报的结构进行分析 关于UDP数据报的结构分析推荐看UDP数据报结构分析&#xff08;面试重点&#xff09; TCP结构图示 TCP报头结构的分析 一.16位源端口号 源端口表示发送数据时&#xff0c;发送方的端口号&am…

【GO】LGTM_Grafana_Tempo(2)_官方用例改后实操

最近在尝试用 LGTM 来实现 Go 微服务的可观测性&#xff0c;就顺便整理一下文档。 Tempo 会分为 4 篇文章&#xff1a; Tempo 的架构官网测试实操跑通gin 框架发送 trace 数据到 tempogo-zero 微服务框架使用发送数据到 tempo 根据官方文档实操跑起来 tempo&#xff0c;中间根…

微信小程序 趣味学习与益智游戏系统APP

管理员、用户可通过HBuilder系统手机打开系统&#xff0c;注册登录后可进行管理员后端&#xff1b;首页、个人中心、用户管理、学生分类管理、学一学管理、玩一玩管理、听一听管理、试题管理、练一练管理、系统管理、考试管理&#xff0c;用户前端&#xff1b;首页、学一学、玩…

Linux 内核动态打印调试(dev_info、 dev_dbg )

目录 前言 1 printk消息级别 2 调整内核printk打印级别 3 dev_xxx函数简介 4 配置内核使用动态打印 5 动态调试使用方法 6 动态打印调试的基本原理 &#x1f388;个人主页&#x1f388;&#xff1a;linux_嵌入式大师之路的博客-CSDN博客&#x1f389;&#x1f389;&…

Mysql优化原理分析

一、存储引擎 1.1 MyISAM 一张表生成三个文件 xxx.frm&#xff1a;存储表结构xxx.MYD&#xff1a;存储表数据xxx.MYI&#xff1a;存储表索引 索引文件和数据文件是分离的&#xff08;非聚集&#xff09; select * from t where t.col1 30; 先去t.MYI文件查找30对应的索引…

【Terraform学习】Terraform模块基础操作(Terraform模块)

本站以分享各种运维经验和运维所需要的技能为主 《python》&#xff1a;python零基础入门学习 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8》暂未更新 《docker学习》暂未更新 《ceph学习》ceph日常问题解…

Python爬虫框架之Selenium库入门:用Python实现网页自动化测试详解

概要 是否还在为网页测试而烦恼&#xff1f;是否还在为重复的点击、等待而劳累&#xff1f;试试强大的Selenium&#xff01;让你的网页自动化测试变得轻松有趣&#xff01; 一、Selenium库到底是什么&#xff1f; Selenium 是一个强大的自动化测试工具&#xff0c;它可以让你直…

单片机(二)使用位移 让灯亮

一&#xff1a;硬件电路 P2 口&#xff1a; P2.0~ P2.7 是这些 I0 口 LED 阳极接 电源 &#xff0c; P20 口 为低电平 可以让 LED灯 亮 二&#xff1a;软件实现部分 两种 ① 通过循环 来展示从左 到右 #include "reg52.h"#define LED_PORT P2 // 定义单片机的P2端…

5G工业网关赋能救护车远程监控,助力高效救援

智慧医疗是传统医疗业发展进步的必要趋势&#xff0c;医疗设备通过物联网技术的应用实现智能化转型。通过5G工业网关将医疗器械等设备的数据采集再经过专网传输到医疗系统中&#xff0c;实现医疗设备间的数据共享和远程监控&#xff0c;能够帮助医疗行业大大提高服务质量和管理…

Unity——资产包(Asset Bundles)

对很多单机游戏来说&#xff0c;游戏的所有资源往往是与游戏本体一同发布的&#xff0c;资源部西药独立出来。但对于大型商业项目来说&#xff0c;游戏产品还需要再发布之后进行维护和更新&#xff0c;这就引出了Unity资产包的概念 一、资产包&#xff08;Asset Bundles&#x…