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

📄 kernel.c

📁 itron操作系统在日本用的很多
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <limits.h>
#include "itron.h"
#include "config.h"
#include "kernel.h"
#include "target.h"

T_TCB   TCB[TSKID_MAX + 1];     //任务的TCB//
T_TCB   *RDQ[TSKPRI_MAX + 1];   //就绪队列的TCB指针//
T_SEM   SEM[SEMID_MAX + 1];     //信号量//
T_MBX   MBX[MBXID_MAX + 1];     //邮箱//
T_TIM   TIM;                    //系统时间//

T_TCB   *RUNTCB;                //正在运行任务的TCB指针//
INT     *USP;                   //指向任务堆栈指针的指针//
INT     DELAY;                  //是否处在调度器延时状态//
INT     INEST;                  //中断嵌套次数//
INT     SYSSTAT;                //系统状态(调度器加锁,CPU加锁...)//
INT     UIPL;                   //中断允许级别//


void _dly_tsk(DLYTIME dlytim)
{
	//在中断处理和分发器禁止状态使用该系统调用是无效的//
    if (INEST>0 || SYSSTAT >= TSS_DDSP)
    {
        *USP = E_CTX;   //返回系统调用无效//

        return;
    }

    //延时时间小于最小延时时间则返回参数错误//
    if (dlytim < TMO_POL)
    {
        *USP = E_PAR;   //参数错误//

        return;
    }

    //延时时间等于最小延时时间则正常返回//
    if (dlytim == TMO_POL)
    {
        *USP = E_OK;    //正常返回//

        return;
    }

    RUNTCB->tmout = TIM.time + dlytim;		//设定唤醒的时间//
    RUNTCB->tskstat = TTS_WAI;				//将当前任务状态改为等待状态//
    RUNTCB->tskwait = TTW_DLY;				//等待模式为Delay//

    del_que(&RDQ[RUNTCB->tskpri], RUNTCB);  //将任务TCB从Ready队列中删除//
    add_que(&(TIM.head), RUNTCB);   //将任务TCB添加到邮箱等待队列中//

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

//系统定时器处理//
void timer(void)
{
    TIM.time ++;    //系统定时器计数器//

    //如果有等待的任务则判断是否到时//
    if (TIM.head != NULL)
    {
        T_TCB *tcb = TIM.head;
        T_TCB *nexttcb = TIM.head;
        T_TCB *endtcb = tcb->prev;
        do
        {
            tcb = nexttcb;
            nexttcb = tcb->next;
            //如果时间到则唤醒任务//
            if (tcb->tmout == TIM.time)
            {
                tcb->tskstat = TTS_RDY;     //任务状态设为就绪状态//
                del_que(&(TIM.head), tcb);  //将任务TCB从等待队列中删除//
                add_que(&RDQ[tcb->tskpri], tcb);    //将任务TCB添加到Ready队列中//
                *(tcb->sp) = E_OK;  //等待任务的返回值为正常返回//
                DELAY = SET;    //设置为分发器延时状态//
            }
        }while (tcb != endtcb);
    }
}

//从邮箱中接收邮件//
void _rcv_msg(void **ppk_msg, ID mbxid)
{
    T_MBX *mbx;

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

        return;
    }
    //超过邮箱ID的最大值则返回邮箱ID不存在//
    if (mbxid > MBXID_MAX)
    {
        *USP = E_NOEXS; //邮箱ID不存在//

        return;
    }

    mbx = &MBX[mbxid];  //根据邮箱ID获取邮箱//
    //邮件计数器值大于0则获取邮件
    if (mbx->msgcnt > 0)
    {
        *ppk_msg = *(mbx->msghead); //获取邮件//
        //将邮件从邮件对列中删除//
        if (++(mbx->msghead) >= (msgq_tbl[mbxid]+msgsiz_tbl[mbxid]))
        {
            mbx->msghead = msgq_tbl[mbxid];
        }
        mbx->msgcnt--;  //邮件计数器递减//
        *USP = E_OK;    //正常返回//

        return;
    }
    else
    {
        RUNTCB->arg = ppk_msg;
        RUNTCB->tskstat = TTS_WAI;  //任务状态设置为等待状态//
        RUNTCB->tskwait = TTW_MBX;  //等待方式为等待邮件//
        del_que(&RDQ[RUNTCB->tskpri], RUNTCB);  //将任务TCB从Ready队列中删除//
        add_que(&(mbx->head), RUNTCB);  //将任务TCB添加到邮箱等待队列中//
        dispatch(); //激活分发器//

        return;
    }
}

//发送邮件//
void _snd_msg(ID mbxid, void *pk_msg)
{
    T_MBX *mbx;

    //超过邮箱ID的最大值则返回邮箱ID不存在//
    if (mbxid >MBXID_MAX)
    {
        *USP = E_NOEXS; //邮箱ID不存在//

        return;
    }
    mbx = &MBX[mbxid];  //根据邮箱ID获取邮箱//
    //如果没有任务在等待邮箱,则将邮件加入邮件队列//
    if (mbx->head == NULL)
    {
        //如果邮件计数器大于邮箱邮件最大值则发生溢出//
        if (mbx->msgcnt >= msgsiz_tbl[mbxid])
        {
            *USP = E_QOVR;  //邮箱计数器溢出//

            return;
        }
        else
        {
            *(mbx->msgtail) = pk_msg;   //将邮件加入邮件队列//
            if (++(mbx->msgtail) >= (msgq_tbl[mbxid]+msgsiz_tbl[mbxid]))
            {
                mbx->msgtail = msgq_tbl[mbxid];
            }
            mbx->msgcnt++;  //邮件计数器递增//
            *USP = E_OK;    //正常返回//

            return;
        }
    }
    else
    {
        T_TCB *tcb = mbx->head; //取得第一个等待邮件的任务//
        *(tcb->arg) = pk_msg;   //邮件传递给任务//
        tcb->tskstat = TTS_RDY; //将任务状态设置为Ready状态//
        del_que(&(mbx->head), tcb); //将任务TCB从等待邮件队列删除//
        add_que(&RDQ[tcb->tskpri], tcb);    //任务TCB添加到Ready队列中//
        *(tcb->sp) = E_OK;  //等待任务继续运行时的返回值为正常返回//
        *USP = E_OK;    //中在运行的任务正常返回//
        dispatch();     //激活分发器//

        return;
    }
}

//中断通知处理中发送邮件//
ER _isnd_msg(ID mbxid, void *pk_msg)
{
    T_MBX *mbx;

    //超过邮箱ID的最大值则返回邮箱ID不存在//
    if (mbxid >MBXID_MAX)
    {
        return E_NOEXS; //邮箱ID不存在//
    }
    mbx = &MBX[mbxid];  //根据邮箱ID获取邮箱//
    //如果没有任务在等待邮箱,则将邮件加入邮件队列//
    if (mbx->head == NULL)
    {
        //如果邮件计数器大于邮箱邮件最大值则发生溢出//
        if (mbx->msgcnt >= msgsiz_tbl[mbxid])
        {
            return E_QOVR;  //邮箱计数器溢出//
        }
        else
        {
            *(mbx->msgtail) = pk_msg;   //将邮件加入邮件队列//
            if (++(mbx->msgtail) >= (msgq_tbl[mbxid]+msgsiz_tbl[mbxid]))
            {
                mbx->msgtail = msgq_tbl[mbxid];
            }
            mbx->msgcnt++;  //邮件计数器递增//

            return E_OK;    //正常返回//
        }
    }
    else    //如果有任务等待邮件则将邮件传递给等待的任务//
    {
        T_TCB *tcb = mbx->head;     //取得第一个等待邮件的任务//
        *(tcb->arg) = pk_msg;       //邮件传递给任务//
        tcb->tskstat = TTS_RDY;     //将任务状态设置为Ready状态//
        del_que(&(mbx->head), tcb); //将任务TCB从等待邮件队列删除//
        add_que(&RDQ[tcb->tskpri], tcb);    //任务TCB添加到Ready队列中//
        *(tcb->sp) = E_OK;  //等待任务继续运行时的返回值为正常返回//
        DELAY = SET;    //设置分发器延时状态//

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

//无等待获取邮件//
ER _prcv_msg(void **ppk_msg, ID mbxid)
{
    T_MBX *mbx;

    //超过邮箱ID的最大值则返回邮箱ID不存在//
    if (mbxid > MBXID_MAX)
    {
        return  E_NOEXS;    //邮箱ID不存在//
    }

    mbx = &MBX[mbxid];
    //邮件计数器值大于0则获取邮件
    if (mbx->msgcnt > 0)
    {
        *ppk_msg = *(mbx->msghead); //获取邮件//
        //将邮件从邮件对列中删除//
        if (++(mbx->msghead) >= (msgq_tbl[mbxid]+msgsiz_tbl[mbxid]))
        {
            mbx->msghead = msgq_tbl[mbxid];
        }
        mbx->msgcnt--;  //邮件计数器递减//

        return E_OK;    //正常返回//
    }
    else
    {
        return E_TMOUT;     //轮询检测失败//
    }
}

//获取信号量//
void _wai_sem(ID semid)
{
    T_SEM *sem;

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

        return;
    }

    //超过信号量的最大值//
    if (semid > SEMID_MAX)
    {
        *USP = E_NOEXS; //信号量ID不存在//

        return;
    }

    sem = &SEM[semid];

    //如果信号量计数器大于0,则获得信号量//
    if (sem->cnt > 0)
    {
        sem->cnt --;    //信号量计数器递减//
        *USP = E_OK;    //正常返回//

        return;
    }
    else    //信号量计数器等于0,进入等待状态//
    {
        RUNTCB->tskstat = TTS_WAI;  //任务状态设置为等待状态//
        RUNTCB->tskwait = TTW_SEM;  //等待方式为等待信号量//
        del_que(&RDQ[RUNTCB->tskpri], RUNTCB);  //将任务TCB从Ready队列中删除//
        add_que(&(sem->head), RUNTCB);  //将任务TCB添加到信号量等待队列中//
        dispatch(); //激活分发器//

        return;
    }
}

//释放信号量//
void _sig_sem(ID semid)
{
    T_SEM *sem;

    //超过信号量的最大值//
    if (semid > SEMID_MAX)
    {
        *USP = E_NOEXS; //信号量ID不存在//

        return;
    }
    sem = &SEM[semid];
    //如果没有任务在等待信号量,信号量计数器的值仅仅是简单地加1//
    if (sem->head == NULL)
    {
        if (sem->cnt < INT_MAX)     //判断信号量计数器是否溢出//
        {
            sem->cnt ++;    //信号量计数器递增//
            *USP = E_OK;    //正常返回//

            return;
        }
        else
        {
            *USP = E_QOVR;  //信号量计数器溢出//

            return;
        }
    }
    else
    {
        T_TCB *tcb = sem->head;     //获得等待信号量的第一个任务的TCB//
        tcb->tskstat = TTS_RDY;     //将状态设置为Ready状态//
        del_que(&(sem->head), tcb);     //从等待信号量队列中删除该TCB//
        add_que(&RDQ[tcb->tskpri], tcb);    //将该TCB添加到Ready对列中//
        *(tcb->sp) = E_OK;  //等待信号量的任务继续运行时的返回值为正常返回//
        *USP = E_OK;    //正在运行的任务为正常返回//
        dispatch();     //激活分发器//

        return;
    }
}

//中断通知中释放信号量//
ER _isig_sem(ID semid)
{
    T_SEM *sem;

    //超过信号量的最大值//
    if (semid > SEMID_MAX)
    {
        return E_NOEXS; //信号量ID不存在//
    }

    sem = &SEM[semid];

    //如果没有任务在等待信号量,信号量计数器的值仅仅是简单地加1//
    if (sem->head == NULL)
    {
        if (sem->cnt < INT_MAX) //判断信号量计数器是否溢出//
        {
            sem->cnt ++;    //信号量计数器递增//

            return E_OK;    //正常返回//
        }
        else
        {
            return E_QOVR;  //信号量计数器溢出//
        }
    }
    else
    {
        T_TCB *tcb = sem->head;     //获得等待信号量的第一个任务的TCB//
        tcb->tskstat = TTS_RDY;     //将状态设置为Ready状态//
        del_que(&(sem->head), tcb);     //从等待信号量队列中删除该TCB//
        add_que(&RDQ[tcb->tskpri], tcb);    //将该TCB添加到Ready对列中//
        *(tcb->sp) = E_OK;  //等待信号量的任务继续运行时的返回值为正常返回//
        DELAY = SET;    //设置分发器延时状态//

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

//无等待获得信号量//
ER _preq_sem(ID semid)
{
    T_SEM *sem;

    //超过信号量的最大值//
    if (semid > SEMID_MAX)
    {
        return  E_NOEXS;    //信号量ID不存在//
    }

    sem = &SEM[semid];  //通过ID获得对应的信号量//
    //如果信号量计数器值大于零则获得该信号量,正常返回//
    if (sem->cnt > 0)   
    {
        sem->cnt --;    //信号量计数器值递减//

        return  E_OK;   //正常返回//
    }
    else
    {
        return E_TMOUT; //轮询检测失败//
    }
}

ER _dis_dsp(void)

⌨️ 快捷键说明

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