韦东山老师 RTOS 入门课程(一)RTOS 介绍,熟悉裸机的汇编逻辑

韦东山老师 RTOS 入门课程

课程链接:韦东山直播公开课:RTOS实战项目之实现多任务系统 第1节:裸机程序框架和缺陷_哔哩哔哩_bilibili

RTOS 介绍

裸机:固定顺序执行。

中断:可以一直专心做循环里的事情,直到触发中断。也可以中断里设立 flag 在循环里检测执行,防止中断超时。

定时器:太多个任务的时候不适合说都用中断。可以用定时器,设定不同任务的执行频率,比如 A 1ms 执行一次,B 2ms 执行一次…… 但是相互之间会有影响,比如 A 卡住了会影响 B。

还有一种解决办法是状态机。每个函数设定几个状态,每次执行一部分状态后保留当前状态退出,下次进入的时候继续执行。

image-20230818232306800

状态机有四大概念:状态,事件,动作,变换。

状态就是不同的状态。

事件是执行某个操作的触发条件,比如门开状态我发起关门事件,门关事件我发起开门事件。

动作是由事件触发额具体行为。

变换是状态之间的切换。

状态机忒麻烦而且也没有那么优。

RTOS 比如可以设定每个程序按一定时间片执行,到时间自己切换,不用自己写状态机那么复杂。而且现在 RTOS 生态比较好(特别是 rt-thread),而且大多数开发都需要 RTOS 。其实用了 RTOS 反而更简单。

ARM 基础

程序是什么?

运行程序时,先把程序烧录到 flash 文件中,数据放入 RAM 中(可变),CPU 读指令取数据写数据。RAM 中的数据是拿到了 CPU 的寄存器中。

