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

📄 manual.txt

📁 就像在嵌入系统中使用C语言替代汇编一样,在嵌入系统中使用RTOS是大势所趋。原因主要是现在在大多数情况下编程效率比执行效率重要(单片机便宜嘛)。但纵观51的RTOS
💻 TXT
📖 第 1 页 / 共 3 页
字号:
     可以减少两个字节空间占用,但这样程序复杂一些。

Small RTOS的移植:
(1)在os_cpu.h中定义几个宏(以keil c51为例):

    #define  OS_INT_ENTER() OSIntNesting++                      /* 中断嵌套管理             */
#define  OS_ENTER_CRITICAL()  EA = 0,Os_Enter_Sum++             /* 关中断                                     */
#define  OS_EXIT_CRITICAL()   if (--Os_Enter_Sum==0) EA = 1     /* 开中断                                     */

    #define  HIGH_BYTE  0                                       /* uint16的高位字节         */
    #define  LOW_BYTE   1                                       /* uint16的低位字节         */

    #define  OS_TASK_SW()         OSCtxSw()                     /* 任务切换函数             */


    OS_ENTER_CRITICAL()、OS_EXIT_CRITICAL()分别定义为关中断和开
    中断在特定的c编译器的表示方法。
    HIGH_BYTE、LOW_BYTE定义uint16型变量在特定的c编译器的存储方法,
    如果高位字节的地址小于低位字节的地址(如keil c51),则
    HIGH_BYTE为0,LOW_BYTE为1。否则(如8086系列),HIGH_BYTE为1,
    LOW_BYTE为0。
    OS_INT_ENTER则将变量OSIntNesting加1。它仅在中断服务程序中使用。
    注意:如果中断嵌套层数可能超过255,OS_INT_ENTER要防止
    OSIntNesting溢出。
    OS_TASK_SW()定义非中断中任务切换时执行的指令,可以是一条软中断指
    令(例如在8086系列CPU上),或仅仅是函数调用(如keil c51)。

(2)定义与编译器无关的变量类型(以keil c51为例):

    typedef unsigned char  uint8;                                   /* 定义可移植的无符号8位整数关键字            */
    typedef signed   char  int8;                                    /* 定义可移植的有符号8位整数关键字            */
    typedef unsigned int   uint16;                                  /* 定义可移植的无符号16位整数关键字           */
    typedef signed   int   int16;                                   /* 定义可移植的有符号16位整数关键字           */
    typedef unsigned long  uint32;                                  /* 定义可移植的无符号32位整数关键字           */
    typedef signed   long  int32;                                   /* 定义可移植的有符号32位整数关键字           */

