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

📄 kernel.c

📁 itron操作系统在日本用的很多
💻 C
📖 第 1 页 / 共 2 页
字号:
{
    //在中断通知处理中或者CPU锁定状态不允许禁止分发器//
    if (INEST > 0 || SYSSTAT == TSS_LOC)
    {
        return E_CTX;   //返回系统调用无效//
    }

    SYSSTAT = TSS_DDSP; //系统状态设定为禁止分发器状态//

    return  E_OK;   //系统调用正常返回//
}


void _ena_dsp(void)
{
    //在中断通知处理中或者CPU锁定状态不允许使能分发器//
    if (INEST > 0 || SYSSTAT == TSS_LOC)
    {
        *USP = E_CTX;   //返回系统调用无效//

        return;
    }

    SYSSTAT = TSS_TSK;  //系统状态设定为任务状态//
    *USP = E_OK;    //系统调用正常返回//

    dispatch();     //激活分发器//  
}

ER _loc_cpu(void)
{
    //在中断通知处理中不允许锁定CPU//
    if (INEST > 0)
    {
        return E_CTX;   //返回系统调用无效//
    }

    SYSSTAT = TSS_LOC;  //系统状态设定为CPU锁定状态//

    return  E_OK;   //系统调用正常返回//
}

void _unl_cpu(void)
{
    //在中断通知处理中不允许解锁CPU//
    if (INEST > 0)
    {
        *USP = E_CTX;   //返回系统调用无效//

        return;
    }

    SYSSTAT = TSS_TSK;  //系统状态设定为任务状态//
    *USP = E_OK;    //系统调用正常返回//

    dispatch(); //激活分发器//     
}

ER _iwup_tsk( ID tskid )
{
    T_TCB *tcb;     //指向任务TCB的临时指针//

    //判断任务ID是否大于任务ID的最大值//
    if (tskid > TSKID_MAX)
    {
        return E_NOEXS;     //返回任务不存在//
    }

    //在中断通知处理中,TSK_SELF是无效的//
    if (tskid == TSK_SELF)
    {
        //是TSK_SELF,返回//
        return E_OBJ;
    }
    tcb = &TCB[tskid];      //通过任务ID得到任务的TCB//

    //不能唤醒DORMANT状态的任务//
    if (tcb->tskstat == TTS_DMT)
    {
        //要唤醒的任务是DORMANT状态,返回//
        return E_OBJ;
    }

    //要唤醒的任务如果处在等待状态,并且是由于调用了tsk_slp(itsk_slp)//
    //怎唤醒该任务,否则//
    if (tcb->tskstat == TTS_WAI && tcb->tskwait == TTW_SLP)
    {
        //将要唤醒的任务状态改为Ready状态//
        tcb->tskstat = TTS_RDY;
        //将任务的TCB添加到Ready对列//
        add_que( &RDQ[tcb->tskpri], tcb );
        //调用slp_tsk时,将PC,FLG,FB,SB,A1,A0,R3,R2,R1,R0压入任务堆栈//
        //tcb->sp为任务堆栈的栈顶指针//
        //*(tcb->sp)为R0//
        //任务唤醒后,R0中存放返回值//
        *(tcb->sp) = E_OK;  //等待唤醒的任务继续运行时的返回值为正常返回//
        DELAY = SET;    //设置调度器延时状态//

        //iwup_tsk正常结束返回//
        return E_OK;
    }
    else
    {
        //唤醒请求计数器是一个16位有符号值,最大值为32767//
        //判断唤醒请求计数器是否溢出//
        if (tcb->wupcnt < INT_MAX)
        {
            tcb->wupcnt ++;     //唤醒请求计数器递增//

            /*iwup_tsk正常结束返回*/
            return E_OK;
        }
        else
        {
            /*唤醒请求计数器发生溢出错误,返回溢出错误状态*/
            return E_QOVR;
        }
    }
}

void _slp_tsk(void)
{
	//在中断通知处理或者分发器禁止状态不允许调用此系统调用//
    if (INEST > 0 || SYSSTAT >= TSS_DDSP)
    {
		//返回错误状态//
        //Context error (issued from task-independent portions or a task in dispatch disabled state)
        *USP = E_CTX;	//USP为中断時SP値,*USP为R0的值//
        return;
    }

	//如果当前任务的唤醒请求计数器>0,则任务不进入等待状态//
    if (RUNTCB->wupcnt > 0)
    {
        RUNTCB->wupcnt --;	//唤醒请求计数器递减//
        *USP = E_OK;		//系统调用正常结束//
        return;
    }
	//当前任务的唤醒请求计数器为0,任务进入等待状态//
    else
    {
        RUNTCB->tskstat = TTS_WAI;	//任务状态设为等待状态//
        RUNTCB->tskwait = TTW_SLP;	//等待模式为SLP//

		//将当前任务的TCB从Ready对列中删除//
        del_que( &RDQ[RUNTCB->tskpri], RUNTCB );

		//调用分发器,运行其它任务//
        dispatch();

        return;
    }
}

