搜索
bottom↓
回复: 2

抢占式内核改版!!大家来看看,信号量部分需要改进,看看能不能添加邮箱部分。。编译器AVRs

[复制链接]

出0入0汤圆

发表于 2009-4-24 14:50:02 | 显示全部楼层 |阅读模式
/*
*********************************************************************************************************
*                                      The Real-Time Kernel For AVR
*                                             CORE FUNCTIONS
*
*
* File    : AVR_RTOS.C
* By      :
* Version : V1.0
*********************************************************************************************************
*/
#include "AVR_RTOS.h"

/********************************************************************************************************
函数名称:        OSTaskCreate
函数原型:        void OSTaskCreate(void (*Task)(void),INT8U *Stack,INT8U prio)
函数功能:        用户函数,建立任务
入口参数:        *Task:任务函数地址;*Stack:任务堆栈指针;prio:任务优先级
*********************************************************************************************************/
void OSTaskCreate(void (*Task)(void),INT8U *Stack,INT8U prio)
{
        INT8U i;
        *Stack--=(INT16U)Task;                                    /*将任务的地址低位压入堆栈             */
        *Stack--=(INT16U)Task>>8;                             /*将任务的地址高位压入堆栈                   */

        *Stack--=0x00;                                                        /*R1 __zero_reg__                                       */
        *Stack--=0x00;                                                        /*R0 __tmp_reg__                                   */
        *Stack--=0x80;                                                        /*SREG 在任务中,开启全局中断               */
        for(i=0;i<14;i++)
    *Stack--=i;/*在 avr-libc 中的 FAQ中的 What registers are used by the C compiler?
        描述了寄存器的作用        */
        TCB[prio].OSTaskStackTop = (INT16U)Stack;/*将人工堆栈的栈顶,保存到堆栈的数组中*/
    TCB[prio].OSWaitTick = 0;                                 /* 初始化任务延时                           */
        OSRdyTbl |= 0x01<<prio;                               /*任务就绪表已经准备好                                 */
}

/*********************************************************************************************************
函数名称:        OSInit
函数原型:        void OInit (void)
函数功能:        用户函数,初始化任务时钟和一些系统全局变量,建立空闲任务       
*********************************************************************************************************/
void OSInit (void)
{
    #if OS_TIME_GET_SET_EN > 0  
    OSTime=0;                 /*系统时间清零       */
    #endif
        OSRdyTbl=0;               /*任务就绪表清零     */
        OSIntNesting=0;                  /*中断嵌套计数器清零 */
        OSTaskCreate(IdleTask,&IdleStack[IDLE_STACK_SIZE-1],IDLE_TASK_PRIO); /*建立IDLE任务*/
}

/*********************************************************************************************************
函数名称:        OSStart
函数原型:        void OSStart(void)
函数功能:        用户函数,开始任务调度,从空闲任务开始运行        
*********************************************************************************************************/
void OSStart(void)
{
        OSPrioCur = OS_TASKS;
        OSPrioHighRdy = OS_TASKS;
        SP=TCB[OS_TASKS].OSTaskStackTop+17;
        __asm__ __volatile__("reti"       "\n\t");
}

