• 简单OS(ucos超级精简版)——裸调度器【worldsing笔记】


    简单原则少ROM,少RAM,任务完成就让出CPU,调度器描述:

    1、按最大任务数轮番调度;

    2、任务调用延时接口将让出CPU使用权,进入下一个任务调度;

    3、用户任务都处于延时或是不使用CPU运行Idle任务;

    4、最大任务数255;

    5、任务用独立栈,栈大小由用户自定义;

    6、调度器无需初始化,代码为单个C文件,结构简单,代码尺寸小;

    7、调度器加3个任务代码尺寸:Code=1428 RO-data=268 RW-data=32 ZI-data=520 

    软件环境:Keil Mdk 4.7a 硬件:stm32f103vb

     image

    -------------------------------------------------------------------------------------------------

    //调度器C文件 Switch.c

    #include "stm32f10x.h"
    #include "switch.h"
    #include "string.h"
    #include "stdbool.h"

    TCB      TaskTCB[MAX_TASK + 1] = {0};
    TCB      *TaskNew, *TaskRuning;
    uint32_t IdleStack[20];
    uint8_t  TaskCnt = 0;

    void TaskIdle() {
        while(1){
        }
    }

    __asm void TaskSwitch(void)
    {
        LDR     R0, =0xE000ED22
        LDR     R1, =0xFF
        STRB    R1, [R0]
        LDR     R0, =0xE000ED04              
        LDR     R1, =0x10000000
        STR     R1, [R0]
        BX      LR
          ALIGN
    }

    __asm void PendSV_Handler(void)
    {
            IMPORT  TaskRuning
            IMPORT  TaskNew
        CPSID   I                                                  
        MRS     R0, PSP                                            
        CBZ     R0, NoSave                          

        SUBS    R0, R0, #0x20                                      
        STM     R0, {R4-R11}

        LDR     R1, =TaskRuning                                    
        LDR     R1, [R1]
        STR     R0, [R1]                                           
    NoSave

        LDR     R0, =TaskRuning                                    
        LDR     R1, =TaskNew
        LDR     R2, [R1]
        STR     R2, [R0]

        LDR     R0, [R2]                                           
        LDM     R0, {R4-R11}                                       
        ADDS    R0, R0, #0x20
        MSR     PSP, R0                                            
        ORR     LR, LR, #0x04                                      
        CPSIE   I
        BX      LR                                                
        ALIGN
    }

    void  SysTick_Handler (void)
    {  
          uint8_t i;
          bool bOneSwitch;
          bOneSwitch = false;
          for(i = 0; i < MAX_TASK; i++){
                if(TaskTCB[i].Delay != 0){
                    TaskTCB[i].Delay--;           
          }
                if(bOneSwitch == false){
                  TaskCnt %= MAX_TASK;
                    if(0 == TaskTCB[TaskCnt].Delay){
                        bOneSwitch = true;
                        TaskNew = &TaskTCB[TaskCnt++];
                    }else{
                         TaskCnt++;
                    }
              }
        }
            if(bOneSwitch == false)
                TaskNew = &TaskTCB[IDLE_TASK];
            TaskSwitch();
    }

    void SwitchDelay(uint16_t nTick)
    {
          uint8_t i;
          if(0 == nTick)
                return;
          TaskRuning->Delay = nTick;            
          for(i = 0; i < MAX_TASK; i++){
                TaskCnt %= MAX_TASK;   
                if(0 == TaskTCB[TaskCnt].Delay){
                    TaskNew = &TaskTCB[TaskCnt++];
                    break;
                }else TaskCnt++;
        }
            if(TaskRuning == TaskNew)
                TaskNew = &TaskTCB[IDLE_TASK];
          TaskSwitch();
    }

    void SwitchTaskInt(void (*task)(void), OS_STK *ptos)
    {
          if(MAX_TASK + 1 <= TaskCnt){
                TaskCnt = 0;
                return;
        }
          if(NULL == task)
                return;
            if(NULL == ptos)
                return;
        *(ptos)    = (INT32U)0x01000000L;            
        *(--ptos)  = (INT32U)task;                    
            TaskTCB[TaskCnt]. pTaskStack =  ptos -14;
            TaskTCB[TaskCnt++]. Delay =  0;   
    }

    void SwitchStart(void)
    {
        SystemInit();                                                                 
        __set_PSP(0);                                                            
        SwitchTaskInt(TaskIdle, IdleStack+19);    
        SysTick_Config((SystemCoreClock / N_TICK_IN_SECOND) - 1); 
    }

    -------------------------------------------------------------------------------------------------

    //调度器头文件 SWitch.h

    #ifndef __SWITCH_H__
    #define __SWITCH_H__

    #include "stdint.h"
    #define MAX_TASK          2
    #define N_TICK_IN_SECOND  1000

    #define IDLE_TASK         MAX_TASK
    typedef uint32_t OS_STK;
    typedef uint32_t INT32U;

    typedef struct TCB
    {
      uint32_t *pTaskStack;
        uint16_t Delay;
    }TCB;

    extern  TCB *TaskRuning;
    extern  TCB *TaskNew;
    extern  TCB  TCBTask[MAX_TASK];

    void    SwitchTaskInt(void (*task)(void), OS_STK *ptos);
    void    SwitchDelay(uint16_t Time);
    void    SwitchStart(void);

    #endif

    -------------------------------------------------------------------------------------------------

    //应用Demo App.c

    #include    "stm32f10x.h"
    #include    "stm32f10x_rcc.h"
    #include    "stm32f10x_gpio.h"

    #include "switch.h"
    #include <stdio.h>

    u32 TaskStack[2][40];

    void Task0(void);
    void Task1(void);

    int main(void)
    {
        SwitchTaskInt(Task0, &TaskStack[0][39]);
        SwitchTaskInt(Task1, &TaskStack[1][39]);
      SwitchStart();
        while(1);
    }

    void Task0(void)
    {
       u8 i;
       for(;;)
       {
         i = i;
         //SwitchDelay(200);

       }
    }
    void Task1(void)
    {
       u8 i;
       for(;;)
       {
         //SwitchDelay(300);
         i = i;
       }
    }

    调度器代码: 点击下载

  • 相关阅读:
    hdu 2020
    hdu 1005
    hdu1014
    集合(一)
    史上最全的 Java 新手问题汇总
    表单验证
    oracle优化原则(二)
    vue的学习--如何使用Intellij IDEA配置并运行vue项目
    在win10环境下IED配置spark项目
    在win10环境下配置spark和scala
  • 原文地址:https://www.cnblogs.com/worldsing/p/3409987.html
Copyright © 2020-2023  润新知