一、前言
刚开始学习写代码时代码都会放在主循环中,通过while(1)不停的轮训。如果想做一个时间触发的任务,比如做一个100ms闪烁一次的LED,通常的写法是创建一个1ms定时器,在定时中断中变量自加,当变量加到100ms标志置位,然后在主循环中切换LED状态,本次实现的OS原理就是基于该原理实现的,准确的说这只是一个多任务链表的轮询。在很多MCU开发中,功能很简单,实时性要求不强,如果使用RTOS显得太浪费,任务多了管理不当又很乱,所以才会想起做一个轮询的任务管理。为体现出高大上,所以命名为cola_os。(如有问题,欢迎指正)
二、例程
目的:创建两个定时任务,500msLED切换一次状态,每1s串口打印一次数据;
任务创建代码
#include "cola_os.h"
#include "app.h"
#include
#include "bsp.h"
#include "led.h"
#include "config.h"
task_t timer_500ms,timer_1s;
//led每500ms状态改变一次
static void timer_500ms_cb(uint32_t event)
{
led_toggle();
}
//led每500ms状态改变一次
static void timer_1s_cb(uint32_t event)
{
os_log("timer 1s......\r\n");
}
void app_init(void)
{
cola_timer_create(&timer_500ms,timer_500ms_cb);
cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
cola_timer_create(&timer_1s,timer_1s_cb);
cola_timer_start(&timer_1s,TIMER_ALWAYS,1000);
}
运行结果:
三、源代码解析(代码注释写的很详细了)
1.头文件
#ifndef _COLA_OS_H_
#define _COLA_OS_H_
#include
#include
//任务事件
enum EVENT_SIG
{
SIG_ALARM = 1 << 0,
SIG_DATA = 1 << 1,
SIG_NOTE = 1 << 2,
SIG_UART = 1 << 3,
SIG_RADIO = 1 << 4,
SIG_GPRS = 1 << 5,
SIG_USR1 = 1 << 8,
SIG_USR2 = 1 << 9,
SYS_EVENT_MSG = 1 << 15,
};
enum
{
TIMER_ALWAYS = 0x00,
TIMER_ONE_SHOT = 0x01,
};
typedef void (*cbFunc)(uint32_t event);
typedef struct task_s
{
uint8_t timerNum; //定时编号
uint32_t period; //定时周期
bool oneShot; //true只执行一次
bool start; //开始启动
uint32_t timerTick; //定时计数
bool run; //任务运行标志
bool taskFlag; //任务标志是主任务还是定时任务
uint32_t event; //驱动事件
cbFunc func; //回调函数
struct task_s *next;
}task_t;
/*
主循环任务创建
*/
int cola_task_create(task_t *task,cbFunc func);
/*
主循环任务删除
*/
int cola_task_delete(task_t *task);
/*
任务遍历,放到while(1)循环中
*/
void cola_task_loop(void);
/*
定时任务创建
*/
int cola_timer_create(task_t *timer,cbFunc func);
/*
启动定时任务
one_shot:TIMER_ALWAYS 循环定时
TIMER_ONE_SHOT 只运行一次
time_ms :定时时间
*/
int cola_timer_start(task_t *timer,bool one_shot,uint32_t time_ms);
/*
停止定时任务
*/
int cola_timer_stop(task_t *timer);
/*
定时任务遍历,放到1ms ticker中
*/
void cola_timer_ticker(void);
/*
设置任务事件
*/
int cola_set_event(task_t *task,uint32_t sig_id);
/*
取消任务事件
*/
int cola_clear_event(task_t *task,uint32_t sig_id);
#endif
2.C文件
#include "cola_os.h"
#include
#include "bsp.h"
enum
{
TASK_TASK = 0x00,
TASK_TIMER = 0x01,
};
static struct task_s *task_list = NULL;
static volatile uint8_t task_num = 0;
/*
查找任务是否存在
*/
static bool cola_task_is_exists( task_t *task )
{
task_t* cur = task_list;
while( cur != NULL )
{
if( cur->timerNum == task->timerNum )
{
return true;
}
cur = cur->next;
}
return false;
}
/*
创建任务
*/
int cola_task_create(task_t *task,cbFunc func)
{
task_t *cur = task_list;
OS_CPU_SR cpu_sr;
enter_critical();
if((NULL == task )||(cola_task_is_exists(task)))
{
exit_critical();
return false;
}
task->taskFlag = TASK_TASK;
task->start = true;
task->run = true;
task->func = func;
task->event = 0;
if(NULL == task_list)
{
task_num++;
task->timerNum = task_num;
task_list = task;
task_list->next = NULL;
}
else
{
while((cur->next != NULL))
{
cur = cur->next;
}
task_num++;
task->timerNum = task_num;
cur->next = task;
task->next = NULL;
}
exit_critical();
return true;
}
/*
删除指定任务
*/
int cola_task_delete(task_t *task)
{
task_t *cur = task_list;
task_t *tmp = NULL;
OS_CPU_SR cpu_sr;
enter_critical();
while( cur != NULL )
{
if( cur->timerNum == task->timerNum )
{
tmp = cur->next;
cur->next = tmp->next;
exit_critical();
return true;
}
cur = cur->next;
}
exit_critical();
return false;
}
/*
循环遍历任务链表
*/
void cola_task_loop(void)
{
uint32_t events;
task_t *cur = task_list;
OS_CPU_SR cpu_sr;
while( cur != NULL )
{
if(cur->run)
{
if(NULL !=cur->func)
{
events = cur->event;
if(events)
{
enter_critical();
cur->event = 0;
exit_critical();
}
cur->func(events);
}
if(TASK_TIMER == cur->taskFlag)
{
enter_critical();
cur->run = false;
exit_critical();
}
if((cur->oneShot)&&(TASK_TIMER == cur->taskFlag))
{
cur->start = false;
}
}
cur = cur->next;
}
}
/*
定时器创建
*/
int cola_timer_create(task_t *timer,cbFunc func)
{
task_t *cur = task_list;
OS_CPU_SR cpu_sr;
enter_critical();
if((NULL == timer )||(cola_task_is_exists(timer)))
{
exit_critical();
return false;
}
timer->taskFlag = TASK_TIMER;
timer->run = false;
timer->period = 0;
timer->oneShot = true;
timer->start = false;
timer->timerTick = 0;
timer->func = func;
timer->event = 0;
if(NULL == task_list)
{
task_num++;
timer->timerNum = task_num;
task_list = timer;
task_list->next = NULL;
}
else
{
while(cur->next != NULL)
{
cur = cur->next;
}
task_num++;
timer->timerNum = task_num;
cur->next = timer;
timer->next = NULL;
}
exit_critical();
return true;
}
/*
定时器启动
*/
int cola_timer_start(task_t *timer,bool one_shot,uint32_t time_ms)
{
task_t *cur = task_list;
OS_CPU_SR cpu_sr;
enter_critical();
while( cur != NULL )
{
if( cur->timerNum == timer->timerNum )
{
timer->period = time_ms;
timer->oneShot = one_shot;
timer->start = true;
timer->timerTick = 0;
timer->taskFlag = TASK_TIMER;
exit_critical();
return true;
}
cur = cur->next;
}
exit_critical();
return false;
}
/*
定时器停止
*/
int cola_timer_stop(task_t *timer)
{
task_t *cur = task_list;
OS_CPU_SR cpu_sr;
enter_critical();
while( cur != NULL )
{
if( cur->timerNum == timer->timerNum )
{
timer->start = false;
exit_critical();
return true;
}
cur = cur->next;
}
exit_critical();
return false;
}
/*
定时信息轮训
*/
void cola_timer_ticker(void)
{
task_t *cur = task_list;
OS_CPU_SR cpu_sr;
while( cur != NULL )
{
if((TASK_TIMER == cur->taskFlag)&& cur->start)
{
if(++cur->timerTick >= cur->period)
{
cur->timerTick = 0;
if(cur->func != NULL)
{
enter_critical();
cur->run = true;
exit_critical();
}
}
}
cur = cur->next;
}
}
/*
设置事件
*/
int cola_set_event(task_t *task,uint32_t sig_id)
{
task_t *cur = task_list;
OS_CPU_SR cpu_sr;
enter_critical();
while( cur != NULL )
{
if( cur->timerNum == task->timerNum )
{
cur->event |= sig_id;
exit_critical();
return true;
}
cur = cur->next;
}
exit_critical();
return false;
}
/*
清除事件
*/
int cola_clear_event(task_t *task,uint32_t sig_id)
{
task_t *cur = task_list;
OS_CPU_SR cpu_sr;
enter_critical();
while( cur != NULL )
{
if( cur->timerNum == task->timerNum )
{
cur->event &= ~(sig_id);
exit_critical();
return true;
}
cur = cur->next;
}
exit_critical();
return false;
}
四、国际惯例-代码下载
CSDN:https://download.csdn.net/download/ziqi5543/11812514
gitlab:https://gitee.com/schuck/cola_os