📄 guide.txt
字号:
MicroStar1.0版,北京航天航空大学自动化学院,郑玉全,2003.7
Email: yuquanzheng@163.net yuquanzheng@163.com
New! 最新版本MicroStar1.1不仅能支持按优先级调度,还支持时间片轮转调度和前二者相接合调度。
声明 代码未经严格测试,现仅作学习和交流用途,不得利用其作任何商业目的的开发。擅自使用之进行商业开发,所造成的后果由自已承担,本人不负任何法律上的责任。
使用需知
1. MicroStar1.0最多只能创建16个任务。最多可提供16个定时器。最多能直接提供16个同步对象,若要更多的同步对象,须自行分配内存。
2 为了使代码能在DOS下运行,不少函数声明和定义前都有_FAR宏,以使所有函数都可以通过在os_type.h中添删FAR_MODE宏来编译成远调函数还是近调函数。随演示程序提供的是在小模式下编译的obj文件,不必关心_FAR。
3 部分函数,结构体在DOS下必须使用 far 指针,移植时只需在os_type.h中添加一条-----#define far
4 此手册并不专对PC机编写,因而有些函数的原型与PC机源码不符,请读者注意。
5 调试版本中内核调用用户编写的os_WARNINGE 和 os_ASSERT校验函数,可参考演示程序中的other.c文件。出错类型和警告类型可在os_macro.h中查的。
有关宏的说明
1.如果要使用message函数,须在#include "os_user.h"之前定义#define _MESSAGE,此时项目文件应包含os_msg.obj.
2.如果要使用定时器函数,须在#include "os_user.h"之前定义#define _TIMER,此时项目文件应包含os_timer.obj.在PC机上还需要安装系统的定时中断程序,参加演示示例。
3.如果要使用信号函数,须在#include "os_user.h"之前定义#define _SIGNAL,此时项目文件应包含os_sign.obj.
4.如果要使用同步对象函数,须在#include "os_user.h"之前定义#define _OBJECT,此时项目文件应包含os_obj.obj.
/***************main的一般框架********************/
main( )
{
os_Initial( );
installTimer( ); /*PC机上如果使用定时器*/
os_CreateTask(....);
.....;
os_CreateTask(....);
os_StartUp(..);
uninstallTimer( );/*PC机上如果使用定时器*/
}
/*************************************************/
使用消息的典型任务函数示例如下:
void MyTask( void* param )
{
MSG msg;
InitTask( );/*线程初始化*/
while( (msg = os_GetMessage( )) != TASK_QUIT )
{
switch( msg )
{
case message1:......
break;
case message2:.....
break;
...................;
...................;
default :
..........;
}
}
}
/***************************************************/
使用信号的典型任务函数示例如下:
uint_16 g_signal;
void task( )
{
while(1)
{
os_WaitORSignal(&g_signal,0x00FF,0x000F);
if( g_signal&0x000F) /*紧急级信号处理代码放在前面*/
{
if(g_signal&0x0001)
{ ..............;g_signal &= ~0x0001;}
if(g_signal&0x0002)
{ ..............;g_signal &= ~0x0002;}
if(g_signal&0x0004)
{ ..............;g_signal &= ~0x0004;}
if(g_signal&0x0008)
{ ..............;g_signal &= ~0x0008;}
continue; /*注意:此语句是必须的*/
}
else
{
if(g_signal&0x0010)
..............;
if(g_signal&0x0020);
..............;
if(g_signal&0x0040)
..............;
if(g_signal&0x0080)
..............;
}
}
}
/***************以下为函数说明*********************/
任务创建函数
void os_CreateTask(
TASKPROC task, //线程函数的指针
uchar taskId, //线程的ID号
uchar priority, //优先级
int * pStack, //线程堆栈底地址
void * param //线程函数的入口参数
);
创建一个线程
Parameters
task
线程函数的指针,即线程函数的起始地址
taskId
线程的ID号,有效值为0到USER_TASK_NUM,系统默认线程的ID号USER_TASK_NUM+1,不同线程不得使有相同的ID号。PC版本将USER_TASK_NUM固定为15。
priority
线程的优先级,由静态优先级与动态优先级组成,按下式得出:
priority = 动态优先级值*16 + 静态优先级值。
静态优先级有效值为0到14(15为系统保留给默认线程),值越小优先级越高,不同线程不能使用相同的静态优先级。动态优先级值为0和1,0级高于1级。
pStack
线程堆栈的栈底地址。
param
线程函数的入口参数
Return Value
无返回值,调试版本会进行参数合法性检查,可在os_ASSERT函数中查看出错类型。
注意
传递sp参数,要弄清处理器栈的增长方向,避免栈底与栈顶搞混。
在DOS上运行系统时,sp和param参数有所不同,都为远指针,因些可用param传递四个字节的参数。
销毁一个线程
void os_KillTask(
uchar taskId //线程的ID号
);
注意
使用该函数时可能使线程不能正确释放如定时器,同步对象等系统资源,须慎重使用。
结束当前线程
void os_Exit( );
注意
调用前应使放所取得的系统资源(定时器,同步对象)。
挂起当前线程
void os_Suspend( );
其它线程调用os_Resume可使其恢复执行。
使调用os_Suspend而挂起线程恢复执行
void os_Resume(
uchar taskId //要恢复执行的线程的ID号
);
注意
如果taskId标识的线程并未挂起,调用该函数不起任何作用。不得用此函数去让由于等待同步对象而挂起的线程恢复执行。
提升动态优先级至0级
void os_RaisePriority( );
降低动态优先级至1级
void os_LowerPriority( );
注意
调用该函数时,如果有动态优先级为0级的其它线程处于就绪态,内核会暂停当前线程执行,让高优先级线程执行。
重新设定静态优先级
BOOL os_SetStaticPriority(
uchar priority //新的静态优先级值
);
返回值
如果该静态优先级值未被使用,返回为os_true,原优先级闲置
如果已被使用,返回os_false,线程的静态优先级不变
HTIMER os_SetTimer(
uchar timerId, //定时器ID号
uint_16 elapse,//定时时长(time-out)
TIMERPROC lpTimerFunc//定时调用函数
);
参数
timerId
有效值为0至31,在一个线程内,此ID号不能复用。定时时间到时,将此ID以消息的形式发送给拥有定时器的线程。如果该值设为NULL_TIMER_ID时,将不发送消息,怱略该参数。其它值保留。
elapse
定时时长,以时钟节拍为单位。
lpTimerFunc
定时时间到时被调用的函数
返回值
若无空闲定时器可用,返回NULL_TIMER(0xFF)
若设定成功,返回非NULL_TIMER的整型值,将该值为参数来调用os_KillTimer来释放定时器
注意
将timerId设为0至15时,定时时间到时,会提高拥用器的线程的动态优先级,因些实时性较好。一般情况下,应设定为16-31。
定时调用函数应该简短,如果过长,将NULL为参数传给lpTimerFunc,在线程函数中来处理。最好不要同时使timerId和lpTimerFunc有效,否则调度延迟时间和调度负荷均会增大。
释放定时器
void os_KillTimer(
HTIMER hTimer //由os_SetTime函数返回的句柄值
);
睡眠一段时间
void os_Sleep(
uint_16 elapse //睡眠时长,以时钟节拍为单位
);
注意
调用该函数也会消耗定时器资源
发送消息
BOOL os_SendMessage(
uchar taskId,//接收该消息的线程ID
MSG msg //消息值
);
void os_PostMessage(
uchar taskId, //接收该消息的线程ID
MSG msg //消息值
);
返回值
使用os_SendMessage时,如果接收线程还有相同值的消息未处理,发送失败,返回os_false。成功则返回os_true。
使用os_PostMessage时,如果接收线程是有相同值的消息未处理,将会覆盖原消息,不返回任何信息。
注意 向不存在的线程发送消息时,会怱略。在调试版中会发出警告,可在os_WARNING中查看之。 msg值只能使用0-31,其中,0-15为紧急级消息,16-31为普通级消息。发送紧急级消息时会提高接收线程的动态优先级,因而处理的实时性优于普通级消息。对实时性没太大要求时,不要使用紧急级消息。
接收消息
MSG os_GetMessage( );
返回消息缓冲区中优先级最高的消息,范围为0-31,值越小消息的优先级越高。
MSG os_PeekMessage( );
返回消息缓冲区中优先级最高的消息,范围为0-31,值越小消息的优先级越高。若无消息,则返回0xFF。
注意
如果消息缓冲区中没有消息,os_PeekMessage会直接返回,os_GetMessage则会阻塞直到有消息发送过来。
如果消息缓冲区中只有普通级消息,os_GetMessage会降低线程的动态优先级,os_PeekMessage则不会改变线程的动态优先级。
等待多个或方式组合的信号
void os_WaitORSignal(
volatile uint_16 *pSignal,//二进制信号组指针
uint_16 acceptMask, //信号掩码
uint_16 urgentMask //信号紧急级掩码
);
参数
pSignal
二进制信号组指针。指针所指向的16位二进制数每一位为一个信号(signal),即标志位,为1表示激活,为0表示未激活。由用户来设定各标志位。
acceptMask
有效信号掩码。如果掩码的某一位为1,则信号组中对应的信号有效;为0,则对应位怱略。
urgentMask
信号紧急级掩码。如果掩码的某一位为1,则信号组中对应的信号为紧急级,否则为普通级。
注意
调用该函数时,如果没有有效信号为激活态,线程会暂停执行,直到该有效信号激活且用os_Notify函数通知了该线程。所谓信号的紧急级或普通级是相对线程而言的,即某个信号转为激活态,要求线程对此的响应的紧迫程度。紧急级时,内核会提高线程的动态优先级,因而响应的实时性好。
void os_WaitANDSignal(
volatile uint_16 *pSignal,//二进制信号组指针
uint_16 acceptMask ////信号掩码
);
如果有效信号不都为激活态,函数会被阻塞,直到有效信号全为激活态
通知线程信号状态已改变
void os_Notify(
uchar taskId, //线程ID
BOOL isUrgent //信号是否为紧急级信号
);
信号状态是由用户代码来完成的,内核是不知道的,因此将信号转为激活态后,需要调用该函数来显式的通知等待该信号的线程。isUrgent为os_true时,内核会提高taskId标识的线程的动态优先级,因此实时性好一些。可以在改变同一个线程等待的多个信号状态后,再来调用os_Notify函数,只要有一个信号是紧急级信号,就应该将isUrgent设为os_true。
创建事件同步对象
HEVENT os_CReateEvent(
BOOL isNotified //事件同步对象的初始态,os_true为激活态,os_false为未激活态
);
返回值
若创建成功,返回非零值,否则返回NULL_HEVENT。
创建信标同步对象
HSEMAPHORE os_CreateSemaphore(
uchar nResource //初始资源数目
);
返回值
若创建成功,返回非零值,否则返回NULL_HSEMAPHORE。
删除同步对象
void os_DeleteObject(
HOBJECT hObject //同步对象句柄
);
参数
hObject
由os_CreateEvent 或 os_CreateSemaphore 返回的有效同步对象句柄
将事件同步对象设为通知态
void os_SetEvent(
HEVENT hEvent, //事件同步对象句柄
uchar resetMode //复位方式
);
参数
hEvent
由os_CreateEvent返回的有效事件同步对象句柄
resetMode
复位方式。可选项位
AUTO_RESET 自动复位方式
HANDLE_RESET 手动复位方式
Remark
调用该函数时,等待该事件对象的线程转为就绪态。选用手动复位方式时,事件同步对象保持通知态只到显示调用os_ResetEvent来改变为未通知态。选用自动方式下,退出该函数时事件同步对象为未通知态。一般选用手动复位方式。
将事件同步对象复位为未通知态
void os_ResetEvent(
HEVENT hEvent//事件同步对象句柄
);
等待事件同步对象
void os_WaitEvent(
HEVENT hEvent //事件同步对象句柄
);
Remark
调用该函数时,若事件同步对象为通知态,同直接返回,若为未通知态,则线程会被暂停执行直到事件同步对象变为通知态。
查询事件同步对象
BOOL os_RequireEvent(
HEVENT hEvent //事件同步对象句柄
);
Remark
若事件同步对象为通知态,返回os_true;若为未通知态返回os_false
等待信标同步对象
void os_WaitSemaphore(
HSEMAPHORE hSemaphore //信标同步对象句柄
);
Remark
若信标同步对象的现有资源数不为0,则现有资源数减一后返回;若为0,则线程被暂停执行直到其它线程来调用os_ReleaseSemahore来释放资源。不再使用资源时,应调用os_ReleaseSemaphore及时释放资源。
查询信标同步对象
BOOL os_RequireSemaphore(
HSEMAPHORE hSemaphore //信标同步对象句柄
);
返回值
若信标同步对象的现有资源数不为0,则现有资源数减一后返回os_true;若为0,返回os_false
释放信标同步对象资源
void os_ReleaseSemaphore(
HSEMAPHORE hSemaphore //信标同步对象句柄
);
Remark
调用此函数使信标同步对象的资源数加一。
在限定时间内等待同步对象
uchar os_WaitObjectTimeOut(
HOBJECT hObject,//同步对象句柄
uint_16 elapse //限定时长
);
参数
hObject
由os_CreateEvent或os_CreateSemaphore返回的有效同步对象句柄
elapse
限定时长,以时钟节为单位。
返回值
若在限定时间内等到同步对象,则返回WAIT_SUCCESS;若在限定时间内未能等到,则返回WAIT_TIME_OUT。
若系统定时器资源不足,返回NOT_ENOUGH_TIMER。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -