单线程轮训裸机OS程序

14 篇文章 0 订阅
8 篇文章 1 订阅

近日在学习STM32单片机操作系统之余,写了如下单线程轮训裸机OS程序,分享出来与大家共同进步,如有错误或不足之处,敬请谅解,尊听指导。


版权说明,此博客出自:http://blog.csdn.net/u011833609/article/details/50564378


此单线程轮训裸机OS具有一下特点:

1.以系统滴答时钟为驱动持续工作;

2.任务具有关闭、睡眠、执行、延时、等待共五种状态;

3.任务ID及任务数需在系统运行前就确定;

4.任务执行过程中可根据需要随时对任务进行关闭,打开,睡眠及唤醒操作;

5.任务间通信可采用全局变量的方式完成;

6.任务间同步可采用任务等待条件(需要编写任务等待条件回调函数)方式完成;

7.任务执行过程中需要延时,可通过任务延时函数给出确定延时时间完成。

区别于FreeRTOS、uCOS等真正意义上的OS,此单线程轮训裸机OS需要注意一下几点:

1.此OS中的任务不得以死循环方式实现,不得长时间占用MCU资源;

2.在任务没有启动或关闭之后,请不要调用任务延时,否则不成功;

3.在任务延时过程中,请退出当前任务,释放MCU资源以供其他任务使用;

4.此OS中任务不支持抢占,也不是争抢资源的意思,而是空闲主动让出资源。

为达到更好的使用效果,任务例程如下:

typedef struct {

    uint32_t step;

    //....Other Param

}TaskTest_TypeDef;

TaskTest_TypeDef taskTest;

void TaskTest(uint32_t p)

{

    switch(taskTest.step)

    {

        case TASK_TEST_INIT:

            // INIT CODE

            taskTest.step = TASK_TEST_STEP1;

            OS_TaskDelay(OS_TASK_THIS, 10);

            break;

        case TASK_TEST_STEP1:

            // STEP1 CODE

            taskTest.step = TASK_TEST_STEP2;

            OS_TaskWait(TaskWaitSignel, 2);

            break;

        case TASK_TEST_STEP2:

            //STEP2 CODE

            break;

        default:

            break;

    }

}

OS_WAIT_STATE TaskWaitSignel(void)

{

    OS_WAIT_STATE state = OS_WAIT_ING;

    if(条件满足)

    {

        state = OS_WAIT_DONE;

    }

    return state;

}

请在创建任务之前,调用OS_Init()初始化OS,创建完任务后,请调用OS_TaskStarting()启动任务。


以下是 os.h 文件

#ifndef __OS_H__
#define __OS_H__

#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>

/***************** OS Config ********************/
#define OS_DRTF_EN      1       //系统抢占功能配置 0 关闭 1 开启
#define OS_MONITOR_EN   0       //任务监控功能配置 0 关闭 1 开启
/*************** OS Config End ******************/

#define OS_TICK_MAX     0x3FFFFFFF
#define IS_OS_TICK_RANGE(nms)   ((nms) < OS_TICK_MAX)

typedef enum
{
    OS_TASK_FIRST,  //不对外开放使用
    
    OS_TASK_IWDG = OS_TASK_FIRST,
    OS_TASK_SYSSEC,
    
#if OS_MONITOR_EN
    OS_TASK_MONITOR,   //单片机监控任务
#endif
    OS_TASK_NUM,
    OS_TASK_THIS,      //当前任务
#if OS_DRTF_EN
    OS_TRDF_NUM = 16,   //抢占任务嵌套层数
#endif //OS_DRTF_EN
}OS_TASK_ID;
#define IS_OS_TASK_ID(id)   ((id) < OS_TASK_NUM)

typedef enum
{
    OS_TASK_AUTO,   //TASK 自动运行
    OS_TASK_MANUAL, //TASK 只运行一次
}OS_TASK_TYPE;
#define  IS_OS_TASK_TYPE(type)  (((type) == OS_TASK_AUTO) || ((type) == OS_TASK_MANUAL))

typedef enum
{
    OS_WAIT_CLOSE,
    OS_WAIT_ING,
    OS_WAIT_DONE,
}OS_WAIT_STATE;

typedef enum
{
    OS_TASK_CLOSE,  //TASK 工作状态-关闭
    OS_TASK_SLEEP,  //TASK 工作状态-睡眠
    OS_TASK_OPEN,   //TASK 工作状态-打开
    OS_TASK_DELAY,  //TASK 工作状态-延时
    OS_TASK_WAIT,   //TASK 工作状态-等待
}OS_TASK_STATE;

#if OS_DRTF_EN
typedef enum
{
    OS_TRPR_COVER,  //覆盖方式
    OS_TRPR_ADDUP,  //累计方式
}OS_TRPR_MODE;
#endif //OS_DRTF_EN

void OS_HardDelayUS(uint32_t nus);
void OS_HardDelayMS(uint32_t nms);
uint32_t OS_TickGet(void);

void OS_Init(void);
OS_TASK_STATE OS_TaskState(OS_TASK_ID id);

void OS_TaskDelete(OS_TASK_ID id);
void OS_TaskSleep(OS_TASK_ID id);
void OS_TaskWakeup(OS_TASK_ID id);
void OS_TaskCreate(OS_TASK_ID id, void (*pTask)(uint32_t), uint32_t param, OS_TASK_TYPE type, uint32_t ival);
void OS_TaskIvalSet(OS_TASK_ID id, uint32_t ival);
void OS_TaskDelay(OS_TASK_ID id, uint32_t nms);
void OS_TaskWait(OS_TASK_ID id, OS_WAIT_STATE (*pWait)(void), uint32_t wival, uint32_t nms);
#if OS_DRTF_EN
void OS_TaskTrdf(OS_TASK_ID trid, OS_TRPR_MODE mode, int16_t trpr);
#endif //OS_DRTF_EN

void OS_TaskStarting(void);

#if OS_MONITOR_EN
void OS_MonitorTask(uint32_t p);
#endif //OS_MONITOR_EN

#endif //__OS_H__

以下是 os.c 文件

#include "os.h"

#if OS_DRTF_EN
typedef enum
{
    OS_TRDF_DISABLE,        //无抢占
    OS_TRDF_ENABLE,         //有抢占
}OS_TRDF_STATE;
#endif //OS_DRTF_EN

typedef struct
{
    void (*pTask)(uint32_t);                //任务指针
    uint32_t                param;          //任务参数
    OS_TASK_TYPE            type;           //任务类型
    uint32_t                ival;           //任务运行间隔
    
    OS_TASK_STATE           state;          //运行状态
    uint32_t                tick;           //运行时间
    
    OS_WAIT_STATE (*pWait)(void);           //等待条件回调函数指针
    uint32_t                wival;          //任务运行间隔
    uint32_t                nms;            //延时时间
}OS_Task_TypeDef;

#if OS_DRTF_EN
typedef struct
{
    uint16_t                first;            //第一个抢占任务地址
    uint16_t                last;             //最后一个抢占任务地址
    uint16_t                pr[OS_TRDF_NUM];  //priority 优先级
    OS_TASK_ID              id[OS_TRDF_NUM];  //抢占任务ID
}OS_Trdf_TypeDef;
#endif //OS_DRTF_EN

#if OS_MONITOR_EN
typedef struct
{
    uint32_t val;
    uint32_t add;
}Object_TypeDef;
#endif //OS_MONITOR_EN

#if OS_MONITOR_EN
typedef struct
{
    Object_TypeDef          schedule;//总调度次数
    Object_TypeDef          busy;   //有用次数
    
    Object_TypeDef          times[OS_TASK_NUM];  //TASK每秒钟调用次数
    Object_TypeDef          nms[OS_TASK_NUM];    //TASK每秒钟调用占用毫秒数
}OS_Monitor_TypeDef;
#endif //OS_MONITOR_EN

