嵌入式–轮询调度模块
参考别人设计,感谢大佬的付出。此模块用在裸机中作为时间片调用,代码层次清晰,并非所有编译器支持,谨慎使用。
头文件 module.h
#ifndef __MODULE_H
#define __MODULE_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* define variable --------------------------------------------------------*/
#define DEFINE_CONN(type, var, line) type var##line
#define DEFINE_TYPE(type, prefix) DEFINE_CONN(type, prefix, __LINE__)
#define DECLARE_TYPE(type, var) type type##var
#define ABTAIN_TYPE(type, var) type##var
#if defined(__CC_ARM) || defined(__GNUC__) /* ARM,GCC*/
#define SECTION(x) __attribute__((section(x)))
#define USED __attribute__((used))
#elif defined (__ICCARM__) /*IAR */
#define SECTION(x) @ x
#define USED __root
#else
#error "Current tool chain haven't supported yet!"
#endif
typedef struct{
void (*init)(void); //初始化接口
}InitItem_t;
typedef struct{
void (*exit)(void); //初始化接口
}ExitItem_t;
typedef struct{
const char *name; //模块名称
void (*handle)(void); //初始化接口
unsigned int interval; //轮询间隔
unsigned int *timer; //指向定时器指针
}TaskItem_t;
#define Module_Init(func) \
USED DEFINE_TYPE(const InitItem_t, init_tbl_##func)\
SECTION("init.item.1") = {func}
#define Module_Exit(func) \
USED DEFINE_TYPE(const ExitItem_t, exit_tbl_##func)\
SECTION("exit.item.1") = {func}
#define Timer_Register(name, handle, interval) \
static unsigned int __task_timer_##handle; \
USED DEFINE_TYPE(const TaskItem_t, task_item_##handle) \
SECTION("task.item.1") = {name,handle, interval, &__task_timer_##handle}
#define Task_Register(name, handle) \
USED DEFINE_TYPE(const TaskItem_t, task_item_##handle) \
SECTION("task.item.1") = {name,handle, 0, NULL}
// 数据报传送
typedef struct{
const char* name; // 标识
void* msg; // 内容
int size; // 内容大小
bool flg; // 数据更新标识
}Msg_Item_t;
// 注意,每个标识在注册的时候,msg的大小已确定
#define MSG_Register(name, type, var) \
static DECLARE_TYPE(type, var); \
USED DECLARE_TYPE(Msg_Item_t, type##var) \
SECTION("msg.item.1") = {name, (void*)&ABTAIN_TYPE(type, var), sizeof(type), false}
void Task_IncTick(void);
unsigned int Task_GetTick(void);
void SysModule_Init(void);
void SysModule_Exit(void);
void SysTask_Process(void);
bool Msg_Send(const char* name, void* msg);
bool Msg_Recv(char* name, void* msg, int size);
#ifdef __cplusplus
}
#endif
#endif
源文件 module.c
#include <string.h>
#include <stdlib.h>
#include "module.h"
static volatile unsigned int s_Task_Tick = 0;
static void NullProcess(void){}
const USED InitItem_t init_tbl_start SECTION("init.item.0") = {
NullProcess
};
const USED InitItem_t init_tbl_end SECTION("init.item.2") = {
NullProcess
};
const USED ExitItem_t exit_tbl_start SECTION("exit.item.0") = {
NullProcess
};
const USED ExitItem_t exit_tbl_end SECTION("exit.item.2") = {
NullProcess
};
const USED TaskItem_t task_tbl_start SECTION("task.item.0") = {
"", NullProcess
};
const USED TaskItem_t task_tbl_end SECTION("task.item.2") = {
"", NullProcess
};
void Task_IncTick(void)
{
++s_Task_Tick;
}
unsigned int Task_GetTick(void)
{
return s_Task_Tick;
}
void SysModule_Init(void)
{
const InitItem_t *it = &init_tbl_start;
while(it < &init_tbl_end)
{
if(!it->init)
{
break;
}
it++->init();
}
}
void SysModule_Exit(void)
{
const ExitItem_t *it = &exit_tbl_start;
while(it < &exit_tbl_end)
{
if(!it->exit)
{
break;
}
it++->exit();
}
}
void SysTask_Process(void)
{
const TaskItem_t *t;
for (t = &task_tbl_start + 1; t < &task_tbl_end; t++)
{
if(!t->timer)
{
if(t->handle)
{
t->handle();
}
continue;
}
if((Task_GetTick() - *t->timer) >= t->interval)
{
*t->timer = Task_GetTick();
if(t->handle)
{
t->handle();
}
}
}
}
Msg_Item_t msg_tbl_start __attribute__((section("msg.item.0"))) = {
"", (void*)0, 0
};
Msg_Item_t msg_tbl_end __attribute__((section("msg.item.2"))) = {
"", (void*)0, 0
};
bool Msg_Send(const char* name, void* msg)
{
Msg_Item_t *it = &msg_tbl_start;
while(it < &msg_tbl_end)
{
if(strcmp(it->name, name) == 0)
{
memcpy(it->msg, msg, it->size);
it->flg = true;
return true;
}
it++;
}
return false;
}
bool Msg_Recv(char* name, void* msg, int size)
{
if(!msg)
{
return false;
}
Msg_Item_t *it = &msg_tbl_start;
while(it++ < &msg_tbl_end)
{
if(strcmp(it->name, name) == 0)
{
if(it->flg == false)
{
return false;
}
if(size < it->size)
{
return false;
}
memcpy(msg, it->msg, it->size);
it->flg = false;
return true;
}
}
return false;
}