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

📄 djyos.c

📁 新一代基于事件的嵌入式操作系统dyos在三星的s3c44b0的arm芯片上的完整移植代码
💻 C
📖 第 1 页 / 共 5 页
字号:
//----------------------------------------------------
//Copyright (C), 2004-2009,  lst.
//版权所有 (C), 2004-2009,   lst.
//所属模块:核心模块
//作者:lst
//版本:V1.0.0
//文件描述:事件类型、事件管理以及多事件调度相关的代码全在这里了。
//其他说明:
//修订历史:
//    2. ...
//    1. 日期:
//       作者:
//       新版本号:
//       修改说明:
//------------------------------------------------------
#include "inc_os.h"
#include "gpio.h"
#include <string.h>

struct process_vm *pg_my_process;
//为cn_events_limit条事件控制块分配内存
static struct  event_script tg_event_table[cn_events_limit];
//为cn_evtts_limit个事件类型控制块分配内存
static struct event_type tg_evtt_table[cn_evtts_limit];
static struct  event_script  *pg_event_free; //空闲链表头,不排序
//轮转调度时间片,0表示禁止轮转调度,默认1,RRS = "round robin scheduling"缩写。
static uint32_t  u32g_RRS_slice = 1;

struct  event_script  *pg_event_ready;      //就绪队列头
struct  event_script  *pg_event_running;    //当前正在执行的事件
static struct  event_script  *pg_event_delay;      //闹钟同步队列表头
static uint32_t  u32g_running_start;        //当前运行中事件的开始执行时间.
static uint32_t  u32g_os_ticks;             //操作系统运行ticks数
volatile static uint32_t    u32g_delay_10uS=40;
uint32_t u32g_ns_of_u32for; //for(i=j;i>0;i--);语句,i和j都是u32型,每循环纳秒数
uint32_t u32g_ns_of_u16for; //for(i=j;i>0;i--);语句,i和j都是u16型,每循环纳秒数
uint32_t u32g_ns_of_u8for;  //for(i=j;i>0;i--);语句,i和j都是u8型,每循环纳秒数

//----设置指令延时常数---------------------------------------------------------
//功能: 设置指令延时常数,使y_delay_10us函数的延时常数=10uS.
//      调用此函数后,延时常数准确==10uS,不管用何种编译器和优化级别
//      44b0x打开cache的情况下,延时 u32g_delay_10uS 约49,误差约2%
//参数:无
//返回: 无
//备注: 本函数移植关键
//-----------------------------------------------------------------------------
void __y_set_delay(void)
{
    uint32_t counter,u32_fors=64000,i;
    uint16_t u16_fors=64000;
    uint8_t  u8_fors=250;
    uint32_t u32_u8 = 128;
    volatile uint32_t u32loops;
    volatile uint16_t u16loops;
    volatile uint8_t  u8loops;

    timer_set_clk_source(5,0);  //timer5的时钟源=cn_timer_clk/2,最高时钟。
    timer_set_precale(2,0);             //预分频数为1(不预分频)
    timer_set_type(5,1);                //自动加载连续工作
    timer_set_counter(5,(uint16_t)(2*cn_timer_clk/2000));  //2000uS,减计数
    timer_reload(5);
    timer_start(5);

    do  //测量32位变量循环时间(nS)
       {
           int_echo_line(cn_irq_line_timer5);      //清中断标志
           while( ! int_query_line(cn_irq_line_timer5));//直到发生中断,重新计数
           for(u32loops=u32_fors;u32loops>0;u32loops--); //循环u32_fors次
           counter = timer_read(5);                  //读取循环u32_fors次所需时间
           u32_fors >>= 1;                         //u32_fors减半
       }while(int_query_line(cn_irq_line_timer5));//中断已发生,说明u32_fors次循环
                                  //大于2mS,u32_fors减半,再次循环,直到中断不发生
       counter = 2*cn_timer_clk/2000 - counter;    //取实际脉冲数。
       u32g_ns_of_u32for = counter*2000/(2*cn_timer_clk/2000)*1000 /(u32_fors<<1);
       do  //测量16位变量循环时间(nS)
       {
           int_echo_line(cn_irq_line_timer5);      //清中断标志
           while( ! int_query_line(cn_irq_line_timer5));//直到发生中断,重新计数
           for(u16loops=u16_fors;u16loops>0;u16loops--); //循环u16_fors次
           counter = timer_read(3);                  //读取循环u32_fors次所需时间
           u16_fors >>= 1;                           //u16_fors减半
       }while(int_query_line(cn_irq_line_timer5));//中断已发生,说明u32_fors次循环
                                 //大于2mS,u32_fors减半,再次循环,直到中断不发生
       counter = 2*cn_timer_clk/2000 - counter;    //取实际脉冲数。
       u32g_ns_of_u16for = counter*2000/(2*cn_timer_clk/2000)*1000 /(u16_fors<<1);
                
       do  //测量8位变量循环时间(nS)
       {
           int_echo_line(cn_irq_line_timer5);      //清中断标志
           while( ! int_query_line(cn_irq_line_timer5));//直到发生中断,重新计数
           for(i = (uint8_t)u32_u8; i > 0; i--)
               for(u8loops=u8_fors;u8loops>0;u8loops--); //循环u8_fors次
           counter = timer_read(3);                      //读取循环k次所需时间
           u32_u8 >>= 1;                           //u32_u8减半
       }while(int_query_line(cn_irq_line_timer5));//中断已发生,说明u32_fors次循环
                                 //大于2mS,u32_fors减半,再次循环,直到中断不发生
       counter = 2*cn_timer_clk/2000 - counter;    //取实际脉冲数。
       u32g_ns_of_u8for = counter*2000/(2*cn_timer_clk/2000)*1000 
                                   /((u8_fors+1) * (u32_u8<<1));

       u32g_delay_10uS = 10000/u32g_ns_of_u32for;
}

