您的位置:首页 > 其它

[TIRTOS--Introduction]TI RTOS Kernel

2016-04-14 16:01 113 查看

简述

Kernel是一个RTOS最核心的部分,因此大致了解下,对于基于该RTOS的Application的开发会很有帮助。

TI-RTOS线程

启动流程(Start up)

和常见MCU一样,在进入用户main函数前部分的Start up以及进入用户main函数后部分的Start up。

在进入用户main函数前部分的Start up的流程是由XDCTool来做的,如下:



从上图可以看到,在CPU reset后,进行一些必要的CPU initialize,然后初始化C运行时call stack(SP指针),然后运行用户提供的reset函数,然后进行更多的初始化提供C运行时环境,再接着运行用户提供的 “first functions”,再初始化所有模块,再运行用户提供的”last functions”,然后就是跳转到main()入口了。

当System_exit()或exit()被调用时,Application就被终止,这种情况是属于正常终止,成为Exit。而当System_abort()或abort()被调用时,是因为某些不预期的异常发生,导致Application被终止。

而进入用户main函数后部分的Start up,是在main()中显式调用BIOS_start()来触发的,在BIOS_start()被调用时,会运行用户提供的BIOS.startupFxns函数,允许硬件中断,允许软件中断,开始task调度。

线程

Hardware interrupts (Hwi)线程,其中包括了Timer;

Software interrupts (Swi)线程,其中包括了Clock功能;

Tasks (Task);

Background thread (Idle)。

如何选择合适的线程

SWI/Task VS HWI

以TI的说法,HWI响应时间在5ms内,SWI/Task则是在100ms的级别。当然是使用中断还是task,还有其他应用上的考虑。

SWI VS Task

SWI因为是属于中断类别,其适合处理相对简单和数据空间占用少的服务,而且相较于Task而言其效率会更高,因为可以避免Task切换时带来的开销。而Task则适合于应用角度的,有许多数据要提供和处理的服务。

Clock

即应用中使用时会调用Util_contructClock之类的接口,来创建一个Clock,使某个function可以以某一频率被执行。Clock也是一个线程,在SWI中执行,Clock的时间控制,应当还是以HW Timer为基准的,以tick为单位,HW Timer触发HWI,然后HWI触发SWI,从而达到Clock的定时作用。Clock应该可以称为SW Timer。

Clock VS SWI

TI的所有Clock线程都是出于SWI同一优先级的线程,因此不能互相抢占。对于这种应用,要注意不在同一优先级的线程里做大量的操作,而是通过post一个信号量或其他类别的消息给低优先级别的线程去做大量的操作流程,这样可以避免同一优先级别的其余线程因为本线程长期操作中而长时间等待。

Timer

而Timer就是指HW Timer了,即CPU上的Timer资源,通过设定其溢出时间,来达到定时中断的目的,而定时时间到,就是在HW ISR来处理了,这里面也是尽量做少量操作,多的操作通过post消息到SWI或者Task低优先级别的去做。

线程优先级



线程挂起与抢占

HWI和SWI都能与Task交互的,即通过发送一些消息给Task,来达到唤醒Task的目的。HWI和SWI都是使用的中断堆栈,即常成为System Stack,而Task则是每个task都有自己的私有Stack的,在创建task的时候就会分配Stack size空间的。

如下是线程之间的抢占关系,总之高优先级别的可以抢占低优先级别的:



下图是表示线程之间抢占的一个场景示意图:



Hooks

Hwi, Swi, 和Task线程提供了可以供用户插入code的指针,这个指针成为Hook(钩子),一般被用来在线程生命周期内测量、监视、分析收集信息。



从上图看到,Hooks可以有多种作用,用来在线程的某个阶段发生时来回调这个Hook函数,使Application能在此时处理某些操作。这里的处理和Android的activity的生命周期很相似。

Task

Task module提供了操作task对象的一系列函数,通过Task_Handle来访问这个task对象的内容。Kernel其实会为每个task对象维护一份处理器寄存器的拷贝,每个task有自己的运行时栈(私有栈),这个栈上用于存放一些局部变量,还有一些嵌套的函数调用(和一般的C运行时栈一样)。每个task的stack size除了存放局部变量和函数调用外,还要包括两个HWI中断上下文(中断嵌套为两层,所以是两个,不过HWI的需要放在task stack中?有点疑问)。

Task的状态机如下:



关于前面task的stack size除了存放局部变量和函数调用外,还要包括两个HWI中断上下文,TI的说法是因为task会被HWI抢占。对于Stack size是否足够的问题,TI提供了一个Task_stat()函数,用来获取当前task所实际使用的最大的stack size,通过统计可以知道具体的值,在task设计时会很有用。

线程同步

就是常见的信号量,邮箱,队列,消息等。

Timing服务

ti.sysbios.knl.Clock module

TI-RTOS的Clock有如下的方式:



ti.sysbios.hal.Timer module

属于如何使用timer外设, 属于硬件抽象层。

ti.sysbios.hal.Seconds module

提供接口用来设置/获取自1970年来的秒数。

xdc.runtime.Timestamp module

时间戳。

提供的模块

TI-RTOS以模块为单位,提供的API,供上层应用可以直接获取或设置底层信息等。

BIOS Module (ti.sysbios.BIOS);

System (xdc.runtime.System);

SysMin (xdc.runtime.SysMin);

SysCallback (xdc.runtime.SysCallback);

Program (xdc.cfg.Program);

Startup (xdc.runtime.Startup);

Reset (xdc.runtime.Reset);

Error (xdc.runtime.Error);

Text (xdc.runtime.Text);

Memory (xdc.runtime.Memory)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: