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

📄 djyos.c

📁 新一代基于事件的嵌入式操作系统dyos在三星的s3c44b0的arm芯片上的完整移植代码
💻 C
📖 第 1 页 / 共 5 页
字号:
//      3、与其他内部函数一样,由调用方保证参数合理性,即u32l_mS>0.
//-----------------------------------------------------------------------------
void __y_addto_delay(uint32_t u32l_mS)
{
    struct  event_script * event;
    uint32_t start;

    pg_event_running->delay_start = y_get_time();   //事件延时开始时间
    pg_event_running->delay_end = pg_event_running->delay_start
                + (u32l_mS + cn_tick_ms -1)/cn_tick_ms;  //延时结束时间

    if(pg_event_delay==NULL)    //延时队列空
    {
        pg_event_running->next = pg_event_running;
        pg_event_running->previous = pg_event_running;
        pg_event_delay=pg_event_running;
    }else
    {
        event = pg_event_delay;
        start=pg_event_running->delay_start;
        do
        {//本循环找到第一个剩余延时时间大于新延时事件的事件.
            //如果1tick=1mS,那么49.7天后将回绕,yos不能提供超过49.7天的延时
            //如果直接比较delay_end,则一个发生回绕而另一个不回绕时,将会出错,
            //-start可以避免回绕时发生错误
            if((event->delay_end - start)
                            <= (pg_event_running->delay_end - start))
                event = event->next;
            else
                break;
        }while(event != pg_event_delay);
        //如果没有找到剩余延时时间比新延时事件长的事件,新事件插入队列尾,
        //而队列尾部就是pg_event_delay的前面,event恰好等于pg_event_delay
        //如果找到剩余延时时间长于新事件的事件,新事件插入该事件前面.
        //所以无论前面循环找到与否,均可使用下列代码
        pg_event_running->next = event;
        pg_event_running->previous = event->previous;
        event->previous->next = pg_event_running;
        event->previous = pg_event_running;
        if(pg_event_delay->delay_end -start > pg_event_running->delay_end-start)
            //新事件延时小于原队列中的最小延时.
            pg_event_delay = pg_event_running;
    }
}

//----清除mark型事件标记-------------------------------------------------------
//功能: 用于mark型事件,一条mark型事件发生后,清除标记前,如果再次发生同类型的
//      事件,只是简单地repeats增量,在清除标记后,再次发生则登记新事件。登记事
//      件时,若前一条事件已经完成,则加入ready队列,并由和mark_unclear指针索引,
//      若前一条事件未完成,则只由mark_unclear指针索引,待前一条事件完成在加入
//      ready队列,以确保mark型事件只有一条在处理。
//参数: 无
//返回: 无
//-----------------------------------------------------------------------------
void y_clear_mark(void)
{
    struct  event_type *pl_evtt;  //被操作的事件的类型指针
    pl_evtt = &tg_evtt_table[pg_event_running->evtt_id];
    pl_evtt->repeats = 0;   //mark标识状态量,一次全处理
    pl_evtt->mark_unclear = NULL;
}

