新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > RTOS的基本概念与线程基础知识

RTOS的基本概念与线程基础知识

作者:时间:2022-10-17来源:CSDN收藏

1 概念及线程的引入

本文引用地址:http://www.eepw.com.cn/article/202210/439154.htm

1.1 的概念

用人来类比单片机程序和

妈妈要一边给小孩喂饭,一边加班跟同事交流,怎么办?

对于单线条的人,不能分心,不能同时做事,她只能这样做:

  1. 给小孩喂一口饭

  2. 瞄一眼电脑,有信息就去回复

  3. 再回来给小孩喂一口饭

  4. 如果小孩吃这口饭太慢,他回复同事的信息也就慢了,被同事催,你半天都不回复我?

  5. 如果回复同事的信息要写一大堆,小孩就饿的大哭起来

对于眼明手快的人,她可以一心多用,她这样做:

  1. 左手拿勺子,给小孩喂饭

  2. 右手敲键盘,恢复同事

  3. 两不耽误,小孩“以为”妈妈在专心喂饭,同事以为“她在专心聊天”

  4. 但是脑子只有一个啊,虽然说一心多用,但是谁能够同时考虑两件事?

  5. 只是她反应快,上一秒钟在考虑夹哪个菜给小孩,下一秒钟考虑给同事回复什么信息

这种做法,在软件开发上,就是使用操作, 在单片机里叫做使用RTOS

RTOS的意思是:Real Time Operating System,即实时操作,但使用Windows,我们经常碰到程序卡死、停顿的现象,日常生活中,这是可以忍受的,但是在电梯中,你按住开门键时如果没有即刻反应,即使知识慢个一秒钟,也会夹住人,在专用的电子设备中,实时性很重要

1.2 程序简单示例:

//经典单片机程序

void main()

{

 

    while(1)

    {

 

        喂一口饭();

        回一条消息();

 

    }

 

 

}

 

//RTOS程序

int a;

喂饭() 栈A

{

    int b=2;

    int c;

    c = a+b;==>1.b+2,2,c=new val

    --------------------------->切换

    while(1)

    {

        喂一口饭();

    

 

    }

 

 

}

 

回信息() 栈B

{

    int b;

    while(1)

    {

        回一个消息();

 

 

 

    }

 

}

 

void main()

{

    create_task(喂饭);

    create_task(回信息);

    start_scheduler();

    while(1)

    {

        sleep();

 

    }

 

}


 1.2 提出问题

什么叫线程?回答这个问题之前,先想想怎么切换线程?怎么保存线程?

  • 线程是函数吗?函数需要保存吗?函数在Flash上,不会被破坏,无需保存

  • 函数里用到的全局变量,全局变量需要保存吗?全局变量在内存上,还能保存到哪里去?全局变量无需保存

  • 函数里用到了局部变量,局部变量需要保存吗?局部变量在栈里面,也是在内存里,只要避免栈被破坏即可,局部变量无需保存

  • 运算的中间值需要保存吗?中间值保存在哪里?在CPU寄存器里,另一个线程也要用到CPU寄存器,所以CPU寄存器需要保存

  • 保存在哪里?保存在线程的栈里面

  • 怎么理解CPU寄存器,怎么理解栈?

2.1 ARM架构及汇编

ARM芯片属于精简指令集计算机(RISC:Reduced Instruction Set Computor),它所用的指令比较简单,有如下特点:

1、对内存只有读、写指令

2、 对于数据的运算是在CPU内部实现

3、 使用RISC指令的CPU复杂度小一点,易于设计

对于比如a= a+b这样的算式,需要经过下面四个步骤才可以实现:

细看这几个步骤,有些疑问:

1、读a,那么a的值读出来后保存在CPU哪里?

2、读b,那么b的值都出来之后保存在哪里?

3、a+b的结果又保存在哪里?

这些问题都涉及到ARM处理器的内部,简单概括如下,我们先忽略各种CPU模式,用户模式等。 

CPU运行时,先去取指令,再执行指令

1)把内存a的值读入CPU寄存器R0

2)把内存b的值读入CPU寄存器R1

3)把R0和R1累计存入R0

4)把R0的值写入内存a

CPU内部寄存器分类

CPU内至少应该有数据缓冲寄存器,栈指针类寄存器、程序指针类寄存器、程序状态类寄存器及其他功能寄存器

1、数据缓冲寄存器

    CPU内数量最多的寄存器是数据缓冲寄存器,名字用寄存器英文Register的首字母加数字组成,如R0、R1、R2等,不同的CPU其种类不同。

2、栈指针类寄存器

    在计算机编程中有全局变量和局部变量的概念。从存储器的角度来看,对一个具有独立功能的完整程序来说,全局变量具有固定的地址,每次读写都是那个地址。而在一个子程序中开辟的局部变量则不同,用RAM中的哪个地址是不确定的,采用“后进先出”的原则使用一段RAM区域,这段区域被称为栈区。它有一个栈底的地址, 是一开始就确定的,当有数据进栈或者出栈时,地址就会连续变动,不然就放到同一个存储地址中了,CPU需要有个地方保存这个不断变化的地址,这就是栈指针(SP)寄存器。

3、程序指针类寄存器

    计算机的程序存储在存储器中,CPU中有个寄存器指示将要执行的指令在存储器中的位置,这就是程序指针类寄存器。在许多CPU中,它的名字叫做程序计数器寄存器(PC),它负责告诉CPU将要执行的指令在存储器的什么地方。

4、程序运行状态类寄存器

    CPU在进行计算过程中,会出现诸如进位、借位结果为0、溢出等情况,CPU内需要有个地方把他们保存下来,以便下一条指令结合这些情况进行处理,这类寄存器就是程序状态类寄存器,不同的CPU其名称不同,有的叫做标志寄存器,有的叫做程序状态字寄存器。

5、其他功能寄存器

    不同的CPU中,除了具有数据缓冲,栈指针、程序指针、程序运行状态寄存器之外、还有表示浮点数运算、中断屏蔽等寄存器。

ARM Cortex-M中的寄存器

ARM Cortex-M处理器的寄存器主要有R0-R15及3个特殊功能寄存器,如上图所示,其中R0-R12为通用寄存器,R13为堆栈指针寄存器(SP)、R14是连接寄存器,R15为程序计数器(PC),特殊功能寄存器有预定义的功能,而且必须通过专用的指令来访问。

几条汇编指令

需要掌握的汇编指令并不多,只有几条。

  1. 读内存指令:LDR,即Load之意

  2. 写内存指令:STR,即Store之意

  3. 加减指令:ADD与SUB

  4. 跳转:BL,即Branch And Link 

  5. 出栈指令:POP

  6. 入栈指令:PUSH

汇编并不复杂:

加载/存储指令

加载指令LDR:LDR r0,[addrA]意思就是将地址addrA的内容加载到R0中

存储指令STR:  STR r0,[addrA]意思就是将r0的值存储到地址addrA上

加法运算指令ADD:ADD r0,r1,r2意思为:r0=r1+r2

减法运算指令SUB:SUB r0,r1,r2意思为:r0=r1-r2

寄存器入栈/出栈指令

函数运行的本质

如下是一个简单的程序,主函数里调用函数add_val():

void add_val(int *pa,int *pb)

{

    volatile int tmp;

    

    tmp = *pa;

    tmp = tmp + *pb;

    *pa = tmp;

 

}

 

int main(void)

{

 

    int a =1 ;    

    int b = 2;

    add_val(&a,&b);

 

    return 0;

}

 其中调用add_val函数的汇编代码如下:

————————————————

版权声明:本文为CSDN博主「~Old」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_43460068/article/details/126896489



关键词: 嵌入式 RTOS 系统

评论


相关推荐

技术专区

关闭