typedef struct
{
    uint32_t                tick;               //OS TICK
    OS_TASK_ID              id;                 //当前执行任务ID
#if OS_DRTF_EN
    OS_TRDF_STATE           trst;               //抢占状态
    OS_Trdf_TypeDef         trdf;               //抢占任务
#endif //OS_DRTF_EN
    OS_Task_TypeDef         task[OS_TASK_NUM];  //任务列表
#if OS_MONITOR_EN
    OS_Monitor_TypeDef      moni;  //监控
#endif //OS_MONITOR_EN
}OS_TypeDef;

/*static*/OS_TypeDef   OS;

void OS_HardDelayUS(uint32_t nus)
{
    uint32_t i = 0;
    
    while(nus > 0)
    {
        for( i = 0; i < 48; i++)
        {
            ;
        }
        
        nus--;
    }
}

void OS_HardDelayMS(uint32_t nms)
{
    uint32_t i = 0;
    
    while(nms)
    {
        for( i = 0; i < 5698; i++)
        {
            ;
        }
        
        nms--;
    }
}

void SysTick_Handler(void)
{
    OS.tick = (OS.tick+1) % OS_TICK_MAX;
}

uint32_t OS_TickGet(void)
{
    return OS.tick;
}

void OS_Init(void)
{
    OS.tick = 0;
    
    for(OS.id = OS_TASK_FIRST; OS.id < OS_TASK_NUM; OS.id++)
    {
        OS.task[OS.id].pTask = NULL;
        OS.task[OS.id].param = 0;
        OS.task[OS.id].type = OS_TASK_AUTO;
        OS.task[OS.id].ival = 0;
        OS.task[OS.id].state = OS_TASK_CLOSE;
        OS.task[OS.id].tick = 0;
    }
#if OS_DRTF_EN
    for(OS.trdf.first = 0; OS.trdf.first < OS_TRDF_NUM; OS.trdf.first++)
    {
        OS.trdf.pr[OS.trdf.first] = 0;
        OS.trdf.id[OS.trdf.first] = OS_TASK_FIRST;
    }
    OS.trdf.first = 0;
    OS.trdf.last = 0;
#endif //OS_DRTF_EN
    
    OS.id = OS_TASK_FIRST;
}

OS_TASK_STATE OS_TaskState(OS_TASK_ID id)
{
    if(!IS_OS_TASK_ID(id))  return OS_TASK_CLOSE;
    
    return OS.task[id].state;
}

void OS_TaskDelete(OS_TASK_ID id)
{
    if(!IS_OS_TASK_ID(id))  return;
    
    OS.task[id].state = OS_TASK_CLOSE;
}

void OS_TaskSleep(OS_TASK_ID id)
{
    if(!IS_OS_TASK_ID(id))  return;
    if(OS_TASK_OPEN != OS.task[id].state)  return;
    
    OS.task[id].state = OS_TASK_SLEEP;
}

void OS_TaskWakeup(OS_TASK_ID id)
{
    if(!IS_OS_TASK_ID(id))  return;
    if(OS_TASK_SLEEP != OS.task[id].state)  return;
    if(NULL == OS.task[id].pTask)  return;
    
    OS.task[id].state = OS_TASK_OPEN;
    OS.task[id].tick = OS.tick;
}

void OS_TaskCreate(OS_TASK_ID id, void (*pTask)(uint32_t), uint32_t param, OS_TASK_TYPE type, uint32_t ival)
{
    if(!IS_OS_TASK_ID(id))  return;
    if(pTask == NULL)  return;
    if(!IS_OS_TASK_TYPE(type))  return;
    if(!IS_OS_TICK_RANGE(ival))  return;
    
    OS.task[id].pTask = pTask;
    OS.task[id].param = param;
    OS.task[id].type = type;
    OS.task[id].ival = ival;
    
    OS.task[id].state = OS_TASK_OPEN;
    OS.task[id].tick = OS.tick;
}

void OS_TaskIvalSet(OS_TASK_ID id, uint32_t ival)
{
    switch(id)
    {
        case OS_TASK_THIS:
            OS.task[OS.id].ival = ival;
            break;
        default:
            if(OS_TASK_OPEN != OS.task[id].state)  return;
            OS.task[id].ival = ival;
            break;
    }
}

void OS_TaskDelay(OS_TASK_ID id, uint32_t nms)
{
    switch(id)
    {
        case OS_TASK_THIS:
            OS.task[OS.id].nms = nms;
            OS.task[OS.id].tick = OS.tick;
            OS.task[OS.id].state = OS_TASK_DELAY;
            break;
        default:
            if(OS_TASK_OPEN != OS.task[id].state)  return;
            OS.task[id].nms = nms;
            OS.task[id].tick = OS.tick;
            OS.task[id].state = OS_TASK_DELAY;
            break;
    }
    
}

void OS_TaskWait(OS_TASK_ID id, OS_WAIT_STATE (*pWait)(void), uint32_t wival, uint32_t nms)
{
    switch(id)
    {
        case OS_TASK_THIS:
            OS.task[OS.id].pWait = pWait;
            OS.task[OS.id].wival = wival;
            OS.task[OS.id].nms = nms;
            OS.task[OS.id].tick = OS.tick;
            OS.task[OS.id].state = OS_TASK_WAIT;
            break;
        default:
            if(OS_TASK_OPEN != OS.task[id].state)  return;
            OS.task[id].pWait = pWait;
            OS.task[id].wival = wival;
            OS.task[id].nms = nms;
            OS.task[id].tick = OS.tick;
            OS.task[id].state = OS_TASK_WAIT;
            break;
    }
}

#if OS_DRTF_EN
void OS_TaskTrdf(OS_TASK_ID trid, OS_TRPR_MODE mode, int16_t trpr)
{
    uint16_t pos = OS.trdf.first;
    uint16_t pr = 0;
    OS_TASK_ID id = OS_TASK_FIRST;
    
    while(pos != OS.trdf.last)
    {
        if(OS.trdf.pr[pos] == trpr)
        {
            switch(mode)
            {
                case OS_TRPR_COVER:
                    if(OS.trdf.id[pos] == trid) return;
                    break;
                case OS_TRPR_ADDUP:
                    break;
                default:
                    break;
            }
        }
        else if(OS.trdf.pr[pos] > trpr)
        {
            if(((OS.trdf.last + 1) % OS_TRDF_NUM) != OS.trdf.first)
            {
                OS.trdf.last = (OS.trdf.last + 1) % OS_TRDF_NUM;
            }
            while(pos != OS.trdf.last)
            {
                pr = OS.trdf.pr[pos];
                id = OS.trdf.id[pos];
                OS.trdf.pr[pos] = trpr;
                OS.trdf.id[pos] = trid;
                trpr = pr;
                trid = id;
                
                pos = (pos + 1) % OS_TRDF_NUM;
            }
            break;
        }
        
        pos = (pos + 1) % OS_TRDF_NUM;
    }
}
#endif //OS_DRTF_EN

void OS_TaskRefresh(OS_TASK_ID id)
{
    switch(OS.task[id].type)
    {
        case OS_TASK_AUTO:
            OS.task[id].tick = (OS.task[id].tick + OS.task[id].ival) % OS_TICK_MAX;
            break;
        case OS_TASK_MANUAL:
            OS_TaskDelete(id);
            break;
        default:
            break;
    }
}

