⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 guide.txt

📁 引入事件驱动观念的抢占式多任务微型实时内核——MicroStar的设计与实现;提出基于事件的优先级这一新概念。
💻 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 + -