(3)在os_cpu_c.c和os_cpu_a.asm中定义几个函数:
    OSStart、OSIntCtxSw、OSTickISR、OSIdle和OS_TASK_SW()最终调用的
    函数或中断。
    
    OSStart:初始化任务并让ID为0的任务执行。同时允许中断。
      定义如下:
    
                void OSStart(void)
        
        {
            初始化除ID为0以外所有任务堆栈;
            OSTaskID = 0;
            使堆栈指针指向ID为0的任务堆栈空间;
            OS_EXIT_CRITICAL();
            使程序指针指向ID为0的任务的程序首地址;
        }

    OSIntCtxSw:中断中任务切换函数
      定义如下:

                void OSIntCtxSw(void)
        
        {
            堆栈指针调整为中断程序调用OSIntExit前的状态;
            堆栈空间变换;
            堆栈指针指向新的堆栈;
            OSTaskID = OSNextTaskID;
            恢复任务环境;
            中断返回指令;
        }
        OSIntCtxSw由OSIntExit直接调用,堆栈指针调整为中断程序调用
        OSIntExit前的状态即为执行若干出栈指令。
        堆栈空间变换可以参照keilc51目录下Os_cpu_c.c文件中被注释的
        C_OSCtxSw函数,C_OSCtxSw还包括 堆栈指针指向新的堆栈.
        
    OSTickISR为系统节拍中断服务程序
      定义如下:

               void OSTickISR(void)

        {
        #if TICK_TIMER_SHARING >1 
            static unsigned char TickSum=0;
        #endif

            禁止中断;
            保存任务环境;

        #if TICK_TIMER_SHARING >1 
            TickSum = (TickSum + 1) % TICK_TIMER_SHARING;
            if (TickSum != 0)
            {
                允许中断;
                恢复任务环境;
                return;
            }                
        #endif


        #if EN_OS_INT_ENTER >0 
            OS_INT_ENTER();                                     /* 中断开始处理                                             */
        #endif
            允许中断;
    
        #if USER_TICK_TIMER_EN == 1 
            UserTickTimer();                                    /* 用户函数                                                 */
        #endif

        #if EN_TIMER_SHARING > 0
            OSTimeTick();                                       /* 调用系统时钟处理函数                                     */
        #else
            OSIntSendSignal(TIME_ISR_TASK_ID);
        #endif
    
            OSIntExit();                                        /* 中断结束处理                                             */
        }
    
      其中有一些CPU的禁止中断和保存任务环境由CPU自动处理或是自动处
      理一部分。    
    
    OSIdle()优先级最低的任务
    定义如下:

            void OSIdle(void)
    {
        while(1)
        {
            /* 使CPU处于省电状态 */
            
        }
    }
    
    OS_TASK_SW()最终调用的函数或中断:非中断中任务切换函数
      定义如下:

                void OS_TASK_SW(void)
        
        {
            保存任务环境;
            堆栈空间变换;
            堆栈指针指向新的堆栈;
            OSTaskID = OSNextTaskID;
            恢复任务环境;
            恢复程序指针;
        }
        
        
        
            
Small RTOS 51(for keil)的特殊说明:
  编译器版本需求需求
      当不使用消息队列时,需要Keil C51 V6.14以上版本。
      当使用消息队列时,需要Keil C51 V7.00以上版本。
  C语言优化等级设置
      优化等级设置不能大于7,可以等于7。
  目标系统需求
      Small RTOS 51可以在没有任何外部数据存储器的单片8051系统上运行
      但应用程序仍然可以访问外部存储器。Small RTOS 51可以使用C51支
      持的全部存储器模块,选择记忆模型仅影响应用目标的位置。一般来说
      Small RTOS 51应用程序工作在小模式下。Small RTOS 51没有按照
      bank switching 程序设计,不能使用code banking程序。
  可再入功能
      不允许从几个任务或中断过程调用非可再入C语言函数。
      非可再入C51函数将它们的参数和自动变量局部数据保存在静态存储器内
      因此当重复调用函数时这些数据会被改写。非可再入C语言函数不可第归
      调用,不可被多个任务同时调用,不可被一个或多个任务与一个或多个
      中断同时调用。Small RTOS 51系统函数不会调用任何这样的函数。那些
      仅使用寄存器作为参变量和自动变量的C语言函数总是可再入的而且可以
      从不同的Small RTOS 51任务中没有任何限制的调用。C51编译程序也提
      供可再入功能,参看“ C51 用户手册”以便获得更多信息。可再入函数
      (用reentrant关键字的函数)将他们的参变量和局部数据变量储存到一
      个可再入堆栈内并且数据是被保护的以预防多重呼叫。然而如果你在你的
      应用程序中使用可再入函数(用reentrant关键字的函数)你必须保证这
      些功能不呼叫任何Small RTOS 51系统函数。而且那些可再入函数(用
      reentrant关键字的函数)不会被Small RTOS 51任务调度所中断。特别
      注意一点,可再入堆栈不得放在内部RAM中。
  C51库函数
      全部的可再入 C51 库函数可以没有任何限制的用于全部任务。非可再入
      c51库函数与非可再入C语言函数在应用时有着同样的限制。
  多数据指针和数学单元的用法
      c51 编译程序允许你使用8051派生类型的多数据指针和数学单元。因为
      Small RTOS 51不包括任何对这些硬件的管理,最好你不要与Small 
      RTOS 51 一起使用这些器件。如果你可以保证在使用这些派生硬件的程
      序执行期间不会被任务调度中断的话你可以使用多数据指针和数学单元。
  寄存器段
      Small RTOS 51分配全部任务到寄存器段0。因此全部的任务函数必须用
      c51的默认设置registerbank 0 编译。不需要Small RTOS 51管理的
      中断函数可以使用剩余的寄存器段。
  局部变量
      keil c51采用变量覆盖的方法分配局部变量,而不是把局部变量分配到
      堆栈中,当在keil c51使用Small RTOS时,编译系统会把各个任务的局
      部变量分配在同一块内存,造成程序运行错误。因此,最多只能允一个
      任务函数与?CO?OS_CPU_C进行覆盖分析,禁止任务函数与?CO?OS_CPU_C
      进行覆盖分析的方法如下:
      在Progect->BL51 Misc->Overlay里填"?CO?OS_CPU_C~任务函数名,"
      每一项禁止一个任务函数。
      如果任务(包括任务调用的函数)没有局部变量,可以不进行以上处理。
      注意参数也是局部变量。
      另外,用户函数被多个任务或和中断调用且不可再入(程序保证各个任
      务和中断不同时调用此函数),它的局部变量不能与任何任务的局部变
      量覆盖,应该禁止所有调用它的任务与之进行覆盖分析,方法与上面一
      样:
      在Progect->BL51 Misc->Overlay里填"任务函数名~用户函数名,"。
      在进行以上处理后,会出现多条类似如下的警告:
      
      *** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
          SEGMENT: ?PR?XXXX?XXX
      
      不用理会它.
      
      注意,以上最后一项不需要逗号。
  关于软非屏蔽中断
      当某个中断对时间要求非常严格的时候,用户可以使用软非屏蔽中断,使
      之不受Small RTOS 51关中断的影响,但它也不再受OS管理。设置方法
      如下:
      (1)将这个中断设置为最高优先级中断,其它受OS管理的中断优先级
      必须比它低。因此,标准51系列单片机就不需要中断嵌套管理了。有些
      51单片机有超过2个中断优先级,它们还需要中断嵌套管理。
      (2)将OS_CPU.h中EN_SP2定义为1
      (3)将OS_CPU.h中宏OS_ENTER_CRITICAL()定义为类似 
           IE = IE & (~0x30)
      形式,其中0x30根据程序要求取值,为1的位为程序运行时需要打开且
      受OS管理的中断。
      (4)将OS_CPU.h中宏OS_ENTER_CRITICAL()定义为类似 
           IE = IE | 0xb0
      形式,其中0xb0根据程序要求取值,为1的位为程序运行时需要打开且
      受OS管理的中断。
      (5)将OS_CPU.h中Sp2Space定义合适大小(ISR使用堆栈最大值+2)。
      (6)将OS_CPU.h中宏SET_EA定义为类似
             orl     IE,#0b0h
      形式,其中0b0h根据程序要求取值,以允许程序运行时受OS管理的中断
      可以中断CPU。
      (7)在合适的时候允许或禁止软非屏蔽中断。
      (8)软非屏蔽中断不允许调用OS_INT_ENTER()和OSIntExit(),因此,
      如果在软非屏蔽中断中调用OSIntSendSignal()使高优先级任务就绪,
      OS也不进行任务切换。作者不推荐在软非屏蔽中断中调用
      OSIntSendSignal()。

      

      
      
  其它注意事项
      1、通过调用系统函数进行任务切换,保存任务环境需要RAM空间为(2+到
         OSSched时的调用层次*2)字节。通过中断进行任务切换保存任务环境
         需要RAM空间为(中断发生时堆栈使用量+15)字节,这15字节包括
         R0~R7,ACC,B,PSW,DPH,DPL和返回地址。而8051系列idata小(51只
         有128字节,52只有256字节),因此,当任务较多时,应该避免过多
         的通过中断进行任务切换。
      2、OS_CPU.H 中的IDATA_RAM_SIZE应当与实际的idata相同。
      

⌨️ 快捷键说明

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