void _wup_tsk( ID tskid )
{
    T_TCB *tcb;     //指向任务TCB的临时指针//

    //判断任务ID是否大于任务ID的最大值//
    if (tskid > TSKID_MAX)
    {
        *USP = E_NOEXS;     //返回任务ID不存在//
        return;
    }

    //当前任务不能唤醒自身,只能唤醒其他任务//
    //判断是否为任务自身//
    if (tskid == TSK_SELF || tskid == RUNTCB->tskid)
    {
        //是当前任务,返回//
        *USP = E_OBJ;	//无效对象//
        return;
    }
    tcb = &TCB[tskid];      //通过任务ID得到任务的TCB//

    //不能唤醒DORMANT状态的任务//
    if (tcb->tskstat == TTS_DMT)
    {
        //要唤醒的任务是DORMANT状态,返回//
        *USP = E_OBJ;	//无效对象//
        return;
    }

    //要唤醒的任务如果处在等待状态,并且是由于调用了tsk_slp(itsk_slp)//
    //怎唤醒该任务,否则//
    if (tcb->tskstat == TTS_WAI && tcb->tskwait == TTW_SLP)
    {
        //将要唤醒的任务状态改为Ready状态//
        tcb->tskstat = TTS_RDY;
        //将任务的TCB添加到Ready对列//
        add_que( &RDQ[tcb->tskpri], tcb );
        //调用slp_tsk时,将PC,FLG,FB,SB,A1,A0,R3,R2,R1,R0压入任务堆栈//
        //tcb->sp为任务堆栈的栈顶指针//
        //*(tcb->sp)为R0//
        //任务唤醒后,R0中存放返回值//
        *(tcb->sp) = E_OK;
        //wup_tsk的返回值用堆栈返回//
        *USP = E_OK;
        //调用分发器,调度任务//
        dispatch();
        return;
    }
    else
    {
        //唤醒请求计数器是一个16位有符号值,最大值为32767//
        //判断唤醒请求计数器是否溢出//
        if (tcb->wupcnt < INT_MAX)
        {
            tcb->wupcnt ++;     //唤醒请求计数器递增//
            //wup_tsk正常结束返回//
            *USP = E_OK;
            return;
        }
        else
        {
            //唤醒请求计数器发生溢出错误,返回溢出错误状态//
            *USP = E_QOVR;
            return;
        }
    }
}

ER _ista_tsk(ID tskid, INT stacd)
{
	T_TCB *tcb;     //指向任务TCB的临时指针//
	UINT data;

	//判断任务ID是否大于任务ID的最大值//
    if (tskid > TSKID_MAX)
    {
        return E_NOEXS;     //返回任务不存在//
    }

	tcb = &TCB[tskid];      //通过任务ID得到任务的TCB//

    //只能启动DORMANT状态的任务//
    if (tcb->tskstat != TTS_DMT)
    {
        //要启动的任务不是DORMANT状态,返回//
        return E_OBJ;
    }

	//将任务状态改为Ready状态//
    tcb->tskstat = TTS_RDY;
	//设置任务的优先级//
	tcb->tskpri = pri_tbl[tskid];
	//设置任务堆栈指针
	//任务启动前堆栈内容为:FLG,PC,FB,SB,A1,A0,R3,R2,R1,R0//
	//nc30的堆栈生长方向为递减//
	tcb->sp = (INT*)sp_tbl[tskid] - CTXSIZ;
	//任务的唤醒请求计数器清零//
	tcb->wupcnt = 0;

	//设置任务的起始地址//
	data = (UINT)stad_tbl[tskid];	//起始地址的低0~15位放到sp_tbl[tskid]-2//
	*(sp_tbl[tskid]-2) = data;
	data = (UINT)(stad_tbl[tskid] >> 8) & 0x0f00;	//起始地址的16~20低位放到sp_tbl[tskid]-1的8~11位//
	data |= INIFLG;					//标志寄存器的0~7低位放到sp_tbl[tskid]-1的0~7位//
	*(sp_tbl[tskid] - 1) = data;	//标志寄存器的12~15低位放到sp_tbl[tskid]-1的12~15位//
									//标志寄存器的8~11不保存//
	*((tcb->sp)+1) = stacd;		//将任务的参数放到R1寄存器内//

	add_que(&RDQ[tcb->tskpri], tcb);	//将启动的任务加入Ready对列//

	DELAY = SET;	//设置调度器延时状态//

	return E_OK;	//正常返回//
}