//----闹钟同步-----------------------------------------------------------------
//功能:由正在执行的事件调用,使自己暂停u32l_mS毫秒后继续运行.
//参数:u32l_mS,延迟时间,单位是毫秒,0且允许轮转调度则把事件放到同优先级的
//      最后。非0值将被向上调整为cn_tick_ms的整数倍
//返回:实际延时时间(ticks)数
//备注:延时队列为双向循环链表
//-----------------------------------------------------------------------------
uint32_t y_timer_sync(uint32_t u32l_mS)
{
    struct  event_script * event;
    uint32_t start;

    if( !y_query_sch())
    {   //禁止调度,不能进入闹钟同步状态。
        y_error_login(enum_knl_cant_sched,NULL);
        return 0;
    }
    int_save_asyn_signal();
    //延时量为0的算法:就绪队列中有同优先级的,把本事件放到轮转最后一个,
    //注意:这里不管轮转调度是否允许
    if(u32l_mS == 0)
    {
        if((pg_event_running->prio == pg_event_running->next->prio)
                    && (pg_event_running != pg_event_running->next)   )
        {
            pg_event_running->delay_start = y_get_time();   //设定闹铃的时间
            __y_cut_ready_event(pg_event_running);      //从同步队列取出
            __y_event_ready(pg_event_running);            //放回同步队列尾部
        }else
        {
            int_restore_asyn_signal();
            return 0;   //延时量为0,且不符合轮转条件
        }
    }else
    {
        pg_event_running->delay_start = y_get_time();   //设定闹铃的时间
        pg_event_running->delay_end = pg_event_running->delay_start
                    + (u32l_mS + cn_tick_ms -1)/cn_tick_ms;  //闹铃时间

        __y_cut_ready_event(pg_event_running);

        pg_event_running->last_status.all = pg_event_running->event_status.all;
        pg_event_running->event_status.bit.event_delay=1;
        if(pg_event_delay==NULL)    //闹钟同步队列空
        {
            pg_event_running->next = pg_event_running;
            pg_event_running->previous = pg_event_running;
            pg_event_delay=pg_event_running;
        }else
        {
            event = pg_event_delay;
            start=pg_event_running->delay_start;
            do
            {//本循环找到第一个闹铃时间晚于新事件的事件.
                //如果1tick=1mS,那么49.7天后将回绕,djyos不能提供超过49.7天的延时
                //如果直接比较delay_end,则一个发生回绕而另一个不回绕时,将会出错,
                //-start可以避免回绕时发生错误
                if((event->delay_end - start)
                                <= (pg_event_running->delay_end - start))
                    event = event->next;
                else
                    break;
            }while(event != pg_event_delay);
            //下面把新事件插入前述找到的事件前面,如没有找到,则event将等于
            //pg_event_delay,因是双向循环队列,g_event_delay前面也就刚好是队列尾。
            pg_event_running->next = event;
            pg_event_running->previous = event->previous;
            event->previous->next = pg_event_running;
            event->previous = pg_event_running;
            if(pg_event_delay->delay_end -start
                    >pg_event_running->delay_end-start)
                //新事件延时小于原队列中的最小延时.
                pg_event_delay = pg_event_running;
        }
    }
    int_restore_asyn_signal();
    return (y_get_time() - pg_event_running->delay_start)*cn_tick_ms;
}

//----同步事件----------------------------------------------------------------
//功能: 把正在运行的事件加入到指定事件的同步队列中去,然后重新调度
//参数: event_id,目标事件id号
//      timeout,超时设置,单位是毫秒,cn_timeout_forever=无限等待,0则立即按
//      超时返回。非0值将被向上调整为cn_tick_ms的整数倍
//返回: cn_sync_success=同步条件成立返回,
//      cn_sync_timeout=超时返回,
//      cn_sync_error=出错,
//----------------------------------------------------------------------------
uint32_t y_event_sync(uint16_t event_id,uint32_t timeout)
{
    struct  event_script * pl_ecb;
    pl_ecb = &tg_event_table[event_id];

    if(y_query_sch() == false)  //不能在禁止调度的情况下执行同步操作
        return cn_sync_error;
    if(timeout == 0)
        return cn_sync_timeout;
    int_save_asyn_signal();
    if(pl_ecb->previous == (struct event_script *)&pg_event_free)
    {//目标事件是空闲事件
        int_restore_asyn_signal();
        return cn_sync_error;
    }
    __y_cut_ready_event(pg_event_running);
    pg_event_running->next = NULL;
    pg_event_running->previous = NULL;

    //以下把pg_event_running加入到目标事件的同步队列中

    pg_event_running->sync_head = &pl_ecb->sync;
    if(pl_ecb->sync != NULL)
    {//被同步事件的同步队列不是空的
        pg_event_running->multi_next = pl_ecb->sync;
        pg_event_running->multi_previous = pl_ecb->sync->multi_previous;
        pl_ecb->sync->multi_previous->multi_next = pg_event_running;
        pl_ecb->sync->multi_previous = pg_event_running;
    }else
    {//被同步事件的同步队列是空的
        pl_ecb->sync = pg_event_running;
        pg_event_running->multi_next = pg_event_running;
        pg_event_running->multi_previous = pg_event_running;
    }

    pg_event_running->last_status.all = pg_event_running->event_status.all;
    pg_event_running->event_status.bit.event_sync = 1;
    if(timeout != cn_timeout_forever)
    {
        pg_event_running->event_status.bit.wait_overtime = 1;
        __y_addto_delay((timeout + cn_tick_ms -1)/cn_tick_ms);
    }
    int_restore_asyn_signal();  //恢复中断会引发重新调度

    int_save_asyn_signal();
    //检查从哪里返回,是超时还是同步事件完成。
    if(pg_event_running->event_status.bit.event_sync)
    {//说明同步条件未到,从超时返回,应从目标事件的同步队列中取出事件。
     //此时,被同步的事件肯定还没有完成。
        pg_event_running->event_status.bit.event_sync = 0;
        int_restore_asyn_signal();
        return cn_sync_timeout;
    }else
    {
        int_restore_asyn_signal();
        return cn_sync_success;
    }
}

//----事件类型完成同步----------------------------------------------------------
//功能: 把正在运行的事件加入到指定事件类型的前同步队列中去,然后重新调度。完成
//      同步以目标事件类型的完成次数为同步条件。
//参数: evtt_id,目标事件类型号
//      done_times,完成次数,0表示待最后一条该类型事件完成.
//      timeout,超时设置,单位是毫秒,cn_timeout_forever=无限等待,0则立即按
//      超时返回。非0值将被向上调整为cn_tick_ms的整数倍
//返回: cn_sync_success=同步条件成立返回,
//      cn_sync_timeout=超时返回,
//      cn_sync_error=出错,
//      本函数必须联系共享文档的相关章节才容易读懂,注释难于解释那么清楚的。
//----------------------------------------------------------------------------
uint32_t y_evtt_done_sync(uint16_t evtt_id,uint16_t done_times,uint32_t timeout)
{
    struct  event_type *evtt;
    struct event_script *pl_ecb;
    evtt = &tg_evtt_table[evtt_id];
    if(y_query_sch() == false)  //不能在禁止调度的情况下执行同步操作
        return cn_sync_error;
    if(timeout == 0)
        return cn_sync_timeout;
    int_save_asyn_signal();
    if(evtt->property.registered == false)
    {//该事件类型是无效事件类型
        int_restore_asyn_signal();
        return cn_sync_error;
    }
    __y_cut_ready_event(pg_event_running);
    pg_event_running->next = NULL;
    pg_event_running->previous = NULL;
    pg_event_running->sync_counter = done_times;

    //以下把pg_event_running加入到目标事件的同步队列中
    pg_event_running->sync_head = &evtt->done_sync;
    if(evtt->done_sync != NULL)
    {//被同步事件类型的同步队列不是空的
        pl_ecb = evtt->done_sync;
        do
        {//本循环找到第一个剩余完成次数不小于新事件的事件.
            if(pl_ecb->sync_counter < done_times)
                pl_ecb = pl_ecb->multi_next;
            else
                break;
        }while(pl_ecb != evtt->done_sync);
        //下面把新事件(pg_event_running)插入到队列中
        pg_event_running->multi_next = pl_ecb;
        pg_event_running->multi_previous = pl_ecb->multi_previous;
        pl_ecb->multi_previous->multi_next = pg_event_running;
        pl_ecb->multi_previous = pg_event_running;
        if(evtt->done_sync->sync_counter > done_times)
            evtt->done_sync = pg_event_running;
    }else
    {//被同步事件类型的同步队列是空的
        evtt->done_sync = pg_event_running;
        pg_event_running->multi_next = pg_event_running;
        pg_event_running->multi_previous = pg_event_running;
    }

    pg_event_running->last_status.all = pg_event_running->event_status.all;
    pg_event_running->event_status.bit.evtt_done_sync = 1;
    if(timeout != cn_timeout_forever)
    {
        pg_event_running->event_status.bit.wait_overtime = 1;
        __y_addto_delay((timeout + cn_tick_ms -1)/cn_tick_ms);
    }
    int_restore_asyn_signal();  //恢复调度会引发事件切换

    int_save_asyn_signal();
    //检查从哪里返回,是超时还是同步事件完成。
    if(pg_event_running->event_status.bit.evtt_done_sync)
    {//说明同步条件未到,从超时返回,应从目标事件的同步队列中取出事件。
     //此时,被同步的事件肯定还没有完成。

⌨️ 快捷键说明

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