这里我们重点关注6条 arm 指令即可。

  1. 读指令。LDR R0,[R1,#4],指明了 rd, rs, length。LDR 是固定取 4B,从 R1+4 地址取。
  2. 写指令。STR R0,[R1,#4]
  3. 加减。ADD R0,R1,R2 ADD R0,R0,#1 SUB R0,R1,R2
  4. 比较。CMP R0,R1 结果存在 PSR 中。
  5. 跳转 B BL ,BL 是跳转后还保存返回地址。

分析C的汇编码,理解程序

image-20230819133726104

用一个很简单的程序来举例,Keil 进入调试模式后可以看到对应代码的汇编码。

首先通过 PUSH 指令自动压栈 r3 lr 并修改 sp 指针,保存 r3 寄存器和函数返回地址

第二句令 r0 = a 的地址。

第三句根据地址取出 a 的值存入 r0.

第四句 r0 的值存入栈0的位置,因为刚才压栈后,栈中从高到低分别存了 lr r3,也就是说r0 实际上是把数据存入栈中 r3 的位置,r3 入栈是在栈中占了一个栈中的位。

然后出栈,lr 赋值给 pc 以供函数返回,r3 获取到栈中写入的值。

再看第二个程序:

int add_val(int *pa, int *pb)
{volatile int tmp;tmp = *pa;tmp += *pb;return tmp;
}int mymain()
{volatile int a = 1;volatile int b = 2;volatile int c;c = add_val(&a, &b);return 0;
}

汇编得到的代码(在 .dis 文件中):

    i.mymainmymain0x08000372:    b50e        ..      PUSH     {r1-r3,lr}0x08000374:    2001        .       MOVS     r0,#10x08000376:    9002        ..      STR      r0,[sp,#8]0x08000378:    2002        .       MOVS     r0,#20x0800037a:    9001        ..      STR      r0,[sp,#4]0x0800037c:    a901        ..      ADD      r1,sp,#40x0800037e:    a802        ..      ADD      r0,sp,#8 ;传参0x08000380:    f7ffffca    ....    BL       add_val ; 0x80003180x08000384:    9000        ..      STR      r0,[sp,#0]0x08000386:    2000        .       MOVS     r0,#00x08000388:    bd0e        ..      POP      {r1-r3,pc}0x0800038a:    0000        ..      MOVS     r0,r0i.add_valadd_val0x08000318:    b508        ..      PUSH     {r3,lr}0x0800031a:    4602        .F      MOV      r2,r00x0800031c:    6810        .h      LDR      r0,[r2,#0]0x0800031e:    9000        ..      STR      r0,[sp,#0]0x08000320:    6808        .h      LDR      r0,[r1,#0]0x08000322:    9b00        ..      LDR      r3,[sp,#0]0x08000324:    4418        .D      ADD      r0,r0,r30x08000326:    9000        ..      STR      r0,[sp,#0]0x08000328:    9800        ..      LDR      r0,[sp,#0]0x0800032a:    bd08        ..      POP      {r3,pc}

可见几个函数参数 r0 r1… 来传入,超过 r3 的一般压栈,这是一个约定俗成的标准,直接传入的参数不超过4个。

参数问题,我们再尝试第二个代码:传入4个参数的 add。

程序:

int add_val(int a, int b, int c, int d)
{return a+b+c+d;
}int mymain()
{volatile int a = 1;volatile int b = 2;volatile int c = 3;volatile int d = 4;volatile int sum;sum = add_val(a,b,c,d);return 0;
}
i.mymainmymain0x0800036a:    b500        ..      PUSH     {lr}0x0800036c:    b085        ..      SUB      sp,sp,#0x140x0800036e:    2001        .       MOVS     r0,#10x08000370:    9004        ..      STR      r0,[sp,#0x10]0x08000372:    2002        .       MOVS     r0,#20x08000374:    9003        ..      STR      r0,[sp,#0xc]0x08000376:    2003        .       MOVS     r0,#30x08000378:    9002        ..      STR      r0,[sp,#8]0x0800037a:    2004        .       MOVS     r0,#40x0800037c:    9001        ..      STR      r0,[sp,#4]0x0800037e:    e9dd3201    ...2    LDRD     r3,r2,[sp,#4]0x08000382:    e9dd1003    ....    LDRD     r1,r0,[sp,#0xc]0x08000386:    f7ffffc7    ....    BL       add_val ; 0x80003180x0800038a:    9000        ..      STR      r0,[sp,#0]0x0800038c:    2000        .       MOVS     r0,#00x0800038e:    b005        ..      ADD      sp,sp,#0x140x08000390:    bd00        ..      POP      {pc}0x08000392:    0000        ..      MOVS     r0,r0

存入 lr r3 r2 r1 r0 后,从低到高地址加载 r3 r2 r1 r0(大概是因为输入入栈顺序和函数参数顺序是反的),然后跳转。

i.add_valadd_val0x08000318:    b510        ..      PUSH     {r4,lr}0x0800031a:    4604        .F      MOV      r4,r00x0800031c:    1860        `.      ADDS     r0,r4,r10x0800031e:    4410        .D      ADD      r0,r0,r20x08000320:    4418        .D      ADD      r0,r0,r30x08000322:    bd10        ..      POP      {r4,pc}

这里涉及到了函数中的寄存器保护。最近在看 MIPS 的体系结构,那里面是分了不同的寄存器(t,s,a……)arm 也是有不同作用之分。

r0-r3 传参。r13 sp,r14 lr,r15 pc。

传参的三个函数随意使用,无需保护,返回的时候值不同了也没关系。r4-r11 也可以用,但是得保存和恢复。上例中 add 函数就使用了 r4.

比如,如果代码改为:

int add_val(int a, int b, int c, int d)
{// 故意使用R4register int sum asm("r4");sum = a+b+c+d;return sum;
}

汇编:

    i.add_valadd_val0x08000318:    b530        0.      PUSH     {r4,r5,lr}0x0800031a:    4604        .F      MOV      r4,r00x0800031c:    1865        e.      ADDS     r5,r4,r10x0800031e:    4415        .D      ADD      r5,r5,r20x08000320:    18e8        ..      ADDS     r0,r5,r30x08000322:    bd30        0.      POP      {r4,r5,pc}

r5 相当于中间计算结果,他和 r4 都要回复。

中断处理

保存现场-处理中断-还原现场,继续源程序执行。要保存哪些寄存器?

  • 首先参数寄存器要存,不然函数还没处理参数呢来个中断参数丢了。

  • r4-r11 要保存,不然函数还没压栈保存呢这些丢了找不回来了,没法还原了。

  • lr 要保存,一样道理,没压栈的时候 lr 被修改了就没法跳转回原位置了。

实际上,发生中断的一瞬间所有寄存器都要存!

我们调用的 c 中断处理函数只能保证 r4-r11 不被破坏,所以如果想保证所有寄存器都能被保存,调用 c 函数之前就要保存。硬件自动保存其他寄存器.

恢复的时候也是硬件自动恢复其他寄存器,c 函数保证恢复 r4-r11.

硬件要保存的寄存器有 r0-r3,r12,lr,当前中断返回位置。一个典型的误区是,lr 不就是当前中断返回位置吗? 并不是。比如 main 函数调用 A 函数,A 函数执行到一半发生了中断,这时 lr 里的值是 A 函数返回到 main 函数所需的位置地址,中断返回到 A 函数的地址需要再单独保存。

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

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

相关文章

webSocket 开发

1 认识webSocket WebSocket_ohana!的博客-CSDN博客 一,什么是websocket WebSocket是HTML5下一种新的协议(websocket协议本质上是一个基于tcp的协议)它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽…

数据可视化-canvas-svg-Echarts

数据可视化 技术栈 canvas <canvas width"300" height"300"></canvas>当没有设置宽度和高度的时候&#xff0c;canvas 会初始化宽度为 300 像素和高度为 150 像素。切记不能通过样式去设置画布的宽度与高度宽高必须通过属性设置&#xff0c;…

四、内存管理

1、为什么需要自己实现内存管理 (1)RTOS涉及的内核对象&#xff1a;task、queue、semaphores和event group等。为了让FreeRTOS更容 易使用&#xff0c;这些内核对象一般都是动态分配&#xff1a;用到时分配&#xff0c;不使用时释放。使用内存的动态管理功能&#xff0c;简化了…

ATF(TF-A)安全通告 TFV-5 (CVE-2017-15031)

安全之安全(security)博客目录导读 ATF(TF-A)安全通告汇总 目录 一、ATF(TF-A)安全通告 TFV-5 (CVE-2017-15031) 二、CVE-2017-15031 一、ATF(TF-A)安全通告 TFV-5 (CVE-2017-15031) Title 未初始化或保存/恢复PMCR_EL0可能会泄露安全世界的时间信息 CVE ID CVE-2017-1503…

亿级短视频,如何架构?

说在前面 在尼恩的&#xff08;50&#xff09;读者社群中&#xff0c;经常指导大家面试架构&#xff0c;拿高端offer。 前几天&#xff0c;指导一个年薪100W小伙伴&#xff0c;拿到字节面试邀请。 遇到一个 非常、非常高频的一个面试题&#xff0c;但是很不好回答&#xff0…

从外部访问K8s中Pod的五种方式

hostNetwork、 hostPort、 NodePort、 LoadBalancer、 Ingress 暴露Pod与Service一样&#xff0c;因为Pod就是Service的backend 1、hostNetwork&#xff1a;true 这是一种直接定义 Pod 网络的方式。 如果在 Pod 中使用 hostNetwork:true 配置&#xff0c; pod 中运行的应用程序…

SpringBoot项目集成ElasticSearch服务

本文已收录于专栏 《中间件合集》 目录 版本介绍背景介绍优势说明集成过程1.引入依赖2.添加配置文件3.初始化 示例说明代码结果 总结提升 版本介绍 Spring boot的版本是&#xff1a; 2.3.12   ElasticSearch的版本是&#xff1a;7.6.2 背景介绍 在我们的项目中经常会遇到对于…

java面试基础 -- ArrayList 和 LinkedList有什么区别, ArrayList和Vector呢?

目录 基本介绍 有什么不同?? ArrayList的扩容机制 ArrayLIst的基本使用 ArrayList和Vector 基本介绍 还记得我们的java集合框架吗, 我们来复习一下, 如图: 可以看出来 ArrayList和LinkedList 都是具体类, 他们都是接口List的实现类. 但是他们底层的逻辑是不同的, 相信…

2023-8-18 区间和

题目链接&#xff1a;区间和 #include <iostream> #include <vector> #include <algorithm>using namespace std;typedef pair<int, int> PII;const int N 300010;int n, m; int a[N], s[N]; vector<int> alls; vector<PII> add, query…

移植PeerTalk开源库IOS的USB通信监听服务到QT生成的FFmpeg工程

1.添加生成的PeerTalk库 下图选中部分为FFmpeg依赖库 将USB通信服务的m与h文件添加到工程 因为OC文件使用了弱指针,所以要启用弱指针支持 因为FFmpeg拉流动用到本地网络,所以要在plist文件中启动本地网络使用 设置PeerTalk为嵌入模式 设置Runpath Search Paths为@executable_p…

【欧拉计划】3或5的倍数

题目链接&#xff1a;3或5的倍数 解法一&#xff1a;暴力枚举 C语言代码 #include<stdio.h> int main (){int sum 0;for(int i 0;i<1000;i){if(i%30 || i%50)sum i;}printf("%d\n",sum);return 0; } //运行结果&#xff1a;233168上面这个解法的时间复杂…

Linux 虚拟机Ubuntu22.04版本通过远程连接连接不上,输入ifconfig只能看到127.0.0.1的解决办法

之前给虚拟机配置静态IP之后&#xff0c;可以直接通过主机Vscode远程连接。但是前一段时间把主机的TCP/IPV4静态IP设置了一下之后&#xff0c;再连接虚拟机就连不上了&#xff0c;于是参考解决虚拟机不能上网ifconfig只显示127.0.0.1的问题&#xff0c;又可以连接上了&#xff…

Swing程序设计(1)概述及常用组件

文章目录 前言一、什么是GUI?二、Swing概述 1.Swing包2.Swing常用组件总结 前言 该文介绍了Java中Swing组件的概述&#xff0c;以及常用组件的介绍。Swing程序是关于开发软件界面的一种轻量级Java组件。那什么是Swing组件&#xff1f;弹出对话框&#xff0c;窗体&#xff0c;设…

ClickHouse AST is too big 报错问题处理记录

ClickHouse AST is too big 报错问题处理记录 问题描述问题分析解决方案1、修改系统配置2、修改业务逻辑 问题描述 项目中统计报表的查询出现 AST is too big 问题&#xff0c;报错信息如下&#xff1a; 问题分析 报错信息显示 AST is too big。 AST 表示查询语法树中的最大…

pycharm调整最大堆发挥最大

python程序运行时&#xff0c;怎么提高效率&#xff0c;设置pycharm最大堆过程如下&#xff1b; 一、进入设置pycharm最大堆&#xff1b; 二、进入设置pycharm最大堆&#xff1b; 如果8g设置为6g左右&#xff0c;占75%左右最佳

自动驾驶港口车辆故障及事故处理机制

1、传感器故障&#xff1a; &#xff08;1&#xff09;单一传感器数据异常处理。自动驾驶电动平板传感方案为冗余设置&#xff0c;有其他传感器能够覆盖故障传感器观测区域&#xff0c;感知/定位模块将数据异常情况发给到规划决策模块&#xff0c;由“大脑”向中控平台上报故障…

mac m1上系统内录内部声音的方法/无需安装Blackhole

总所周知&#xff0c;m1的mac不能录制桌面音频&#xff0c;obsstudio都不行。 最快的解决方法就是下载飞书&#xff1a; 登陆后新建直播/视频会议&#xff1a; 共享的时候选择下面的两个钩上去就好了

野火i.mx 6ull上手

目录 屏幕驱动打印信息 实现触摸屏校验 开发板连接WIFI 连接操作 申请路由器动态IP和ping网络通断 WiFi信息保存位置 常用wifi操作&#xff08;wpa_cli工具&#xff09; NFS网络文件系统共享 虚拟机安装NFS服务器 开发板安装NFS客户端 控制开发板 找出硬件设备所对…

n5173b是德科技keysight N5173B信号发生器

产品概述 是德科技/安捷伦N5173B EXG模拟信号发生器 当您需要平衡预算和性能时&#xff0c;是德科技N5173B EXG微波模拟信号发生器是经济高效的选择。它提供解决宽带滤波器、放大器、接收机等参数测试的基本信号。执行基本LO上变频或CW阻塞&#xff0c;低成本覆盖13、20、31.…

Python土力学与基础工程计算.PDF-螺旋板载荷试验

python 求解代码如下&#xff1a; 1. import numpy as np 2. 3. # 已知参数 4. p_a 100 # 标准压力&#xff0c; kPa 5. p np.array([25, 50, 100, 200) # 荷载&#xff0c; kPa 6. s np.array([2.88, 5.28, 9.50, 15.00) / 10 # 沉降量&#xff0c; cm 7. D 10 # 螺旋板直…