CC2640开发记录2 《TI-RTOS Training》 记录-翻译-笔记

笔者需要深刻认识TI-RTOS的运行机制,使得自己开发的产品可以运行多个线程,发现了TI有一个很好的介绍文档,于是有了此篇博客。

文档地址 http://processors.wiki.ti.com/index.php/SYS/BIOS_Training:_Introduction_to_SYS/BIOS

笔者的编译运行环境 : IAR

笔者的硬件运行环境: CC2640

正文

What is an RTOS?

一个标准的操作系统包括一下组件:

1 低等级的服务(startup,IO控制等等)

2 各种任务

3 内存管理能力

4 硬件层抽象

5 文件系统

6 通讯协议栈(网络 USB 蓝牙等)

实时操作系统可以做到如下

1 快速响应

2 健壮抢占

3 优化动态内存

4 文件系统

Why Use an RTOS?

1 复杂任务运行处理

2 各个主流主控器兼容

3 避免重新造轮子

4 DEBUG工具

什么是线程?

thread of execution(可执行的线程)是一系列在内存中的指令,一旦相关寄存器被合理初始化,那么就可以被CPU执行。

》定义和包含一切线程执行相关的组件

1 包含 程序计数器 堆栈 寄存器值

2 上下文

3 RTOS scheduler决定何时运行此线程

》可以是四种不同的线程类型

1 硬件中断线程 HWI

2 软件中断线程 SWI

3 普通TASK

4 idle TASK

》包含显式/隐式 优先级特性

1 隐式优先级由线程类型决定

2 显式优先级由编程决定

》允许抢占

高优先级TASK抢占低优先级TASK

线程抢占的例子

由图可以看出 HWI的优先级最高,且会POST一些信号量,这些信号量在低优先级的TASK中被反复的判断PEND 如果发现曾经被POST过,那么TASK将会运行。

What is SYS/BIOS?

v 6.30 SYS/BIOS是开源软件有 BSD open-source license

///////////////

介绍两个线程 HWIs 和 IDLE THREAD

一般的不运行TI-RTOS的单片机,运行结构是左图,包含 init 初始化函数 和一个死循环,以及多个ISR中断服务函数。

运行BOIS的单片机运行结构是右图,主函数仅运行init和BIOS_start()函数。idle loop扮演原先的死循环角色,HWI扮演原先的ISR中断服务角色。

IDLE LOOP总是最低优先级,一般的在IDLE LOOP中运行电源管理低功耗代码

高优先级抢占低优先级任务,抢占完成之后会恢复到原先的TASK中继续运行

任何HWI会打断IDLE processing

上图指明HWI中断后要做的事情

1 关闭任务调度器,防止此时又调度其他的任务

2 跳转到ISR的堆栈

3 保存中断前的一些重要信息

4 关闭SWI调度器

5 调用HWI BEGIN HOOKS(钩子)

...继续运行调度器

举了一些好处,感觉不重要,也不好理解!

笔者理解,IDLE TASK类似裸奔的while(1)内容,而HWI就是裸机的中断服务函数。

///////////////////

Software Interrupts (Swi)

软件中断相关

1  Used todefer hardware interrupt servicing to less restrictive thread
软件中断是为了将硬件中断的服务函数放到限制较少的线程中来。

有0-15的优先级选择

上下文保存/自动修复处理

单独的堆栈模型

这里区分了前台(foreground)后台(background) hwi趋向前台,响应及时SWI趋向于后台,多数是由HWI 通过POST信号量来触发执行,SWI的代码何时运行比较随意,不像HWI必须保证快速响应,这里想到按键相关的程序,按下按键的外部中断必须快速捕获,至于处理按键操作的程序可以晚一点,对应HWI与SWI。

提到 HWI 与 SWI有很多相似的地方

1 都是使用内核封装函数来访问

2 一旦执行就必须执行到底,不可以中途被打断

3 只会执行一次,无论多少信号量被POST ,多次POST将会压入queue一次次执行。这里应该也是强调,HWI与SWI必须执行完,不能被打断,也不会出现还没运行完,又post一次重新运行的现象。

上图显示了生命周期,创建了SWI/HWI后,都处于inactive状态,等待POST出现,POST出现之后,TASK处于READY状态,但没有被执行,由调度器来给予运行条件,进入running状态,此时如果由更高优先级的TASK出现,那么此TASK将会暂停,进入ready状态,再有调度器resume,运行完成后,回到inactive状态。

·

HWI 收集数据到 frame/buffer中,展现一个最小的处理方式

SWI 处理在buffer中的数据

idle 当没有任务运行时运行。

上图可以看出,最开始没有任务运行时系统运行IDLE任务,HWI发生,快速处理HWI任务,比如快速写一个BIT标志位,然后结束,第一次没有POST SWI于是系统继续运行IDLE,第二次再次发生HWI,此时POST了SWI,于是HWI返回后开启一个SWI任务,SWI运行期间被HWI打断,SWI任务处理HWI记录在BUFFER里面的数据(process buffer)处理完了之后回到IDLE TASK。

相同优先级的SWI由FIFO的原则决定处理顺序,例如上图,SWI_A已经在运行了,但是被HWI打断,并且POST 任务B,任务B虽然在HWI中被“宠幸”了 但是HWI结束了以后,还是得乖乖等在SWI_A之后!

ISR直接POST了高级的SWI,这样是not good的情况,并且会导致PROBLEM !既然TI大神都说这样 not good 我们也不要这样尝试了!

TI大神给出了HWI快速抢占当前SWI的方式,也就是上上张图,HWI POST非正在运行的SWI_B,必须要等当前的SWI_A运行完后才能运行SWI_B,如果非要抢占SWI_A,那么必须先关闭调度器,然后POST,然后再打开调度器。

这种用法,给我用我也不会用,太危险了,知道就好!

笔者理解

SWI与HWI,HWI好像是外部中断服务函数,仅仅做了一件很短的事情,有可能就是置位了一个标志位。而SWI不一样,SWI处理HWI所作的修改,然后执行一大批处理函数。SWI对实时性不敏感,可以慢慢做,HWI很敏感,要快速记录。好比警察抓人,HWI当务之急是记下坏人的长相,SWI就是执行抓捕行动。HWI快,SWI慢慢来!HWI会触发SWI,因为如果没有HWI的工作前提,就没有SWI的工作意义,好比警察连犯罪分子的长相都不知道,无从抓起,所以要等待拍照同时给过来的信息,才能进行下一步的操作!

猜你喜欢

转载自blog.csdn.net/Clarence_happy/article/details/89478588