//----10微秒级延时-------------------------------------------------------------
//功能:利用循环实现的微秒分辨率延时,调用__y_set_delay函数后才能使用本函数,
//      否则在不同优化级别和不同编译器下,延时数不同.
//参数:time,延时时间,单位为10微秒,最多655毫秒。
//返回:无
//注意:不建议使用此函数做太长延时,长延时请使用函数 y_timer_sync,
//-----------------------------------------------------------------------------
void y_delay_10us(volatile uint16_t time)
{
    volatile uint32_t i;
    for(; time > 0; time--)
        for(i = u32g_delay_10uS; i >0 ; i--);
}

//----实时串长度---------------------------------------------------------------
//功能: strlen函数的执行时间不可控,不宜在实时环境中使用。
//参数: s,被测字符串
//      over,最长检测长度,over=0则不限长度,与strlen函数无异。
//返回: 串长度,在over范围内没有检测到串结束则返回-1
//-----------------------------------------------------------------------------
sint32_t rtstrlen(const char *s,uint32_t over)
{
    uint32_t len;
    if(over == 0)
        return strlen(s);
    else
    {
        for(len = 0; len < over; len++)
        {
            if(s[len] =='\0')
            {
                return len;
                break;
            }
        }
        return cn_limit_uint32;
    }
}

//----读取当前ticks-------------------------------------------------------------
//功能:读取操作系统时钟
//      u32g_os_ticks 为32位无符号变量,ARM是32位机,可以直接读取,非32位系统中
//      读取 u32g_os_ticks 需要超过1个周期,因此访问SysTimer时需要关中断。
//参数:无
//返回:当前时钟
//-----------------------------------------------------------------------------
uint32_t y_get_time(void)
{
    uint32_t time;
#if (32 > cn_cpu_bits)
    //若处理器字长不是32位,需要多个周期才能读取os_ticks,该过程不能被时钟中断打断.
    int_save_line(cn_irq_line_timer5);
#endif

    time = u32g_os_ticks;

#if (32 > cn_cpu_bits)
    //若处理器字长不是32位,需要多个周期才能读取os_ticks,该过程不能被时钟中断打断.
    int_restore_line(cn_irq_line_timer5);
#endif
    return time;
}

//----读取精密时间-----------------------------------------------------------
//功能:读取操作系统精密时钟,时间单位在配置文件中设置,依硬件不同而不同,一般设为
//      tick的百分之一或者千分之一,44b0x中设为千分之一.结果是从上次ticks改变到
//      现在的时间间隔/
//参数:无
//返回:时间值
//备注: 本函数是移植关键函数.
//-----------------------------------------------------------------------------
uint32_t y_get_fine_time(void)
{
    return 1000-pg_timer_reg->TCNTO5;
}

//以下为多任务管理函数

