轻松自编小型嵌入式操作系统的附录基础系统源码.docx
《轻松自编小型嵌入式操作系统的附录基础系统源码.docx》由会员分享,可在线阅读,更多相关《轻松自编小型嵌入式操作系统的附录基础系统源码.docx(62页珍藏版)》请在冰豆网上搜索。
轻松自编小型嵌入式操作系统的附录基础系统源码
是书后的代码,用的是keil51软件,目标器件是AT89C52
我把它放在一个文件中了,然后建立工程添加Main.c后,右键Main.c
选择第一项,
勾选GenerateAssemblerSRCfIle
和AssembleSRCfile
然后由于是内嵌汇编,所以还得做一件事:
右键SourceGroup添加文件
然后去安装keil的命令下找到C51文件夹下的Lib文件,找到
个文件,加入进去
然后就编译运行
调试的时候全速运行,LED灯就闪亮了
#include
sbitLED1=P0^1;
sbit LED2=P0^2;
sbit LED3=P0^3;
sbit LED4=P0^4;
voidrenwu_0();
voidrenwu_1();
voidrenwu_2();
voidrenwu_3();
voidrenwu_4();
#definerwzons5//任务总数
#define ch_danzhan_zs18 //任务栈长度配置
#definech_sjzs 3//任务时间片长度总数,如果定时时间是10ms,那么单个任务连续一次的运行时间是50ms
#define ch_tick_zs 0xdc//10ms系统时间粒度配置
#definech_ticks 10//10ms延时节拍=时间粒度
#definech_rwtd_xs 1//堆栈操作模式
#definech_gn_rw 0//功能函数配置 \
//信号量使能配置
#define ch_xhl_en 0
#definech_xhl_zs 0
//邮箱使能配置
#definech_yx_en 0
#define ch_yx_zs0
//消息队列使能配置
#definech_xxdl_en0
#definech_xxdl_zs0
#definech_fuwu_en0
typedefunsignedcharuc8;
typedefunsignedintui16;
typedefunsignedlongul32;
//系统状态模式的宏标志
#definech_tzms0x00 //系统处于停止的状态
#definech_yxms0x01//运行
#definech_hcms0x02//互斥
#definech_fwms0x04//服务运行
//任务状态宏标志
#definech_yunxing0x01 //任务是处于就绪运行态之中的
#definech_yanshi0x02 //任务处于延时运行态中
#definech_dengdai_zd0x20//等待中断状态
#definech_tingzhi 0x40//状态停止
//变量状态宏定义,比如P43说道,RW/CZXT小型嵌入式操作系统的系统管理器中有一个系统运行标志,ch_xtyx,如果操作系统
//进入运行,那么运行标志为真,即ch_xtyx=ch_on,如果操作系统未启动或停止运行,那么运行标志为假,即ch_xtyx=ch_off
//又比如ch_zd_on和ch_zd_off分别用来开方CPU总中断和禁止CPU总中断,EA=ch_zd_on,相等于EA=1
//等等,那么ch_xtyx不就是变量了嘛
#definech_on0xff // 系统运行
#definech_off0x00 //系统停止
#definech_sj_on0xff//有任务要优先运行
#definech_sj_off 0x00 //无任务要优先运行
#definech_zd_on1 //中断开
#definech_zd_off0 //中断关
#definech_dengdai_cs_on 0xff//等待超时
#definech_dengdai_cs_off0x00 //没有超时
uc8yxhao;
uc8ch_xtyx;//系统运行标志
uc8xyxhao;//存放新运行任务的任务号
uc8ch_tdsuo;//调度锁
uc8ch_zdzs;//中断嵌套计数器
uc8ch_rwsjzs;
typedefstruct guanlikuai //管理控制块,简称系统管理器,这是RW/CZXT最核心的数据结构
{
uc8yxhao;
uc8xyxhao;//存放新运行任务的任务号
uc8ch_xtyx;//系统运行标志
uc8ch_rwsjzs;
uc8ch_tdsuo;//调度锁
uc8ch_zdzs;//中断嵌套计数器 ;
uc8ch_xtzt; //系统状态
uc8ch_sjyx;//优先运行标志
}GLK;
GLK ch_xtglk;
#define ch_rwzs5// 配置任务的数量
#definech_rwzhan_cd20 //配置每个任务栈的长度
uc8idatarwzhan[ch_rwzs][ch_rwzhan_cd];
uc8idatach_yxb[ch_rwzs]; //定义任务的运行队列
uc8idatach_sj_yxb[ch_rwzs];
typedefstructrenwukuai
{
uc8rwsp;//任务栈顶寄存器
ui16rwys;//任务延时寄存器
uc8rwzt; //任务状态寄存器两个
uc8rwztchucun; //这两个相当于CPSR和SPSR
}RWK;
RWK idata ch_rwk[ch_rwzs];
voidxt_blcsh(void) //变量初始化
{
uc8i,j;
ch_xtglk.yxhao=0;//这个hao是指运行号的号,默认0号为空闲任务
ch_xtglk.xyxhao=0;// 新运行号
ch_xtglk.ch_rwsjzs=0;//任务时间片总数
ch_xtglk.ch_zdzs=0;//总段总数
ch_xtglk.ch_tdsuo=0;//调度锁
ch_xtglk.ch_xtyx=ch_off; //系统运行标志为关
ch_xtglk.ch_xtzt=ch_tzms; //系统状态等于停止状态
ch_xtglk.ch_sjyx=ch_sj_off;//无任务要优先运行
//
for(i=0;i{ch_yxb[i]=0; //数组全部初始化,这个是运行队列初始化,运行队列的作用是用来登记就绪任务的任务号,
//任务在新建立的时候,必须把任务的任务号登记在运行队列中,只有在运行队列中进行就绪登记的任务,才能够
//被调度器调度进入运行
ch_sj_yxb[i]=0;
}
for(i=0;i for(j=0;j rwzhan[i][j]=0;
} //任务堆栈用来保存任务的断电数据
voidxt_rwkzk(void)
{
uc8i;
for(i=0;i{
ch_rwk[i].rwsp=rwzhan[i]; //类比第一章,各种任务地址放在各自的任务空间,然后任务块是存放指向RAM存放
//任务的地址,说白了就是指向任务的五个指针就是这个数组
//也就是任务指针取得栈区的首地址
ch_rwk[i].rwsp+=11;//任务指针取得任务的栈顶地址
ch_rwk[i].rwzt=ch_yunxing;//任务状态为运行态
ch_rwk[i].rwztchucun=0;//SPSR无储存,也就是挂起前状态寄存器,0表示不储存任何状态信息
ch_rwk[i].rwys=0; //任务无延时,也就是延时寄存器清零
}
}
voidch_xt_renwu(void)
{
//任务函数的入口地址存入任务栈区中
rwzhan[0][1]=(ui16)renwu_0; //就像第一章一样保持任务入口地址
rwzhan[0][2]=(ui16)renwu_0>>8;
rwzhan[1][1]=(ui16)renwu_1;
rwzhan[1][2]=(ui16)renwu_1>>8;
rwzhan[2][1]=(ui16)renwu_2;
rwzhan[2][2]=(ui16)renwu_2>>8;
rwzhan[3][1]=(ui16)renwu_3;
rwzhan[3][2]=(ui16)renwu_3>>8;
rwzhan[4][1]=(ui16)renwu_4;
rwzhan[4][2]=(ui16)renwu_4>>8;
//任务块初始化
xt_rwkzk();
//任务就绪登记
//系统初始化时所创建的任务,其状态都是就绪运行态,那么任务就必须在运行队列中进行登记,
ch_yxb[0]=1;//队列首元素赋值为1,表示1号任务的任务号存入运行队列的0号位置中,下面同理
ch_yxb[1]=2;
ch_yxb[2]=3;
ch_yxb[3]=4;
ch_yxb[4]=0;
}
voidch_xt_int(void)
{
xt_blcsh(); //系统变量初始化
ch_xt_renwu();//创建任务
}
//下面是简单的任务测试代码,运行到下面的函数的末尾的时候碰到ret,然后PC=SP指向的内存地址的。
。
。
内容,然后
//就跳转到任务1了,如果没有的话就在空闲任务(任务0)运行?
不是,如果ch_xt_on函数中什么都没有,那么SP就是调用ch_xt_on的
//那个地址也就是返回函数调用
voidch_xt_on()
{
//取出1号任务的任务号
ch_xtglk.xyxhao=ch_yxb[0];//任务管理块取得任务运行队列的第一个运行任务号
ch_xtglk.yxhao=ch_xtglk.xyxhao;//系统的运行号设置为那个
//SP取得1号任务的栈顶地址
SP=ch_rwk[ch_xtglk.yxhao].rwsp;
}
//消息队列登记函数
voidch_yxbdengji(uc8dengjihao)
{
uc8wei;//位置
for(wei=0;wei{
if(ch_yxb[wei]==0)
{
ch_yxb[wei]=dengjihao;
ch_rwk[dengjihao].rwzt=ch_yunxing;
wei=ch_rwzs;
}
}
}
//优先消息队列登记函数
voidch_sj_yxbdengji(uc8dengjihao)
{
uc8wei;
for(wei=0;wei{
if(ch_sj_yxb[wei]==0)
{
ch_sj_yxb[wei]=dengjihao;
ch_rwk[dengjihao].rwzt=ch_yunxing;
wei=ch_rwzs;
}
}
ch_xtglk.ch_sjyx=ch_sj_on;
}
//取出就绪任务,然后队伍前移,就是取出队首,然后前移
uc8ch_rwhao(void)
{
uc8xin;
uc8jiu;
uc8rwhao;
rwhao=ch_yxb[0];
if(ch_yxb[0]!
=0)
{
for(jiu=1,xin=0;jiu{
ch_yxb[jiu-1]=0;
if(ch_yxb[jiu]!
=0)
{
ch_yxb[xin]=ch_yxb[jiu];
xin++;
}
if((ch_yxb[jiu]!
=0)&&(jiu==(ch_rwzs-1)))
{
ch_yxb[jiu]=0;
}
}
}
return(rwhao);
}
//取出优先消息队列的任务
uc8ch_sj_rwhao(void)
{
uc8xin;
uc8jiu;
uc8rwhao;
rwhao=ch_sj_yxb[0];
if(ch_sj_yxb[0]!
=0)
{
for(jiu=1,xin=0;jiu{
ch_sj_yxb[jiu-1]=0;
if(ch_sj_yxb[jiu]!
=0)
{
ch_sj_yxb[xin]=ch_sj_yxb[jiu];
xin++;
}
if((ch_sj_yxb[jiu]!
=0)&&(jiu==(ch_rwzs-1)))
{
ch_sj_yxb[jiu]=0;
}
}
}
if(ch_sj_yxb[0]==0)
{
ch_xtglk.ch_sjyx=ch_sj_off;
}
return(rwhao);
}
//更新运行队列中就绪任务的位置
voidyxb_genxin(void)
{
uc8xin;
uc8jiu;
for(xin=0,jiu=0;jiu{
if(ch_yxb[jiu]!
=0)
{
ch_yxb[xin]=ch_yxb[jiu];
xin++;
}
if((ch_yxb[jiu]!
=0)&&(jiu==ch_rwzs-1)&&(xin{
ch_yxb[jiu]=0;
}
}
}
voidsj_yxb_genxin(void)
{
uc8xin;
uc8jiu;
for(xin=0,jiu=0;jiu{
if(ch_sj_yxb[jiu]!
=0)
{
ch_sj_yxb[xin]=ch_sj_yxb[jiu];
xin++;
}
if((ch_sj_yxb[jiu]!
=0)&&(jiu==ch_rwzs-1)&&(xin{
ch_sj_yxb[jiu]=0;
}
}
}
//删除运行队列中的就绪任务
voidch_yxbqingchu(uc8qingchuhao)
{
uc8wei;
for(wei=0;wei{if(ch_yxb[wei]==qingchuhao)
{
ch_yxb[wei]=0;
yxb_genxin();//运行队列更新
wei=ch_rwzs;//中断循环
}
}
}
uc8ch_sj_yxbqingchu(uc8qingchuhao)
{
uc8wei;
uc8czxx;
czxx=0x00;
for(wei=0;wei{if(ch_sj_yxb[wei]==qingchuhao)
{
ch_sj_yxb[wei]=0;
sj_yxb_genxin();//运行队列更新
wei=ch_rwzs;//中断循环
czxx=0xff;
}
}
if(ch_sj_yxb[0]==0)
{ch_xtglk.ch_sjyx=ch_sj_off;
}
return(czxx);//删除成功标志位,cz是操作的意思
}
//任务级调度器
voidch_rwtd(void)
{
EA=ch_zd_off;
if(ch_xtglk.ch_xtyx!
=ch_on)
{EA=ch_zd_on;return;}
if(ch_xtglk.ch_tdsuo!
=0)
{EA=ch_zd_on;return;}
if(ch_xtglk.ch_zdzs!
=0)
{EA=ch_zd_on;return;}
if(ch_xtglk.ch_xtyx==ch_fwms)
{EA=ch_zd_on;return;}
if(ch_xtglk.ch_rwsjzs!
=0)
{EA=ch_zd_on;return;}
if(ch_xtglk.xyxhao==0)
{
if(ch_xtglk.ch_sjyx==ch_sj_on)
{
ch_xtglk.xyxhao=ch_sj_rwhao();
}
else
{
ch_xtglk.xyxhao=ch_rwhao();
}
}
ch_xtglk.ch_rwsjzs=ch_sjzs;
if(ch_xtglk.yxhao!
=ch_xtglk.xyxhao)
{
/*__asmPUSHACC
__asmPUSHB
__asmPUSHPSW
__asmPUSHAR0
__asmPUSHAR1
__asmPUSHAR4
__asmPUSHAR5
__asmPUSHAR6
__asmPUSHAR7
*/
#pragmaasm
PUSHACC
PUSHB
PUSHPSW
PUSHAR0
PUSHAR1
PUSHAR4
PUSHAR5
PUSHAR6
PUSHAR7
#pragmaendasm
ch_rwk[ch_xtglk.yxhao].rwsp=SP;
ch_xtglk.yxhao=ch_xtglk.xyxhao;
ch_xtglk.xyxhao=0;
SP=ch_rwk[ch_xtglk.yxhao].rwsp;
/*__asmPOPAR7
__asmPOPAR6
__asmPOPAR5
__asmPOPAR4
__asmPOPAR1
__asmPOPAR0
__asmPOPPSW
__asmPOPB
__asmPOPACC */
#pragmaasm
POPAR7
POPAR6
POPAR5
POPAR4
POPAR1
POPAR0
POPPSW
POPB
POPACC
#pragmaendasm
}
EA=ch_zd_on;
}
//中断调度器在此,但是书上的函数名有所缺漏
//调度器上锁
voidch_tdsuo_on(void)
{
EA=ch_zd_off;
if(ch_xtglk.ch_tdsuo==0)
{
ch_xtglk.ch_tdsuo=1;
}
EA=ch_zd_on;
}
//解锁
voidch_tdsuo_off(void)
{
EA=ch_zd_off;
if(ch_xtglk.ch_tdsuo>0)
{
ch_xtglk.ch_tdsuo=0;
}
EA=ch_zd_on;
}
//定时器T0初值数据安装函数
//比如定时10ms,就是每10ms就产生一次中断,设置TF0=1,基于12M晶振就如下确定值
#definech_tick_th0 ((65536-10000)/256)
#definech_tick_tl0 ((65536-10000)%256)
//系统配置文件PZ中有对时间片总数的定义
voidch_time_sjaz(void)
{
TR0=0;//关定时器0
TH0=ch_tick_th0;
TL0=ch_tick_tl0;
TR0=1;//定时器0启动
}
voidch_time_on(void)
{
TMOD|=0x01;//运行模式1
ch_time_sjaz();
ET0=1;//定时器中断开,当溢出时就产生中断,设置TF0=1
}
//时间节拍延时函数,就是延时的单位是以时间节拍为单位,而时间节拍由定时器产生中断产生,比如每10ms产生一次
//中断,那么时间节拍就是10ms,任务延时100个时钟节拍,那么任务的延时时间就是1s,在进入延时之前,系统清除时间片
//设置任务状态为延时状态,
//进入,退出中断函数,
voidch_zhongduan_on(void)
{
EA=ch_zd_off;
if(ch_xtglk.ch_zdzs<8)
{
ch_xtglk.ch_zdzs++;
}
EA=ch_zd_on;
}
voidch_zhongduan_off(void)
{
EA=ch_zd_off;
if(ch_xtglk.ch_zdzs<8)
{
ch_xtglk.ch_zdzs--;
}
EA=ch_zd_on;
}
voidch_rwyschaxun(void)
{
uc8i;
for(i=0;i{
if((ch_rwk[i].rwys>0)&&(ch_rwk[i].rwzt!
=ch_tingzhi))
{
ch_rwk[i].rwys-=1;
if(ch_rwk[i].rwys==0)
{
if(ch_rwk[i].rwzt==ch_yanshi)
{
ch_yxbdengji(i);
}
}
}
}
}
//T0中断服务
voidch_timer0(void)interrupt1
{
ch_zhongduan_on();
EA=ch_zd_off;
ch_time_sjaz();
ch_rwyschaxun();
if((ch_xtglk.ch_rwsjzs>0)&&
(ch_xtglk.ch_tdsuo==0))
{
ch_xtglk.ch_rwsjzs--;
if(ch_xtglk.ch_rwsjzs==0)
{
if(ch_xtglk.yxhao!
=0)
{
ch_yxbdengji(ch_xtglk.yxhao);
}
}
}
ch_zhongduan_off();
if((ch_xtglk.yxhao==0)&&
(ch_xtglk.ch_rwsjzs!
=0))
{
ch_xtglk.ch_rwsjzs=0;
}
EA=ch_zd_off;
if((ch_xtglk.ch_zdzs==0)&&
(ch_xtglk.ch_tdsuo==0)&&
(ch_xtglk.ch_rwsjzs==0)&&
(ch_xtglk.ch_xtzt!
=ch_fwms))
{
if(ch_xtglk.xyxhao==0)
if(ch_xtglk.ch_sjyx==ch_sj_on)
{ch_xtglk.xyxhao=ch_sj_rwhao();}
else
{
ch_xtglk.xyxhao=ch_rwhao();
}
ch_xtglk.ch_rwsjzs=ch_sjzs;
if(ch_xtglk.yxhao!
=ch_xtglk.xyxhao)
{
ch_rwk[ch_xtglk.yxhao].rwsp=SP;
ch_xtglk.yxhao=ch_xtglk.xyxhao;
ch_xtglk.xyxhao=0;
SP=ch_rwk[ch_xtglk.yxhao].rwsp;
}
}
EA=ch_zd_on;
}
voidch_rwys_tk(ui16