void OS_TaskStarting(void)
{
#if OS_MONITOR_EN
    uint32_t ticktmp;
#endif //OS_MONITOR_EN

#if OS_MONITOR_EN
    OS_TaskCreate(OS_TASK_MONITOR, OS_MonitorTask, 0, OS_TASK_AUTO, 1000);
#endif //OS_MONITOR_EN
    
    while(1)
    {
        for(OS.id = OS_TASK_FIRST; OS.id < OS_TASK_NUM; OS.id++)
        {
#if OS_DRTF_EN
            OS.trst = OS_TRDF_DISABLE;
            if(OS.trdf.first != OS.trdf.last)
            {
                //抢断选择
                OS.id = OS.trdf.id[OS.trdf.first];
                
                OS.trdf.first = (OS.trdf.first + 1) % OS_TRDF_NUM;
                OS.trst = OS_TRDF_ENABLE;
            }
#endif //OS_DRTF_EN
            
#if OS_MONITOR_EN
            OS.moni.schedule.add ++;
#endif //OS_MONITOR_EN
            
            switch(OS.task[OS.id].state)
            {
                case OS_TASK_OPEN:
#if OS_DRTF_EN
                    if(OS_TRDF_DISABLE == OS.trst)
                    {
#endif //OS_DRTF_EN
                        if((OS.tick + OS_TICK_MAX - OS.task[OS.id].tick) % OS_TICK_MAX < OS.task[OS.id].ival)   continue;
#if OS_DRTF_EN
                    }
#endif //OS_DRTF_EN
                    
#if OS_MONITOR_EN
                    ticktmp = OS.tick;
#endif //OS_MONITOR_EN
                    
                    OS_TaskRefresh(OS.id);
                    OS.task[OS.id].pTask(OS.task[OS.id].param);
#if OS_MONITOR_EN
                    OS.moni.nms[OS.id].add += OS.tick - ticktmp;
                    OS.moni.times[OS.id].add++;
                    OS.moni.busy.add++;
#endif //OS_MONITOR_EN
                    break;
                case OS_TASK_DELAY:
#if OS_DRTF_EN
                    if(OS_TRDF_DISABLE == OS.trst)
                    {
#endif //OS_DRTF_EN
                        if((OS.tick + OS_TICK_MAX - OS.task[OS.id].tick) % OS_TICK_MAX < OS.task[OS.id].nms)   continue;
#if OS_DRTF_EN
                    }
#endif //OS_DRTF_EN
                    OS.task[OS.id].state = OS_TASK_OPEN;
#if OS_MONITOR_EN
                    ticktmp = OS.tick;
#endif //OS_MONITOR_EN
                    OS_TaskRefresh(OS.id);
                    OS.task[OS.id].pTask(OS.task[OS.id].param);
#if OS_MONITOR_EN
                    OS.moni.nms[OS.id].add += OS.tick - ticktmp;
                    OS.moni.times[OS.id].add++;
                    OS.moni.busy.add++;
#endif //OS_MONITOR_EN
                    break;
                case OS_TASK_WAIT:
#if OS_DRTF_EN
                    if(OS_TRDF_DISABLE == OS.trst)
                    {
#endif //OS_DRTF_EN
                        if((OS.tick + OS_TICK_MAX - OS.task[OS.id].tick) % OS_TICK_MAX < OS.task[OS.id].nms)   continue;
                        if(OS_WAIT_DONE != OS.task[OS.id].pWait())  continue;
#if OS_DRTF_EN
                    }
#endif //OS_DRTF_EN
                    
#if OS_MONITOR_EN
                    ticktmp = OS.tick;
#endif //OS_MONITOR_EN
                    OS.task[OS.id].state = OS_TASK_OPEN;
                    OS_TaskRefresh(OS.id);
                    OS.task[OS.id].pTask(OS.task[OS.id].param);
#if OS_MONITOR_EN
                    OS.moni.nms[OS.id].add += OS.tick - ticktmp;
                    OS.moni.times[OS.id].add++;
                    OS.moni.busy.add++;
#endif //OS_MONITOR_EN
                    break;
                default:
                    break;
            }
        }
    }
}

#if OS_MONITOR_EN
void OS_MonitorTask(uint32_t p)
{
    OS_TASK_ID id = OS_TASK_FIRST;
    
    OS.moni.schedule.val = OS.moni.schedule.add;
    OS.moni.busy.val = OS.moni.busy.add;
    OS.moni.schedule.add = 0;
    OS.moni.busy.add = 0;
    
    for(id = OS_TASK_FIRST; id < OS_TASK_NUM; id++)
    {
        OS.moni.times[id].val = OS.moni.times[id].add;
        OS.moni.nms[id].val = OS.moni.nms[id].add;
        OS.moni.times[id].add = 0;
        OS.moni.nms[id].add = 0;
    }
}
#endif //OS_MONITOR_EN

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值