//----tick中断-----------------------------------------------------------------
//功能:为操作系统产生时钟源,并比较理闹钟同步队列中的事件,如果有闹铃时间到的
//      事件,就把他们激活的ready队列中。如果时间片轮转调度被允许,还要看是否要
//      执行轮转。ticks被设置为异步信号。
//参数:line,ticks中断的中断线号,实际上不用。
//返回:无
//-----------------------------------------------------------------------------
uint32_t  __y_isr_tick(ufast_t line)
{
    struct  event_script *pl_ecb,*pl_ecbp,*pl_ecbn;
    u32g_os_ticks++;    //系统时钟,4294967296次后溢出,将环绕
    if(pg_event_delay != NULL)
    {
        pl_ecb = pg_event_delay;
        while(1)
        {
            if(pl_ecb->delay_end == u32g_os_ticks)
            {
                if(pl_ecb->sync_head != NULL)   //事件在某同步队列中
                {
                    if(*pl_ecb->sync_head == pl_ecb)//本事件是该同步队列的首事件
                    {
                        if(pl_ecb->multi_next == pl_ecb)    //队列中只有一个事件
                        {
                            *pl_ecb->sync_head = NULL;
                            pl_ecb->multi_next = NULL;
                            pl_ecb->multi_previous = NULL;
                        }else                   //队列中有多个事件
                        {
                            //头指针指向下一个事件
                            *pl_ecb->sync_head = pl_ecb->multi_next;
                            pl_ecb->multi_previous->multi_next
                                                = pl_ecb->multi_next;
                            pl_ecb->multi_next->multi_previous
                                                = pl_ecb->multi_previous;
                        }
                    }else           //本事件不是首事件
                    {
                        pl_ecb->multi_previous->multi_next
                                            = pl_ecb->multi_next;
                        pl_ecb->multi_next->multi_previous
                                            = pl_ecb->multi_previous;
                    }
                    pl_ecb->sync_head = NULL;   //事件头指针置空
                }
                if(pl_ecb->next == pl_ecb)      //这是闹钟同步队列最后一个结点.
                {
                    pg_event_delay = NULL;
                    pl_ecb->last_status.all = pl_ecb->event_status.all;
                    pl_ecb->event_status.bit.event_delay = 0;
                    pl_ecb->event_status.bit.wait_overtime = 0;
                    __y_event_ready(pl_ecb);
                    break;
                }else
                {
                    pg_event_delay = pl_ecb->next;
                    pl_ecb->next->previous = pl_ecb->previous;
                    pl_ecb->previous->next = pl_ecb->next;
                    pl_ecb->last_status.all = pl_ecb->event_status.all;
                    pl_ecb->event_status.bit.event_delay = 0;
                    pl_ecb->event_status.bit.wait_overtime = 0;
                    __y_event_ready(pl_ecb);
                    pl_ecb = pg_event_delay;
                }
            }else
                break;
        }
    }
    pg_event_running->consumed_time++;
    //下面处理时间片轮转调度.
    //因在开异步信号(允许调度)才可能进入__y_isr_tick,即使因闹钟响导致新事件加入,
    //也不影响pg_event_running是同优先级首事件的性质,但可能不等于pg_event_ready
    if(u32g_RRS_slice != 0)      //允许轮转调度
    {
        if( (pg_event_running->prio == pg_event_running->next->prio)
                    &&(pg_event_running != pg_event_running->next) )
        {//该优先级有多个事件,看轮转时间是否到
            if(pg_event_running->consumed_time%u32g_RRS_slice == 0) //时间片用完
            {
                //先处理首事件链表
                pl_ecb = pg_event_running->next;
                pl_ecbn = pg_event_running->multi_next;
                pl_ecbp = pg_event_running->multi_previous;
                if(pg_event_ready == pg_event_running)
                    pg_event_ready = pl_ecb;
                pl_ecbp->multi_next = pl_ecb;
                pl_ecb->multi_previous = pl_ecbp;
                pl_ecbn->multi_previous = pl_ecb;
                pl_ecb->multi_next = pl_ecbn;
                pg_event_running->multi_next = NULL;
                pg_event_running->multi_previous = NULL;

                //再处理就绪链表
                pl_ecbn = pg_event_ready->multi_next;
                pl_ecbp = pg_event_running->previous;
                pl_ecbp->next = pg_event_ready;
                pg_event_ready->previous = pl_ecbp;
                pg_event_running->previous = pl_ecbn->previous;
                pg_event_running->next = pl_ecbn;
                pl_ecbn->previous->next = pg_event_running;

⌨️ 快捷键说明

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