📄 os_core.c.bak
字号:
#include "include.h"
#define DEBUG
#define OS_TASK_SWITCH
extern uint8 idata STACK[1];
//堆栈首地址
uint8 data gStack;
//当前任务号
uint8 data OSCurrentTaskID;
//下一个任务号
//uint8 data OSNextTaskID;
uint8 const OSMapTbl[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00};
//uint8 data OS_IRQ_Sum;//中断计数器
uint8 xdata taskMAX_stack[24];
uint8 code OSUnMapTbl[] = {
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00 to 0x0F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x10 to 0x1F */
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x20 to 0x2F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x30 to 0x3F */
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x40 to 0x4F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x50 to 0x5F */
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x60 to 0x6F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x70 to 0x7F */
7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x80 to 0x8F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x90 to 0x9F */
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xA0 to 0xAF */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xB0 to 0xBF */
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xC0 to 0xCF */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xD0 to 0xDF */
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xE0 to 0xEF */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 0xF0 to 0xFF */
};
// 上面256的表可以简化为16*2的表,查表麻烦点,不过说不定最后占用代码空间更大
// 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, //0Xx0 0Xx1 0Xx2 0Xx3....0XxE 0XxF
// 0, 4, 5, 4, 6, 4, 5, 4, 7, 4, 5, 4, 6, 4, 5, 4, //0X00 0X10 0X20 0X30....0XE0 0XF0
uint8 data OSRdyGrp; // Ready list group
uint8 data OSRdyTbl[OS_RDY_TBL_SIZE]; // Table of tasks which are ready to run
OS_TCB data Tasks_TCB[OS_MAX_TASKS];
extern void Push_Reg (void);
extern void Pop_Reg (void);
//功能描述: 系统开始运行时初始化
void OSInit(void) SMALL
{uint8 i;
gStack=STACK-2; //堆栈的首地址
//OS_IRQ_Sum = 0;
OSRdyGrp=0;//就绪组标志
memset(OSRdyTbl, 0, OS_RDY_TBL_SIZE);///就绪组内标志
OSCurrentTaskID = OS_MAX_TASKS-1;//当前任务为系统任务
//OSCPUInit();//初始化任务表
for (i = 0; i < OS_MAX_TASKS; i++)
{
Tasks_TCB[i].pTask = 0; // Load Stack pointer in TCB
//Tasks_TCB[i].OSTCBPrio = i; // Load task priority into TCB
Tasks_TCB[i].OSTCBStat = INACTIVE; //OS_STAT_RDY; // Task is ready to run
Tasks_TCB[i].OSTCBDly = 0; //Task is not delayed
//Tasks_TCB[i].stk = stk;
Tasks_TCB[i].size = 0;
Tasks_TCB[i].stk_used = 0;
}
}
/*
该函数将创建一个系统任务
*/
//#pragma disable //禁止所有中断
void os_sys_init(pFUN task)//( void (*task)(void) )
{char xdata *pstack;
//char idata *stack_bottom;
//uint8 IEtemp;
uint16 addr;
OS_AllIRQ_Unable(); //总中断禁止
//IEtemp=Read_data(SP--);//将堆栈中的中断标志读出来 #pragma disable //禁止所有中断
OSInit();
//系统任务地址
addr=Read_data(SP--); //读出刚才压入堆栈的函数地址.高地址
addr <<= 8;
addr += Read_data(SP) ;//Read_data(SP-1); //读出刚才压入堆栈的函数地址.低地址.有错
SP++;
//保存系统任务
Tasks_TCB[OS_MAX_TASKS-1].pTask = (void code *)addr; // Load Stack pointer in TCB
//Tasks_TCB[OS_MAX_TASKS-1].OSTCBPrio = (INT8U)priority; // Load task priority into TCB
Tasks_TCB[OS_MAX_TASKS-1].OSTCBStat = READY; //OS_STAT_RDY; // Task is ready to run
Tasks_TCB[OS_MAX_TASKS-1].OSTCBDly = 0; //Task is not delayed
Tasks_TCB[OS_MAX_TASKS-1].stk = taskMAX_stack;
Tasks_TCB[OS_MAX_TASKS-1].size = sizeof(taskMAX_stack);
Tasks_TCB[OS_MAX_TASKS-1].stk_used = (2+13);
pstack=Tasks_TCB[OS_MAX_TASKS-1].stk;
//系统任务就绪
//OSTaskResume(OS_MAX_TASKS-1);
OSRdyGrp |= OSMapTbl[(OS_MAX_TASKS-1)>>3]; //prio>>3-->prio/8
OSRdyTbl[(OS_MAX_TASKS-1)>>3] |= OSMapTbl[(OS_MAX_TASKS-1)&0x07]; //prio&0x07-->prio%8
//将task函数地址替换为进入该函数后地址,该函数退出后将执行task函数
task();//该函数里面会打开中断
//addr = (uint16)task;
//Write_data( ++SP, addr );
//Write_data( ++SP, addr>>8 );
//Write_data( ++SP, IEtemp );
}
/*------------------------------------------------------------------*-
创建任务
* pFunction--任务地址
* prio--优先级
task, Task to create
prio, Task priority (1-254)
stk, Pointer to the task's stack
size, Number of bytes in the stack
任务创建后进入就绪状态
-*------------------------------------------------------------------*/
#pragma disable //禁止所有中断
OS_TID os_tsk_create_user( pFUN task, U8 prio, void* stk, STK_SIZE_BIT size ) SMALL
{//OS_TCB *ptcb;
char xdata *pstack;
uint16 i;
//OS_ENTER_CRITICAL();
// IrqAll_Unable(); //总中断禁止 IrqT0_Unable(); //定时器0中断禁止
//ptcb=&Tasks_TCB[prio];
if (Tasks_TCB[prio].pTask == NULL)
{
Tasks_TCB[prio].pTask = task; // Load Stack pointer in TCB
//Tasks_TCB[prio].OSTCBPrio = (INT8U)priority; // Load task priority into TCB
Tasks_TCB[prio].OSTCBStat = READY; //OS_STAT_RDY; // Task is ready to run
Tasks_TCB[prio].OSTCBDly = 0; //Task is not delayed
Tasks_TCB[prio].stk = stk;
Tasks_TCB[prio].size = size;//size必须比2+13大
Tasks_TCB[prio].stk_used = 2+13;//2个任务地址+13个特殊功能寄存器
//设置任务就绪表,让任务就绪
OSRdyGrp |= OSMapTbl[prio>>3]; //prio>>3-->prio/8
OSRdyTbl[prio>>3] |= OSMapTbl[prio&0x07]; //prio&0x07-->prio%8
//堆栈初始化
//OSTaskStkInit(task, prio);
pstack=Tasks_TCB[prio].stk;
*pstack++ = (uint8)task; //任务低地址进栈
*pstack++ = (uint16)task>>8; //任务高地址进栈
for(i=0; i<Tasks_TCB[prio].size; i++)//初始化清空堆栈
{
*pstack++ = 0;
}
return (prio);
}
//OS_EXIT_CRITICAL();
// IrqAll_Enable(); //总中断允许 IrqT0_Enable(); //打开T0中断允许
return (0);
}
#ifndef OS_TASK_SWITCH
//功能描述: 系统时钟中断服务函数
//#pragma disable //禁止所有中断
void OSTickISR(void) interrupt 1 //OS_TIME_ISR
{uint8 data IEtemp;
//TH0=T0H_COUNTER;
//TL0=T0L_COUNTER;
IEtemp=IE;//保存中断
OS_AllIRQ_Unable(); //总中断禁止
//IE &= B0000_0000; //IE &= B0000_0001; //保留外部中断原来状态,屏蔽掉其他中断
//#if EN_TIMER_SHARING > 0
if(TH0==0)//==0说明是定时器溢出中断,!=0表示是软件设置的定时器中断
{
TH0=T0H_COUNTER;
TL0=T0L_COUNTER;
OSTimeTick(); //调用系统时钟处理函数
}//
//#else
// OSIntSendSignal(TIME_ISR_TASK_ID); // 唤醒ID为TIME_ISR_TASK_ID的任务
//#endif
OSIntExit(); //在完全退出中断时,才进行任务切换
//OS_AllIRQ_Enable(); //总中断允许
IE=IEtemp; //恢复所有中断状态
}
#else
#endif
/*
堆栈保存内容:
数据堆栈+函数地址+特殊功能积存器
//功能描述: 中断退出处理函数,在此进行中断后的任务切换
//IRQ_Stack_Bottom任务中断后的堆栈栈顶
//在退出中断时,不让进栈的数据出栈。在完全退出中断时,才进行任务切换,
1.1 保存当前任务堆栈
1.2 保存任务特殊功能寄存器
1.3 保存任务堆栈+任务特殊功能寄存器->堆栈备份空间
1.4 切换任务
2.1 从堆栈备份空间->恢复新的就绪的任务的堆栈
2.2 恢复任务特殊功能寄存器
2.3 将新任务原来断点地址压入堆栈
*/
void OSIntExit(void) SMALL
{char idata * stack_bottom;
char xdata * stack_bottom_bak;
//uint16 addr;
uint16 old_addr;
uint8 old_taskid;//
old_taskid=OSCurrentTaskID;
OSFindNextRunningTask(); //查找下一个就绪的任务
if(old_taskid==OSCurrentTaskID) //任务不切换
return;
Tasks_TCB[OSCurrentTaskID].OSTCBStat = RUNNING; //任务运行中
//系统不备份调用本函数压入的堆栈
old_addr=Read_data(SP--); //读出刚才压入堆栈的函数地址.高地址
old_addr <<= 8;
old_addr += Read_data(SP--); //读出刚才压入堆栈的函数地址.低地址
stack_bottom=gStack+1;//当前任务堆栈底地址
stack_bottom_bak=Tasks_TCB[old_taskid].stk;//当前任务堆栈底备份地址
//1.3 保存任务堆栈+任务特殊功能寄存器->堆栈备份空间
Tasks_TCB[old_taskid].stk_used=SP-gStack;//任务堆栈已经使用数量
memcpy(stack_bottom_bak, stack_bottom, SP-gStack);
//1.4 切换任务.前面已经执行过
//OSFindNextRunningTask(); //查找下一个就绪的任务
//2.1 从堆栈备份空间->恢复新的就绪的任务的堆栈
stack_bottom=gStack+1;//当前任务堆栈底地址
stack_bottom_bak=Tasks_TCB[OSCurrentTaskID].stk;//当前任务堆栈底备份地址
SP=gStack+Tasks_TCB[OSCurrentTaskID].stk_used;//新任务恢复堆栈后,堆栈指针的位置
memcpy(stack_bottom, stack_bottom_bak, Tasks_TCB[OSCurrentTaskID].stk_used);//将保存的堆栈数据拷贝到堆栈区
// //2.2 恢复任务特殊功能寄存器
// #ifdef DEBUG
// //方便在本文件中调试,查看代码方便,将多占2byte堆栈,和一点代码空间
// Pop_Reg();
// SP -= 13;
// #else
// #pragma ASM
// #pragma ENDASM
// #endif
//2.3 将新任务原来断点地址压入堆栈
//addr = (uint16)Tasks_TCB[OSCurrentTaskID].pTask;//将新任务原来断点地址压入堆栈,在该函数退出后将恢复运行
//Write_data( ++SP, addr );
//Write_data( ++SP, addr>>8 );
//Write_data( ++SP, SPtemp );//恢复中断标志
Write_data( ++SP, old_addr );
Write_data( ++SP, old_addr>>8 );
}
//功能描述: 系统时钟处理函数,处理各个任务的延时
//任务延时减为0,就进入就绪状态
//中断中调用, 各任务等待时间-1
void OSTimeTick(void) SMALL
{uint8 prio;
//OS_TCB *ptcb;
//ptcb=&Tasks_TCB[0];
for ( prio = 0; prio < OS_LOWEST_PRIO; prio++)//,ptcb++ )
{
if(Tasks_TCB[prio].OSTCBDly != 0 && Tasks_TCB[prio].OSTCBDly != 0xffff)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -