FreeRTOS深入教程(任务的引入及栈的作用)

文章目录


前言

本篇文章开始带大家深入学习FreeRTOS,带大家学习什么是任务,并且深入学习栈的作用。

一、任务的引入

在 FreeRTOS 中,任务(Task)是一个基本的执行单元,它代表了一个并行执行的工作单元。FreeRTOS 是一个实时操作系统,允许你创建多个任务,每个任务都有自己的代码、堆栈和优先级。这些任务可以独立运行,以实现多任务并发。

以下是关于 FreeRTOS 任务的一些关键概念:

任务的特点:

每个任务都有自己的独立堆栈,用于保存任务的局部变量和上下文信息。

任务可以具有不同的优先级,操作系统根据任务的优先级来调度它们的执行。

任务可以是无限循环的,也可以在完成其工作后自行删除。

每个任务都有一个唯一的任务句柄,可以用于管理和控制任务。

二、深入理解C语言函数的调用

1.ARM架构

在我们看来执行a+b是一件非常简单的事情,但是在CPU的内部却做了非常多的操作。

CPU运行时,先去Flash上取得指令,再执行指令:

  • 把内存a的值读入CPU寄存器R0
  • 把内存b的值读入CPU寄存器R1
  • 把R0、R1累加,存入R0
  • 把R0的值写入内存a

2.基础汇编指令

LDR(Load Register):

LDR 指令用于将数据从内存加载到寄存器中。

典型的 LDR 指令的语法:LDR Rd, Rn, #Offset,其中 Rd 是目标寄存器,Rn 是基址寄存器,Offset 是偏移量。

举例:LDR R0, R1, #4 表示将存储在地址 (R1 + 4) 处的数据加载到 R0 寄存器中。

STR(Store Register):

STR 指令用于将寄存器中的数据存储到内存中。

典型的 STR 指令的语法:STR Rd, Rn, #Offset,其中 Rd 是源寄存器,Rn 是基址寄存器,Offset 是偏移量。

举例:STR R0, R1, #4 表示将 R0 寄存器中的数据存储到地址 (R1 + 4) 处。

ADD(Add):

ADD 指令用于将两个操作数相加,并将结果存储在目标寄存器中。

典型的 ADD 指令的语法:ADD Rd, Rn, Operand2,其中 Rd 是目标寄存器,Rn 是第一个操作数寄存器,Operand2 是第二个操作数。

举例:ADD R0, R1, #10 表示将 R1 寄存器中的值与 10 相加,并将结果存储在 R0 中。

POP:

POP 指令用于从栈中弹出多个寄存器的值。

POP 指令的操作是根据栈指针(通常是 SP 寄存器)从栈中弹出值,同时更新栈指针。

通常用于函数返回时,以恢复之前保存的寄存器状态。

POP {R3, PC}

PUSH:

PUSH 指令用于将多个寄存器的值推送(压入)到栈上。

PUSH 指令的操作是根据栈指针(通常是 SP 寄存器)将值压入栈中,同时更新栈指针。

通常用于函数调用时,以保存当前寄存器状态。

PUSH {R3, LR}

3.函数运行流程分析

在keil5中编写一个加法函数:

c 复制代码
/* a = a + b */
void add_val(int *pa, int *pb)
{
	//*pa = *pa + *pb;

	volatile int tmp;

	tmp = *pa;
	tmp = tmp + *pb;
	*pa = tmp;
	
}

int a = 1;
int b = 2;

add_val(&a, &b);	

汇编代码:

汇编代码分析:

复制代码
首先执行PUSH	{r3,lr}命令
将r3寄存器的值和lr返回地址保存到了栈中。
r3就是局部变量tmp的值。

tmp = *pa;

复制代码
LDR      r2,[r0,#0x00]   读取r0的值到r2中,也就是将*pa读取到r2中。
STR      r2,[sp,#0x00]   将r2的值保存到sp+0x00地址处也就是将*pa保存到tmp中。
			完成tmp = *pa;赋值语句

tmp = tmp + *pb;

复制代码
LDR	     r2,[r1, #0x00] 读取r1的值到r2中,也就是将*pb读取到r2中
LDR		 r3,[sp,#0x00] 读取sp+0x00的值到r3中,也就是将tmp读取到r3中
ADD	 	 r2,r2,r3 将r2+r3的和保存到r2中,也就是将*pb + tmp的值保存到r2中
STR		 r2,[sp,#0x00] 将r2的值保存到sp中也就是tmp = *pb + tmp

*pa = tmp;

复制代码
LDR    r2,[sp,#0x00] 读取sp+0x00的值保存到r2中,也就是将tmp保存到r2中
STR	   r2,[r0,#0x00] 将r2的值保存到r0中,也就是*pa = tmp

POP {r3,lr}

出栈将lr的值返回给pc寄存器,执行下一条指令。

三.保存现场的几种情况

1.函数调用

当函数调用时R0,R1,R2通常被用来传递参数故不需要保存这几个寄存器的值。

c 复制代码
void funA(void)
{
	.........
	funB(a, b);
}

2.中断处理

被中断打断时硬件会帮我们保存R0,R1,R2寄存器,其他寄存器需要通过软件来保存。

c 复制代码
void funA(void)
{
	->被中断打断
}

3.任务切换

当任务切换时需要保存所有的寄存器,因为任务并不知道会使用到哪些寄存器。

总结

本篇文章主要引入了任务及说明了栈在这里的作用。

相关推荐
纵有疾風起2 小时前
磁盘与固态硬盘:SSD原理、磨损均衡与寿命计算全解析
操作系统·ssd·408·固态硬盘·闪存·磨损均衡
别催小唐敲代码2 小时前
STM32 定时器学习笔记:TIM 架构、输入捕获与 PWM 一篇讲透
笔记·stm32·学习
wuyk5554 小时前
89.嵌入式内存管理的“稳定利器”:内存池原理与C语言实现
c语言·开发语言·stm32·单片机·嵌入式硬件
zcmodeltech5 小时前
智慧城市沙盘模型多系统协同控制系统设计:基于STM32与Modbus RTU的园区-城市-数字孪生联动方案
服务器·数据库·人工智能·stm32·嵌入式硬件·信息可视化·智慧城市
Run_Teenage5 小时前
嵌入式:认识STM32命名方法和引脚定义,认识仿真器
stm32·单片机·嵌入式硬件
lhbweilai6 小时前
STM32 时钟源&时钟树(hal库)
stm32·单片机·嵌入式硬件
lhbweilai18 小时前
STM32 ADC模拟数字转换(hal库)
stm32·单片机·嵌入式硬件
小僧景贤20 小时前
STM32 工程文件深度解析(Keil‑MDK + STM32CubeIDE)
stm32·单片机·stm32cubeide
纵有疾風起1 天前
页面置换算法与实战机制:从 LRU 到内存映射文件
操作系统·408·lru·mmap·clock·页面置换·belady异常
云泽8081 天前
深入浅出 STM32(六):GPIO 硬件电路深度剖析——从输入输出模式到 MOS 管开关原理
stm32·单片机·嵌入式硬件