近日在学习STM32单片机操作系统之余,写了如下单线程轮训裸机OS程序,分享出来与大家共同进步,如有错误或不足之处,敬请谅解,尊听指导。
版权说明,此博客出自:http://blog.youkuaiyun.com/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