/*********************************************************************************************************
函数名称:        OS_TASK_SW
函数原型:        void OS_TASK_SW(void)
函数功能:        进行任务调度
有关说明:        内部函数,中断和任务都可以调用这个任务调度函数       
*********************************************************************************************************/
void OS_TASK_SW(void)
{
        __asm__ __volatile__("LDI  R16,0x01             \n\t");
              /*清除中断要求任务切换的标志位,设置正在任务切换标志位                            */
        __asm__ __volatile__("SEI                       \n\t");
              /*开中断,因为如果因中断在任务调度中进行,要重新进行调度时,已经关中断            */
              /*根据中断时保存寄存器的次序入栈,模拟一次中断后,入栈的情况              */
        __asm__ __volatile__("PUSH __zero_reg__         \n\t");        /*R1                                         */
        __asm__ __volatile__("PUSH __tmp_reg__          \n\t");        /*R0                                        */
        __asm__ __volatile__("IN   __tmp_reg__,__SREG__ \n\t");        /*保存状态寄存器SREG        */
        __asm__ __volatile__("PUSH __tmp_reg__          \n\t");
        __asm__ __volatile__("CLR  __zero_reg__         \n\t");        /*R0重新清零                        */
        __asm__ __volatile__("PUSH R18                  \n\t");
        __asm__ __volatile__("PUSH R19                  \n\t");
        __asm__ __volatile__("PUSH R20                  \n\t");
        __asm__ __volatile__("PUSH R21                  \n\t");
        __asm__ __volatile__("PUSH R22                  \n\t");
        __asm__ __volatile__("PUSH R23                  \n\t");
        __asm__ __volatile__("PUSH R24                  \n\t");
        __asm__ __volatile__("PUSH R25                  \n\t");
        __asm__ __volatile__("PUSH R26                  \n\t");
        __asm__ __volatile__("PUSH R27                  \n\t");
        __asm__ __volatile__("PUSH R30                  \n\t");  
        __asm__ __volatile__("PUSH R31                  \n\t");       
        __asm__ __volatile__("Int_OSSched:              \n\t");        /*当中断要求调度,直接进入这里                */
        __asm__ __volatile__("SEI                       \n\t");
        /*开中断,因为如果因中断在任务调度中进行,已经关中断*/
        __asm__ __volatile__("PUSH R28                  \n\t");        /*R28与R29用于建立在堆栈上的指针        */
        __asm__ __volatile__("PUSH R29                  \n\t");        /*入栈完成                                                        */       
        TCB[OSPrioCur].OSTaskStackTop=SP;                                        /*将正在运行的任务的堆栈底保存                    */       
        OSPrioCur = OSPrioHighRdy ;                                                        /*运行当前就绪表中的最高优先级任务            */       
        cli();                                                                                                /*保护堆栈转换,属于临界代码,要保护            */
        SP=TCB[OSPrioCur].OSTaskStackTop;
        sei();       
        /*根据中断时的出栈次序*/
        __asm__ __volatile__("POP  R29                  \n\t");
        __asm__ __volatile__("POP  R28                  \n\t");
        __asm__ __volatile__("POP  R31                  \n\t");
        __asm__ __volatile__("POP  R30                  \n\t");
        __asm__ __volatile__("POP  R27                  \n\t");
        __asm__ __volatile__("POP  R26                  \n\t");
        __asm__ __volatile__("POP  R25                  \n\t");
        __asm__ __volatile__("POP  R24                  \n\t");
        __asm__ __volatile__("POP  R23                  \n\t");
        __asm__ __volatile__("POP  R22                  \n\t");
        __asm__ __volatile__("POP  R21                  \n\t");
        __asm__ __volatile__("POP  R20                  \n\t");
        __asm__ __volatile__("POP  R19                  \n\t");
        __asm__ __volatile__("POP  R18                  \n\t");
        __asm__ __volatile__("POP  __tmp_reg__          \n\t");                /*SERG 出栈并恢复        */
        __asm__ __volatile__("OUT  __SREG__,__tmp_reg__ \n\t");
        __asm__ __volatile__("POP  __tmp_reg__          \n\t");                /*R0 出栈                        */
        __asm__ __volatile__("POP  __zero_reg__         \n\t");                /*R1 出栈                        */
        /*中断时出栈完成*/
        __asm__ __volatile__("CLI                       \n\t");                /*关中断                        */
        __asm__ __volatile__("SBRC R16,1                \n\t");
        /*        SBRC当寄存器位为0则跳过下一条指令
                检查系统正在进行任务调度时,是否有中断发生并进行要求任务调度,
                如果中断要求调度则重新进行一次任务调度。
                0x02是中断要求调度的标志位        */
        __asm__ __volatile__("RJMP OSSched              \n\t");                /*重新调度                        */
        __asm__ __volatile__("LDI  R16,0x00             \n\t");
        /*        清除中断要求任务切换的标志位,清除正在任务切换标志位,
            表示任务切换已经完成。        */
        __asm__ __volatile__("RETI                      \n\t");     /*返回并开中断                */
}

/********************************************************************************************************
函数名称:        IntSwitch
函数原型:        void IntSwitch(void)
函数功能:        从中断退出并进行调度
有关说明:        当无中断嵌套并且中断中要求进行任务切换时才进行任务切换。
                        因为从中断到运行下一个任务共调用了两次子函数,所以要弹出四个入栈的PC
*********************************************************************************************************/
void IntSwitch(void)
{
        if((OSCoreState == 0x02) && (OSIntNesting == 0))
        {
                /*进入中断时,已经保存了SREG和R0,R1,R18~R27,R30,R31,
                 所以没有必要再保存一次了,直接跳转到Int_OSSched进行下一个调度*/
                __asm__ __volatile__("POP  R31                  \n\t");        /*去除因调用子程序而入栈的PC*/
                __asm__ __volatile__("POP  R31                  \n\t");
                __asm__ __volatile__("POP  R31                  \n\t");
                __asm__ __volatile__("POP  R31                  \n\t");
                __asm__ __volatile__("LDI  R16,0x01             \n\t");
                /*        清除中断要求任务切换的标志位,设置正在任务切换标志位 */
                __asm__ __volatile__("RJMP Int_OSSched          \n\t");        /*重新调度                                        */
        }
}

/********************************************************************************************************
函数名称:        OSSched
函数原型:        void OSSched(void)
函数功能:        任务调度器,进行任务调度
有关说明:        内部函数,只有有更高优先级的任务就绪时才进行一次任务切换,否则不做切换,中断中不可调用此函数       
********************************************************************************************************/
void OSSched (void)
{
    OS_ENTER_CRITICAL();
        if(OSIntNesting == 0)                           /*判断是否由中断调用,是则直接推出    */
     {       
            OSFindPrioHighRdy();                                                /*找出就绪表中优先级最高的任务        */
            if(OSPrioHighRdy != OSPrioCur)                                /*如果不是当前运行的任务,进行任务调度*/
            {
                   OS_TASK_SW();                                                        /*调度任务                            */
             }
      }
    OS_EXIT_CRITICAL();
}

/********************************************************************************************************
函数名称:        OSTaskSuspend
函数原型:        void OSTaskSuspend(INT8U prio)
函数功能:        挂起任务
入口参数:        prio:任务优先级
有关说明:        用户函数,一个任务可以挂起本身也可以挂起其他任务       
*********************************************************************************************************/
void OSTaskSuspend(INT8U prio)
{
        OS_ENTER_CRITICAL();
        TCB[prio].OSWaitTick=0;         
        OSRdyTbl &= ~(0x01<<prio);                /*从任务就绪表上去除标志位        */
        if(OSPrioCur == prio)                        /*当要挂起的任务为当前任务        */
        {
                OS_EXIT_CRITICAL();
                OSSched();                                        /*重新调度                                        */
                return;
        }
        OS_EXIT_CRITICAL();
}

/********************************************************************************************************
函数名称:        OSTaskResume
函数原型:        void OSTaskResume(INT8U prio)
函数功能:        用户函数,恢复任务 可以让被OSTaskSuspend或 OSTimeDly暂停的任务恢复
入口参数:        prio:任务优先级       
*********************************************************************************************************/
void OSTaskResume(INT8U prio)
{
        OS_ENTER_CRITICAL();
        OSRdyTbl |= 0x01<<prio;                        /*从任务就绪表上重置标志位                        */
    TCB[prio].OSWaitTick=0;                        /*将时间计时设为0,到时                                */
        if(OSPrioCur > prio)                        /*当前任务的优先级低于重置位的任务的优先级        */
        {
                OS_EXIT_CRITICAL();
                OSSched();                                        /*重新调度                                                         */
        }
        OS_EXIT_CRITICAL();
}