void main(void)
{
	ID id;

    //RTOS初始化(TCB,SEM,MBX)//
	sysini();

    //启动任务//
	for(id=1; id<TSKID_MAX+1; id++)
	{
		_ista_tsk(id, DUMMY);   //通过带i的系统调用不激活分发器//
	}

    //系统定时器的初始化//
	systimini();

    //开始多任务系统//
	syssta();   //此函数模拟一次中断,永远不会返回//
}

void sysini(void)
{
	ID id;

	//初始化任务的TCB//
	for(id=1; id<TSKID_MAX+1; id++)
	{
		TCB[id].tskid = id;
		TCB[id].tskstat = TTS_DMT;  //初始任务为Dormant状态//
	}

	//初始化信号量//
	for(id=1; id<SEMID_MAX+1; id++)
	{
		SEM[id].cnt = semcnt_tbl[id];   //设定信号量的初始值//
	}

	//初始化邮箱//
	for(id=1; id<MBXID_MAX+1; id++)
	{
        //初始化邮箱消息指针//
		MBX[id].msghead = msgq_tbl[id]; 
		MBX[id].msgtail = msgq_tbl[id];
	}

	DELAY 	= CLR;		//清除调度器延时状态//
	INEST	= 0;		//中断嵌套清零//
	SYSSTAT	= TSS_LOC;	//系统状态设为CPU加锁状态//
	UIPL	= 0;		//中断允许级别设为零//
}

void _syssta(void)
{
	RUNTCB = &TCB[1];	//将第一个任务设为当前运行的任务//
	USP = TCB[1].sp;	//设置当前的用户堆栈指针//
	SYSSTAT = TSS_TSK;	//设置当前CPU状态为:正常状态,任务状态//

	dispatch();			//调用分发器//
}

void systimini(void)
{
	ta0mr = 0x80;
	ta0ic = (UB)(0x07 & SYSTIM_IPL);    //设定定时器的中断优先级//
    ta0 = (UINT)(SYSTIM_CNT - 1);       //设定计时时间//
    tabsr = 0x01;   //开始计数//
}

void add_que(T_TCB **head, T_TCB *addtcb)
{
    //判断链表是否为空//
	if(*head == NULL)
    {
        addtcb->prev = addtcb;  //前向指针指向自身//
        addtcb->next = addtcb;  //后向指针指向自身//
        *head = addtcb;         //头节点指向添加的节点//
    }
    else
    {		//定义并取得T_TCB的头,尾节点指针//
        T_TCB *toptcb = *head;
        T_TCB *endtcb = toptcb->prev;
		//建立next单链//
        endtcb->next = addtcb;
        addtcb->next = toptcb;
		//建立prev单链//
        addtcb->prev = endtcb;
        toptcb->prev = addtcb;

    }
}

void del_que(T_TCB **head, T_TCB *deltcb)
{
	//定义并获取删除节点的前后T_TCB节点指针//
	T_TCB *prevtcb = deltcb->prev;
	T_TCB *nexttcb = deltcb->next;

	//如果链表中只有一个节点则清空链表//
	if(deltcb == nexttcb)
    {
        *head = NULL;	//清空链表//
    }
    else
    {
		//从双向链表中摘除//
        prevtcb->next = nexttcb;
        nexttcb->prev = prevtcb;

		//如果删除的是头节点则头节点依次向下指//
		if(deltcb == *head)
		{
			*head = nexttcb;		//头节点指向下一个节点//
		}
    }
}

void dispatch(void)
{
    T_TCB **rdq = &RDQ[1];	//指向最高优先级的队列头,itron规范不使用RDQ[0]//

	//在分发器禁止状态要将分发器调度延时//
    if (SYSSTAT >= TSS_DDSP)
    {
		DELAY = SET;    //设置调度器延时状态//

        return;
    }

	DELAY = CLR;    //清除调度器延时状态//

	//在Ready队列中查找优先级最高的任务//
    while (*rdq == NULL)    //*rdq = NULL,说明当前的优先级没有就绪的任务//
    {
        rdq++;  //指向下一个就绪任务的TCB
    }

    RUNTCB->sp = USP;	//保存当前任务堆栈//
    RUNTCB = *rdq;		//更改当前运行任务的TCB//
    USP = RUNTCB->sp;	//恢复新任务的任务堆栈指针//
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -