RTOS必备基础
- 一、ARM基础知识
- 1、ARM架构
- 2、重要寄存器
- 3、汇编指令详解
- 读:load
- 写: store
- 加: ADD
- 减: SUB
- 出栈: push
- 出栈:pop
- 4、栈和堆:
-
- 5、 局部变量和全局变量的分配与初始化
- 1. 局部变量初始化
- 2. 全局变量、静态变量初始化
- 6、 函数是什么
- 二、RTOS系统注意事项
一、ARM基础知识
1、ARM架构
- 程序编译后生成 .bin、.hex文件,(汇编代码)烧入Flash中。
- 启动设备,程序在Flash中一条一条执行。
- 程序告诉CPU执行操作,如分配内存、分配栈、计算。
- CPU操作,如从内存中某个地址读写数据、开辟空间,GPIO的读写等。
![在这里插入图片描述](https://img-blog.csdnimg.cn/1a936d4360364fd6a3d10bbe3ade6eb6.png)
CPU运行时,先去取得指令,再执行指令:
① 把内存a的值读入CPU寄存器R0
② 把内存b的值读入CPU寄存器R1
③ 把R0、R1累加,存入R0(对于数据的运算是在cpu内部执行)
④ 把R0的值写入内存a
2、重要寄存器
R# | APCS别名 | 意义 |
---|
R0 | a1 | 参数/结果/scratch 寄存器1 |
R1 | a2 | 参数/结果/scratch 寄存器2 |
R2 | a3 | 参数/结果/scratch 寄存器3 |
R3 | a4 | 参数/结果/scratch 寄存器4 |
R4 | v1 | arm 状态局部变量寄存器1 |
R5 | v2 | arm 状态局部变量寄存器2 |
R6 | v3 | arm 状态局部变量寄存器3 |
R7 | v4 / wr | arm 状态局部变量寄存器4 / thumb状态工作寄存器 |
R8 | v5 | arm 状态局部变量寄存器5 |
R9 | v6 / sb | arm 状态局部变量寄存器6 / 在支持RWPI的ATPCS中作为静态基址寄存器 |
R10 | v7 / sl | arm 状态局部变量寄存器7 / 在支持数据栈检查的ATPCS中作为数据栈限制指针 |
R11 | v8 / fp | arm 状态局部变量寄存器8 / 帧指针 |
R12 | ip | 内部过程调用 scratch寄存器 |
R13 | sp | 栈指针 |
R14 | lr | 链接寄存器 |
R15 | pc | 程序计数器 |
高编号的寄存器保存在高地址,低编号的寄存器保存在低地
- R0-R12:数据寄存器
调用C函数时 第一个参数保存在R0中 第二个参数保存在R1中 - R13:SP:栈
- R14:LR
跳转到子过程的时候,r14保存了返回地址,可以在调用过程结尾恢复。
异常中断发生时,这个异常模式特定的物理R14被设置成该异常模式将要返回的地址 - R15:PC
存放指令(函数)的地址 (后续会放入R0寄存器中)
3、汇编指令详解
读:load
LDR R0, [addr A]
将addr A的值读到 R0寄存器
LDR:将 存储器地址 所指地址处连续的4个字节(1个字)的数据传送到目的寄存器中。
写: store
STR R0,[addr A]
将addr A的值写到 R0寄存器
STR:用于从源寄存器中将一个32位的字数据传送到存储器
加: ADD
ADD R0,R1,R2
R0=R1+R2
ADD:两数相加
减: SUB
SUB A,B
功能: 两个操作数的相减,即从A中减去B,其结果放在A中.
出栈: push
push {R3,LR}
作用: push寄存器:将一个寄存器中的数据入栈(写入内存)
-
写入内存的位置由SP指定
-
高编号的寄存器保存在高地址,低编号的寄存器保存在低地址
出栈:pop
pop {R3,PC}
读数据从SP指向的位置读取数据
![在这里插入图片描述](https://img-blog.csdnimg.cn/c784b11ec9bc4c9f8e4c68c43202390f.png)
- R3=[SP]:读取R3中的数据
- SP递增
- PC=[SP]:读取LR (函数返回地址)
![在这里插入图片描述](https://img-blog.csdnimg.cn/a34410b101eb4711b1e46fae72b086e2.png)
4、栈和堆:
1. 栈
发生中断时,会保存现场:值保存在栈中
栈的整体作用
(1)保存现场/上下文
(2)传递参数:汇编代码调用c函数时,需传递参数
(3)保存临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量。
需要保存哪些数值
C程序中的保存数值
1.任务切换的时候 寄存器都要保护
2.函数调用的时候只保存改变后的值
用于传参的寄存器则不需要保存如上面的R0 R1 R2
内核中的中断保存数值
cortex M3和M4
- 硬件保存一部分 R0 R1 R2 入栈
- 软件就保存用到的值
栈的大小取决于
- 局部变量的多少
- 调用深度
栈的内存从哪里分配
- freertos的栈 由一个巨大的 全局数组 分配
- 调用深度
2. 堆
一块空闲内存,可以使用malloc/free函数来管理
volatile char my_buf[20*1024];
volatile int index = 0;
void *malloc(int size)
{
char *ret = &my_buf[index];
index += size;
return ret;
}
5、 局部变量和全局变量的分配与初始化
1. 局部变量初始化
C语言:
void my_main(void)
{
int a = 456;
}
汇编:
PUSH {r3,lr}
MOV r0,#0x1C8
STR r0,[sp,#0x00]
![在这里插入图片描述](https://img-blog.csdnimg.cn/089867cc0f774f3b888df643ea7003ea.png)
2. 全局变量、静态变量初始化
在调用main函数之前,使用copy、SetZero函数对全局变量、静态变量初始化
6、 函数是什么
二、RTOS系统注意事项
- 对于实时操作系统 高优先级的任务 永远优先执行(如果没有delay 将程序进入阻塞态 那实时操作系统就一直执行高优先级)
- 空闲任务(优先级通常较低)由调度器创建 会影响同样是0的优先级任务(相同优先级 空闲任务最后创建 所以最先执行)
- 空闲任务礼让:同等优先级 先等其他任务运行一次后 再运行空闲任务
- 在大于或 等于 优先级的时 如果任务1先创建 任务2后创建 就会先执行任务2
![在这里插入图片描述](https://img-blog.csdnimg.cn/df3e7dd990d84d83ba508889384c0216.png)
- 当任务 配置成 不抢占 不轮流 不礼让的时候
创建 顺序从左到右: 任务①<<任务②<<任务③<<空闲任务A
执行顺序如下:空闲任务 A 执行释放内存后 会礼让
空闲任务A << 任务① << 任务① << 任务①
一直会执行 任务①(可设置主动放弃入 即加入delay进入阻塞态就可以运行任务②)
不抢占就不会轮流执行 中断的优先级>任务优先级
参考:散文诗
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)