/********************************************************************************************************
函数名称:        IdleTask(void)
函数原型:        void IdleTask(void)
函数功能:        空闲任务,当其他任务没有就绪的时候运行
有关说明:        系统开始运行的时候是从运行空闲任务开始的。该任务不能删除
这里将timer0放在此处,因为该函数是第一个运行的函数,模仿UCos在第一个任务中启动系统节拍
*********************************************************************************************************/
void IdleTask(void)
{   
    TCN0Init();               /*初始化定时器       */
        OSSched();
        while(1)
        {
            OS_ENTER_CRITICAL();
        OSIdleCtr++;
        OS_EXIT_CRITICAL();       
        }
}

/********************************************************************************************************
函数名称:        OSTimeDly
函数原型:        void OSTimeDly(INT32U ticks)
函数功能:        任务延时
入口参数:        延时的时间,系统节拍的个数
有关说明:        如果延时65535(0xffff)则为无限延时       
*********************************************************************************************************/
void OSTimeDly(INT16U ticks)
{
    if (OSIntNesting>0)
    {                                           /* 判断是否由中断调用        */
        return;
    }
        if(ticks>0)                                     /*当延时有效                 */
        {
            OS_ENTER_CRITICAL();
                OSRdyTbl &= ~(0x01<<OSPrioCur);                /*把任务从就绪表中去掉       */
                TCB[OSPrioCur].OSWaitTick=ticks;
                OS_EXIT_CRITICAL();
                OSSched();                              /*重新调度                         */
         }
}

/********************************************************************************************************
函数名称:        OSTimeDlyHMSM
函数原型:        INT8U OSTimeDlyHMSM (INT8U hours, INT8U minutes, INT8U seconds, INT16U ms)
函数功能:        任务延时
入口参数:        延时的时间,HMSM       
*********************************************************************************************************/
#if OS_TIME_DLY_HMSM_EN > 0
INT8U OSTimeDlyHMSM (INT8U hours, INT8U minutes, INT8U seconds, INT16U ms)
{
    INT32U ticks;
    INT16U loops;
        if (OSIntNesting>0)
    {                                           /* 判断是否由中断调用        */
        return;
    }
    ticks = ((INT32U)hours * 3600L + (INT32U)minutes * 60L + (INT32U)seconds) * OS_TICKS_PER_SEC
          + OS_TICKS_PER_SEC * ((INT32U)ms + 500L / OS_TICKS_PER_SEC) / 1000L;
    loops = (INT16U)(ticks >> 16);               /* Compute the integral number of 65536 tick delays   */
    ticks = ticks & 0xFFFFL;                     /* Obtain  the fractional number of ticks             */
    OSTimeDly((INT16U)ticks);
    while (loops > 0)
        {
        OSTimeDly((INT16U)32768u);
        OSTimeDly((INT16U)32768u);
        loops--;
    }
    return(OS_ERR_NONE);
}
#endif

#if OS_TIME_GET_SET_EN > 0
INT32U  OSTimeGet (void)
{
    INT32U     ticks;
    OS_ENTER_CRITICAL();
    ticks = OSTime;
    OS_EXIT_CRITICAL();
    return (ticks);
}
void  OSTimeSet (INT32U ticks)
{
    OS_ENTER_CRITICAL();
    OSTime = ticks;
    OS_EXIT_CRITICAL();
}
#endif

/********************************************************************************************************
函数名称:        OSSemCreat
函数原型:        void OSSemCreat(INT8U Index,INT8U Type)
函数功能:        初始化信号量
入口参数:        Index:信号量的序号;Type:信号量类型
出口参数:        无
有关说明:        Type为 0 信号量独占型;1 信号量共享型       
*********************************************************************************************************/
void OSSemCreat(INT8U Index,INT8U Type)
{
        Sem[Index].OSEventType=Type;            /*定义信号量类型                   */
        Sem[Index].OSTaskPendTbl=0;                                /*初始化时任务等待列表为空         */
        Sem[Index].OSEventState=0;                                /*信号量无效                       */
}

/*********************************************************************************************************
函数名称:        OSSemPend
函数原型:        INT8U OSSemPend(INT8U Index,INT16U Timeout)
函数功能:        任务等待信号量,挂起
入口参数:        Index:信号量序号;Timeout:等待时间
出口参数:        无
有关说明:        当Timeout==0xffff时,为无限等待,当Timeout==0时不等待也不调度       
**********************************************************************************************************/
INT8U OSSemPend(INT8U Index,INT16U Timeout)
{
    OS_ENTER_CRITICAL();
        if(Sem[Index].OSEventState)                                                        /*信号量有效            */
        {
                if(Sem[Index].OSEventType == 0)                                    /*如果为独占型                */
                {
                   Sem[Index].OSEventState = 0x00;                                /*信号量被独占,不可用  */
                }
        OS_EXIT_CRITICAL();
        }
        else
        {                                                                              /*加入信号的任务等待表  */
               
                              
                   Sem[Index].OSTaskPendTbl |= 0x01<<OSPrioCur;
           if(Timeout!=0)
                   {
                       TCB[OSPrioCur].OSWaitTick = Timeout;                         /*定义等待超时                        */
                       OSRdyTbl &= ~(0x01<<OSPrioCur);                                 /*从任务就绪表中去除        */
                       OS_EXIT_CRITICAL();                                 /*重新调度                                */
                       OSSched();
                    }                                                                 
                   else{return 0;}     /*需要改进*/
        }

        return 1;
}

/********************************************************************************************************
函数名称:        OSSemPost
函数原型:        void OSSemPost(INT8U Index)
函数功能:        发送一个信号量,可以从任务或中断发送,
*                        发送完了信号量之后不进行任务调度,推荐在中断中调用
入口参数:        Index:信号量的序号
出口参数:        无
有关说明:        如果有任务在等待该信号量则将该任务就绪,没有任务等待则仅仅是把信号量置为有效       
*********************************************************************************************************/
void OSSemPost(INT8U Index)
{
    OS_ENTER_CRITICAL();
        if(Sem[Index].OSEventType)                                                        /*当要求的信号量是共享型        */
        {
            Sem[Index].OSEventState=0x01;                                        /*使信号量有效                                */
                OSRdyTbl |=Sem [Index].OSTaskPendTbl;                        /*使在等待该信号的所有任务就绪*/
                Sem[Index].OSTaskPendTbl=0;                                                /*清空所有等待该信号的等待任务*/
                OS_EXIT_CRITICAL();
        OSSched();
        }
        else                                                                                                 /*当要求的信号量为独占型        */
        {
                INT8U i;
                i=0;
                while ((i < OS_TASKS) && (!(Sem[Index].OSTaskPendTbl & (0x01<<i))))
                {
                        i++;/*        找出信号量等待列表中任务优先级最高的任务*/
                }
                if(i < OS_TASKS)                                                                /*如果有任务需要                        */
                {       
                    Sem[Index].OSTaskPendTbl &= ~(0x01<<i);            /*从等待表中去除                        */
                        OSRdyTbl |= 0x01<<i;                                                /*任务就绪                                        */
            if(OSPrioCur<i)        /*如果等待该信号的任务优先级大于当前任务         */
                        {
                            OS_EXIT_CRITICAL();
                OSSched();                              /*重新调度                  */
             }
                         else
                         {
                            OS_EXIT_CRITICAL();
             }
                }
                else                                                                                        /*没有任务等待该信号量                */
                {
                        Sem[Index].OSEventState = 1;                                /*使信号量有效                                */                    OS_EXIT_CRITICAL();
                }
        }
}

/*********************************************************************************************************
函数名称:        OSSemClean
函数原型:        void OSSemClean(INT8U Index)
函数功能:        清除一个信号量,只对共享型的有用。 对于独占型的信号量,在任务占用后,就变得不可以用了
入口参数:        Index:信号量的序号
*********************************************************************************************************/
void OSSemClean(INT8U Index)
{
        Sem[Index].OSEventState = 0;                                /*要求的信号量无效*/
}

/*********************************************************************************************************
函数名称:        OSFindPrioHighRdy
函数原型:        void OSFindPrioHighRdy (void)
函数功能:        找出任务就绪表中的最高优先级的任务
**********************************************************************************************************/
void OSFindPrioHighRdy (void)
{   
        INT8U OSNextTaskPrio;
        OSNextTaskPrio = 0;
        OS_ENTER_CRITICAL();
        while ((OSNextTaskPrio < OS_TASKS) && (!(OSRdyTbl & (0x01<<OSNextTaskPrio))))
        {
                OSNextTaskPrio++;/*        找出信号量等待列表中任务优先级最高的任务        */
        }
        OSPrioHighRdy = OSNextTaskPrio;
    OS_ENTER_CRITICAL();
}

/**********************************************************************************************************
函数名称:        OSIntEnter
函数原型:        void OSIntEnter(void)
函数功能:        进入中断时调用此函数
有关说明:        OSIntEnter()和OSIntExit()要成对出现使用
***********************************************************************************************************/
void OSIntEnter(void)
{
        OS_ENTER_CRITICAL();
        if(OSIntNesting<255)
          {
                OSIntNesting++;                                     /*中断嵌套加1                            */
          }
        OS_ENTER_CRITICAL();
}

/***********************************************************************************************************
函数名称:        OSIntExit
函数原型:        void OSIntExit(void)
函数功能:        从中断中退出时调用此函数,如果中断让更高优先级的任务就绪就进行任务调度
有关说明:        OSIntEnter()和OSIntExit()要成对出现使用       
************************************************************************************************************/
void OSIntExit(void)
{
        OS_ENTER_CRITICAL();
        if(OSIntNesting>0)
        {
                OSIntNesting--;                                     /*中断嵌套减1                              */
        }
        if(OSIntNesting == 0)
        {
                OSFindPrioHighRdy();                                /*找出就绪表中优先级最高的任务*/
                if(OSPrioHighRdy != OSPrioCur)
                {
                        IntSwitch();                                        /*进行任务调度                      */
                        return;
                }
        }
        OS_EXIT_CRITICAL();
}

/************************************************************************************************************
函数名称:        OSTimeTick (void)
函数原型:        OSTimeTick (void)
函数功能:        系统节拍服务函数
有关说明:        用来为需要延时的任务进行任务延时并更新系统时间       
*************************************************************************************************************/
void  OSTimeTick (void)
{
        INT8U i;
        OS_ENTER_CRITICAL();
        for(i=0;i < OS_TASKS;i++)                                /*刷新各任务时钟                                 */
        {
                if(TCB.OSWaitTick && (TCB.OSWaitTick != 0xffff))
                {
                        TCB.OSWaitTick--;
                        if(TCB.OSWaitTick == 0)                /*当任务时钟到时,必须是由定时器减时的才行*/
                        {
                                OSRdyTbl |= (0x01<<i);                /*将延时到的程序就需表置位                      */
                        }
                }
        }
        #if OS_TIME_GET_SET_EN > 0
    OS_ENTER_CRITICAL();                    /* 更新系统时间                          */
    OSTime++;
    OS_EXIT_CRITICAL();
    #endif
        OS_EXIT_CRITICAL();
}

/************************************************************************************************************
函数名称:        OSVersion (void)
函数原型:        OSVersion (void)
函数功能:        获取系统版本号       
************************************************************************************************************/
INT16U  OSVersion (void)
{
    return (OS_VERSION);
}

/************************************************************************************************************
函数名称:        TCN0Init
函数原型:        void TCN0Init(void)
函数功能:        初始化定时器0
有关说明:        定时器T0是任务时钟       
*************************************************************************************************************/
void TCN0Init(void)
{
        TCCR0 = 0;
        TCCR0 = 0x05;                            /* 1024预分频                */
        TIMSK |= (1<<TOIE0);                /* T0溢出中断允许        */
        TCNT0 = 100;                                /* 置计数起始值                */
        //TCNT0 = (256-F_CPU/1024/OS_TICKS_PER_SEC);
}

SIGNAL(SIG_OVERFLOW0)
{
   
        OSIntEnter();
        TCNT0=100;
    //TCNT0 = (256-F_CPU/1024/OS_TICKS_PER_SEC);       
    OSTimeTick();       
        OSIntExit();
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2009-4-24 14:50:24 | 显示全部楼层
/********************************************************************************************************
*                                          The Real-Time Kernel
*                                           Configuration File
* File    : AVR_RTOS.H
* By      :
* Version : V1.00
*********************************************************************************************************/
#ifndef _AVR_RTOS_H_
#define _AVR_RTOS_H_
/*********************************************************************************************************
*                                           INCLUDE HEADER FILES
*********************************************************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
/*********************************************************************************************************
*                                             VERSION NUMBER
*********************************************************************************************************/
#define OS_VERSION          100             /*定义系统版本号           */
/*********************************************************************************************************
*                                             SYSTEM SETTING
*********************************************************************************************************/
#define F_CPU               16000000        /*定义系统晶振频率         */
#define OS_TASKS                        3                                /*设定运行任务的数量1-15   */
#define OS_MAX_SEM                        10                                /*最大信号量的数量                   */
#define OS_TICKS_PER_SEC    100             /*设定每秒节拍数           */
#define OS_TIME_DLY_HMSM_EN 0               /*是否允许小时分秒延时     */
#define OS_TIME_GET_SET_EN  1               /*是否允许系统时间运行     */
#define IDLE_STACK_SIZE            16                                /*空闲任务堆栈空间                      */
#define IDLE_TASK_PRIO      OS_TASKS        /*定义最低优先级任务号     */




#define         INT8U                unsigned char       /*数据格式定义             */
#define         INT8S                signed char
#define         INT16U                unsigned int
#define         INT16S                signed int
#define         INT32U                unsigned long
#define         INT32S            signed long
#define         FP32            float
#define         FP64            double
#define     OS_ERR_NONE   0


register INT8U OSRdyTbl                            asm("r2");                /*任务运行就绪表        */
register INT8U OSPrioCur                        asm("r3");                /*正在运行的任务        */
register INT8U OSIntNesting                    asm("r4");      /*中断嵌套计数器
只有当中断嵌套数为0,并且有中断要求时,才能在退出中断时,进行任务调度   */
register INT8U OSPrioHighRdy                asm("r5");                /*更高优先级的任务        */
register INT8U OSCoreState                        asm("r16");
/*系统核心标志位 ,R16 编译器没有使用
只有大于R15的寄存器才能直接赋值 例LDI R16,0x01
0x01 正在任务 切换  0x02 有中断要求切换*/
volatile INT32U  OSIdleCtr;                         /*Idle计数器        */
INT8U IdleStack[IDLE_STACK_SIZE];                   /*建立IDLE任务堆栈  */
INT32U  OSTime;                                     /*定义系统时间      */

/*进入临界代码区*/
#define                OS_ENTER_CRITICAL()          \
asm volatile(                            \
"IN   __tmp_reg__,__SREG__"    "\n\t"    \
"PUSH __tmp_reg__"             "\n\t"    \
"CLR  __zero_reg__"            "\n\t"    \
"CLI"                          "\n\t"    \
)  \

/*退出临界代码区*/
#define                OS_EXIT_CRITICAL()           \
asm volatile(                            \
"POP  __tmp_reg__"            "\n\t"     \
"OUT  __SREG__,__tmp_reg__"   "\n\t"     \
"CLR  __zero_reg__"           "\n\t"     \
)   \

/*任务控制块数据结构*/
typedef struct TaskCtrBlock
{
        INT16U        OSTaskStackTop;                /*保存任务的堆栈顶                */
        INT16U        OSWaitTick;                        /*任务延时时钟                        */
        INT8U        OSTaskStatus;                /*任务状态                                */
} OS_TCB;

/*信号量数据结构*/
typedef struct SemBlk
{
        INT8U OSEventType;                        /*型号 0,信号量独占型;1信号量共享型     */
        INT8U OSEventState;                        /*状态 0,不可用;1,可用                                     */
        INT8U OSTaskPendTbl;                /*等待信号量的任务列表                                     */
} OS_EVENT;

OS_TCB                TCB[OS_TASKS+1];        /*定义任务控制块,加一是因为有一个空闲任务*/
OS_EVENT         Sem[OS_MAX_SEM];        /*定义信号量控制块                                         */

/*防止被编译器占用 */
register INT8U tempR6  asm("r6");
register INT8U tempR7  asm("r7");
register INT8U tempR8  asm("r8");
register INT8U tempR9  asm("r9");
register INT8U tempR10 asm("r10");
register INT8U tempR11 asm("r11");
register INT8U tempR12 asm("r12");
register INT8U tempR13 asm("r13");
register INT8U tempR14 asm("r14");
register INT8U tempR15 asm("r15");
register INT8U tempR16 asm("r17");

void OSTaskCreate(void (*Task)(void),INT8U *Stack,INT8U prio);
void OSStart(void);
void OS_TASK_SW(void);
void OSSched(void);
void IntSwitch(void);
void OSTaskSuspend(INT8U prio);
void OSTaskResume(INT8U prio);
void OSTimeDly(INT16U ticks);
INT8U OSTimeDlyHMSM (INT8U hours, INT8U minutes, INT8U seconds, INT16U ms);
INT32U  OSTimeGet (void);
void  OSTimeSet (INT32U ticks);
void OSSemCreat(INT8U Index,INT8U Type);
INT8U OSSemPend(INT8U Index,INT16U Timeout);
void OSSemPost(INT8U Index);
void OSSemClean(INT8U Index);
void TCN0Init(void);
void IdleTask(void);
void OSInit(void);
void OSFindPrioHighRdy (void);
void OSIntEnter(void);
void OSIntExit(void);
void OSTimeTick (void);
#endif

出0入0汤圆

 楼主| 发表于 2009-4-24 14:50:37 | 显示全部楼层
/************************************************************************************************************************
*                                                                                test.c
*
*
*
************************************************************************************************************************/
#include "AVR_RTOS.h"

INT8U Stack1[64];
INT8U Stack2[64];
INT8U Stack3[64];
/************************************************************************************************************************
函数名称:        void Task0(void)
函数原型:        void Task0(void)
函数功能:        任务0       
************************************************************************************************************************/
void Task0(void)
{
        DDRC = 0xff;
        PORTC = 0x00;
        OSSemCreat(0,0);
        while(1)
        {
                OSSemPend(0,0xffff);
                PORTC = ~PORTC;
        }
}

/************************************************************************************************************************
函数名称:        void Task1(void)
函数原型:        void Task1(void)
函数功能:        任务1:       
************************************************************************************************************************/
void Task1(void)
{
        DDRB = 0xff;
        PORTB = 0xff;
        OSSemCreat(1,0);
        while(1)
        {
                OSSemPend(1,0xffff);
                PORTB = ~PORTB;
        }
}

/************************************************************************************************************************
函数名称:        void Task2(void)
函数原型:        void Task2(void)
函数功能:        任务2       
************************************************************************************************************************/
void Task2(void)
{
        while(1)
        {
                OSTimeDly(200);
                OSSemPost(0);
                OSTimeDly(200);
                OSSemPost(1);
        }
}

/************************************************************************************************************************
函数名称:        int main(void)
函数原型:        int main(void)
函数功能:        主函数:       
************************************************************************************************************************/
int main(void)
{
        OSInit();
       
        OSTaskCreate(Task0,&Stack1[64-1],2);
        OSTaskCreate(Task1,&Stack2[64-1],1);
        OSTaskCreate(Task2,&Stack3[64-1],0);
       
        OSStart();
        return 0;
}
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-20 10:54

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表