SYS/BIOS 是一个可扩展的实时的操作系统。具有非常快速的响应时间(在中断和任务切换时达到较短的延迟),响应时间的确定性,强壮的抢占系统,优化的内存分配和堆栈管理(尽量少的消耗和碎片)。能够实现系统的模块化并可裁剪。
最大的特点就是:实时。
XDCtools 是SYS/BIOS引用的一种实时的软件组件技术(RTSC),它包括一些有用的工具,标准的API函数,静态配置文件和打包(packaging)操作。XDC最主要的亮点在于它标准化了传递过程,并简化了在应用程序中引用目标平台下其他包的过程。
在工程创建的时候需要先创建一个基于RTST的平台,用来分配和管理内存和缓存,它可以自动的生成对应的cmd文件。创建的过程如下:(基于TI DM6437平台)
线程是一组在存储在存储器中的代码,一旦寄存器被正确初始化,CPU就会执行这些代码。线程可以是任何类型的,SYS/BIOS定义了四种线程类型:
硬件中断(HWI),软件中断(SWI),任务(TASK),空闲(Idle)。
硬件中断:时间要求最为严格,要就实时响应的任务:一般为外设和内部的实时时间和定时器模块(定时器模块是通过硬件中断实现的,使用硬件的定时器)。
软件中断:对时间要求较为低的一种中断线程。(时钟模块是基于软件中断模块的定时器模块)
任务:CPU执行的主要线程,和软件中断的区别,可以被阻塞(可以等待)
空闲:优先级最低
各线程有隐式和显示的优先级:隐式优先级是由线程的类型决定的,显示优先级由软件的编程者决定,并且允许抢占的:就是高优先级的线程能够抢线程占低优先级的线程,优先执行,这种高于优先级的调度管理机制保证了最高优先级的线程能在第一时间被执行。下面是线程的抢占的示意图:
另外一种方式,是通过手动编辑.cfg文件,该文件采用Javascript语言编写,同样也可以配置组件。
SYS/BIOS在线程创建和配置方面,提供两种方式,一种是静态的创建,通过XDCtools创建和配置。一种是动态的创建,就是在程序中创建,下面就以HWI为例程,分别列出;两种创建方式:
静态创建:可以通过图形化的界面进行配置,也可以通过JavaScript脚本语言手动编写.cfg文件进行配置,下面写出手动编写.cfg文件配置Hwi:
var hwi0Params =new Hwi.Params();
hwi0Params.instance.name= "Uart_Handle";
hwi0Params.eventId= 85;
Program.global.Uart_Handle= Hwi.create(8, "&Int_Uart1ISR", hwi0Params);
动态配置:在程序中进行配置
需要引用的头文件
#include
Hwi_HandleUart_Handle;
Hwi_Paramshwi0Params;
Error_Block eb;
Error_init(&eb);
Hwi_Params_init(&hwi0Params);
hwi0Params.eventId = 85;
Uart_Handle =Hwi_craete(8, "&Int_Uart1ISR", & hwi0Params, &eb) ;
SYS/BIOS任务线程有0-31个优先级(默认0-15,优先级0被空闲线程使用,任务最低优先级为1),但是在内存允许的情况下可以不限制的创建任务数量。SYS/BIOS有独立的内存堆栈,可以为等待某一事件的发生而被挂起,任务会被其他更高优先级的线程打断。数量和状态可以在程序执行时动态的更改,优先级也可以动态的修改。
空闲线程是一种非实时性的线程,并且仅当没有任何其它线程(HWI/SWI/TASK运行时才会运行),所有空闲线程运行在同一个线程,而且可以被其它线程随时抢占,默认使用任务堆栈,如果任务线程被禁用使用系统堆栈,一个接一个运行,每一个空闲线程函数都会从开始执行到结束。所有函数执行完后再从第一个函数执行,周而复始。
信号量通常用于协调一些处于竞争关系的任务之间对共享资源的访问。可以使任务处于挂起状态,用来等待某一个特定的事件,只有当这个事件发布的时候才能继续执行任务,这是通过信号量来实现的,而信号量操作主要有两种操作:一个是post,一个是pend,而这两种操作就是用来改变信号量的计数值,而在SYS/BIOS中的信号量有两种计数的模式,一种是以2进制的模式计数,一种是计数的模式进行计数。信号量的值为0的时候任务处于挂起状态,信号量为1的时候任务恢复继续执行。下面是两种计数模式的区别:
操作(假定计数初值为0) |
二进制 |
计数 |
Semaphore_post()sem); |
1 |
1 |
Semaphore_pend()sem); |
0 |
0 |
Semaphore_post()sem); |
1 |
1 |
Semaphore_post()sem); |
1 |
2 |
计数 |
任务状态 |
|
Semaphore_pend()sem); |
0 |
挂起 |
Semaphore_post()sem); |
>1 |
恢复 |
信号量的创建:同样是两种方式,静态创建和动态创建,下面写出动态创建的例程:
Error_Block eb;
Error_init(&eb);
Semaphore_Params_init(&semParams);
semParams.mode =Semaphore_Mode_BINARY;
semParams.event = evt;
semParams.eventId =Event_Id_00;
sem = Semaphore_create(1,&semParams, &eb);
if (sem == NULL)
{
System_abort("Semaphore create failed");
}
else
{
System_printf("Semaphore create is OK\n");
}
邮箱SYS/BIOS系统用来在任务间进行buffer传输的,在邮箱创建的时候配置传输buffer的大小,Mailbox_post()函数执行完成代表,邮箱buffer已经传输到缓冲区,当执行Mailbox_pend()时,就从缓冲区中获得数据。
邮箱的创建:Mailbox_HandleMailbox_create(SizeT bufsize,
UInt numBufs,
Mailbox_Params *params,
Error_Block *eb)
Void Mailbox_delete(Mailbox_Handle*handle);
Mailbox_pend()是用来从邮箱中读取Bufferde,如果邮箱中没有Buffer就等待timeout 的时间;
Bool Mailbox_pend(Mailbox_Handle handle,
Ptr buf,
UInt timeout);
Mailbox_post()是用来存入Buffer到邮箱,如果邮箱已满,则等待timeout时间;
Bool Mailbox_post(Mailbox_Handle handle,
Ptr buf,
UInt timeout);
事件同样提供了一种线程间通信和同步的方法,它和信号量有相同的地方,不同的地方是,事件允许你指定多个任务等待的条件。
像信号量一样,事件的挂起和发布也是通过Event_pend(),Event_post()来实现的,如果是一个事件的挂起和发布,那么它和信号量是一样的,一个事件模块的创建,可以管理32个事件,通过事件ID来管理,而每一个事件都相当与一个信号量。
Event_pend()函数的参数有一个"andMask"和一个"orMask"。andMask对应的是需要所有的事件都发布才能解除任务的挂起状态,orMask是任何一个事件的发布都可以解除任务的挂起状态。
同样Event_pend()也有一个等待时间的参数,功能和信号量是一样的。
下面是一个创建事件的例程:
Event_HandlemyEvent;
Error_Block eb;
Error_init(&eb);
/* Defaultinstance configuration params */
myEvent =Event_create(NULL, &eb);
if (myEvent ==NULL) {
System_abort("Eventcreate failed");
}
事件的挂起:
UIntEvent_pend(Event_Handle event,
UInt andMask,
UInt orMask,
UInt timeout);
事件的发布:
VoidEvent_post(Event_Handle event,
UInt eventIds);
1:信号量和邮箱可以编入事件
可以将信号量和邮箱编入一个事件,在信号量和邮箱创建的时候,写入事件的ID,当信号量或者邮箱发布的时候,就等于对应事件ID的事件的发布。
2:任务堆栈的配置:
每个任务可以配置独立的堆栈的大小,在任务创建的时候配置。堆栈太小,会导致任务创建失败。
3:I-RTOSKernel RTSC 和 XDCtools的关系
TI-RTOS Kernel就是指TI公司开发的SYS/BIOS实时操作系统。
RTSC是实时的软件组件平台,基于这个RTSC来创建SYS/BIOS
XDCtools是依赖于RTSC的平台配置的工具
TI-RTOS Kernel是系统,RTSC是平台,XDCtools是工具。
4:cmd更改问题:
.cmd文件只能通过RTSC平台的配置自动生成,不能自己手动的更改,自己通过编辑修改的.cmd在编译又会从新变回去。
5:SYS/BIOS下自定义段的方法:
手动编辑.cfg文件:Program.sectMap["L3_DATA"]= "DDR";