|
此调度器,结合本论坛各位高手的代码,及Protothreads,加上自己的理解,及实际在项目中的使用情况不断修改而成,
在这里要感谢各位坛友的代码;
本调度器共3个文件
schedule.h
schedule.c
sch_cfg.h
本调度器特点:
1,仿OS编程方式
2,代码优化等级不能过高
3,适用于前后台及OS的系统中
4,占用一个CPU一个定时器
5,支持信号量
6,支持邮箱
代码如下:
schedule.h
- #ifndef _SCH_H
- #define _SCH_H
- #ifdef __cplusplus
- extern "C" {
- #endif
- /**********************************************************************************************************
- * schedule 版本号
- **********************************************************************************************************/
- #define SCH_VERSION 02100u
- /**********************************************************************************************************
- * 包含头文件
- **********************************************************************************************************/
- #include <sch_cfg.h>
-
- #ifndef SCH_GLOBALS
- #define SCH_EXT extern
- #else
- #define SCH_EXT
- #endif
- /**********************************************************************************************************
- * 数据结构定义
- **********************************************************************************************************/
- typedef struct { //任务TCB数据类型定义
- SCH_TICKS TaskDly;
- INT8U SpawnExitFlag;
- } SCH_TCB;
- typedef SCH_TICKS SEM; //信号量数据类型定义
- typedef struct { //邮箱数据类型定义
- SCH_TICKS Dly;
- void *pMbox;
- } MBOX;
- /**********************************************************************************************************
- * 全局变量定义
- **********************************************************************************************************/
- SCH_EXT SCH_TCB TaskTcb[SCH_MAX_TASKS]; //任务状态数据结构
- SCH_EXT INT8U CurRunTaskId; //当前运行任务的ID号
- /**********************************************************************************************************
- * 系统状态定义
- **********************************************************************************************************/
- #define SCH_ERR_NONE 0u
- #define SCH_ERR_TIMEOUT 10u
- /**************************************************************************************************************
- ************任务相关宏
- 【1】任务创建按实例创建:
- void Task_xxx(void)
- {
- SCH_TaskBegin();
- while(1) {
- //用户代码
- SCH_TimeDly(SCH_TICKS_PER_SEC/100); //根据任务实际周期进行延时
- }
- SCH_TaskEnd();
- }
- 【注意】
- 1,任务必须是无限循环,不能返回;
- 2,任务中必须有延时函数或等待信号量,便于任务出让CPU使用权;
- 3,任务函数中使用的非静态局部变量会在任务出让CPU后,变量消失,因此要想某个变量不消失,则要使用静态变量
- 【2】任务调度,按以下实例
- SCH_TaskRun(Task_xxx,0);
- 【注意】
- 1,各任务的ID不能相同
- **************************************************************************************************************/
- //@任务开始宏,在任务函数的变量声明后引用
- #define SCH_TaskBegin() static INT16U _lc=0u; switch(_lc){case 0:
-
- //@任务结束宏,在任务尾引用
- #define SCH_TaskEnd() }
- //@任务调用宏,在主循环中调用
- //@ TaskName:任务名
- //@ TaskID:任务ID,最大值不能超过"SCH_MAX_TASKS"值,且每个任务的ID不能相同
- #define SCH_TaskRun(TaskName,TaskID) \
- do { \
- CurRunTaskId = TaskID; \
- if(TaskTcb[CurRunTaskId].TaskDly==0) { \
- TaskName(); \
- } \
- } while(0);
-
- /**************************************************************************************************************
- ************子任务相关宏
- 【1】子任务创建按实例创建:
- void SubTask_xxx(void)
- {
- SCH_SubTaskBegin();
- //用户代码
- SCH_TimeDly(SCH_TICKS_PER_SEC/100); //根据任务实际周期进行延时
- SCH_SubTaskEnd();
- }
- 【注意】
- 1,子任务不可以是无限循环,否则子任务后面程序无法执行;
- 2,子任务可以带参数;
- 3,子任务中必须有延时函数或等待信号量,便于任务出让CPU使用权;
- 4,子任务函数中使用的非静态局部变量会在任务出让CPU后,变量消失,因此要想某个变量不消失,则要使用静态变量
- 【2】子任务调度,按以下实例
- SCH_CallSubTask(SubTask_xxx());
- **************************************************************************************************************/
- //@子任务开始宏,在子任务函数的变量声明后引用
- #define SCH_SubTaskBegin() static INT16U _lc=0u;TaskTcb[CurRunTaskId].SpawnExitFlag=1u;switch(_lc){case 0u:
-
- //@子任务结束宏,在子任务函数尾引用
- #define SCH_SubTaskEnd() }_lc=0;TaskTcb[CurRunTaskId].SpawnExitFlag=0u;return
- //@子任务调用宏,在任务中调用,允许多层嵌套
- //@ SubTaskName:子任务名
- //@ p_arg:子线程函数输入参数
- #define SCH_CallSubTask(SubTaskFun) \
- while(1) { \
- _lc=(__LINE__%65535);return;case(__LINE__%65535): { \
- SubTaskFun; \
- } \
- if(TaskTcb[CurRunTaskId].SpawnExitFlag==0u) { \
- break; \
- } \
- }
-
- /**************************************************************************************************************
- ************延时宏定义
- **************************************************************************************************************/
- //@延时宏,在任务开始宏和结束宏之间的任意位置引用;
- //@【注】由于此调度器运用了C语言的行号的宏代码,因此此宏定义最好放在一行代码中,不能拆分此宏定义,防止行号返回出错
- //@ ticks:延时时间
- #define SCH_TimeDly(ticks) do{_lc=(__LINE__%65535);TaskTcb[CurRunTaskId].TaskDly=ticks;return;}while(0);case (__LINE__%65535):
- /**************************************************************************************************************
- ************信号量相关调用宏定义
- **************************************************************************************************************/
- //@信号量创建
- #define SCH_SemCreate(Sem) Sem = 1
- //@w信号量等待
- //@ sem--等待信号量;
- //@ timeout--等待超时时间,0--直到成功等待信号量;
- //@ err--等待信号状态,SCH_ERR_NONE-等待成功,SCH_ERR_TIMEOUT-等待超时
- #define SCH_SemPend(sem,timeout,err) \
- do { \
- if(sem==0) { \
- sem = 1; \
- err = SCH_ERR_NONE; \
- } else { \
- sem = timeout + 1; \
- SCH_TimeDly(0); \
- if(timeout==0) { \
- if(sem>0) { \
- TaskTcb[CurRunTaskId].TaskDly = 0; \
- return; \
- } \
- sem = 1; \
- err = SCH_ERR_NONE; \
- } else { \
- if(sem>1) { \
- sem --; \
- TaskTcb[CurRunTaskId].TaskDly = 1; \
- return; \
- } else if(sem==1) { \
- err = SCH_ERR_TIMEOUT; \
- } else { \
- sem = 1; \
- err = SCH_ERR_NONE; \
- } \
- } \
- } \
- } while(0)
- //@ 发出一个信号量
- #define SCH_SemPost(Sem) \
- do { \
- Sem = 0; \
- } while(0)
-
- /**************************************************************************************************************
- ************邮箱相关调用宏定义
- **************************************************************************************************************/
- #if SCH_MBOX_EN > 0u
-
- //@创建邮箱
- #define SCH_MboxCreate(mbox) do{mbox.Dly = 1;mbox.pMbox = (void*)0;}while(0)
- //@ 邮箱等待
- //@ mbox--等待邮箱;
- //@ pmsg--等待成功后接收邮箱数据指针;
- //@ timeout--等待邮箱超时时间,0--直到成功等待邮箱;
- //@ err--等待邮箱状态,SCH_ERR_NONE-等待成功,SCH_ERR_TIMEOUT-等待超时
- #define SCH_MboxPend(mbox,pmsg,timeout,err) \
- do { \
- if(mbox.pMbox!=(void*)0) { \
- pmsg = mbox.pMbox; \
- mbox.pMbox = (void*)0; \
- err = SCH_ERR_NONE; \
- } else { \
- mbox.Dly = timeout + 1; \
- SCH_TimeDly(0); \
- if(timeout==0) { \
- if(mbox.pMbox==(void*)0) { \
- TaskTcb[CurRunTaskId].TaskDly = 0; \
- return; \
- } \
- pmsg = mbox.pMbox; \
- mbox.pMbox = (void*)0; \
- err = SCH_ERR_NONE; \
- } else { \
- if(mbox.pMbox!=(void*)0) { \
- pmsg = mbox.pMbox; \
- mbox.pMbox = (void*)0; \
- err = SCH_ERR_NONE; \
- } else { \
- if(mbox.Dly>1) { \
- mbox.Dly --; \
- TaskTcb[CurRunTaskId].TaskDly = 1; \
- return; \
- } else if(mbox.Dly==1) { \
- pmsg = (void*)0; \
- mbox.pMbox = (void*)0; \
- err = SCH_ERR_TIMEOUT; \
- } \
- } \
- } \
- } \
- } while(0)
- //@ 发出一个邮箱
- #define SCH_MobxPost(mbox,pmsg) \
- do { \
- mbox.Dly = 0; \
- mbox.pMbox = (void*)pmsg; \
- } while(0)
-
-
- #endif
-
-
-
- /*************************************
- 函数申明
- *************************************/
- void SCH_Init(void);
- void SCH_TimeTick(void);
- #endif
复制代码
schedule.c
- #define SCH_GLOBALS
- #include <schedule.h>
- /********************************************************************************************************
- ** 函数名: SCH_Init
- ** 输 入: 无
- ** 输 出: 无
- ** 功能说明:调度器初始化函数,任务运行前调用
- *********************************************************************************************************/
- void SCH_Init(void)
- {
- INT8U i;
-
- CurRunTaskId = 0;
- for(i=SCH_MAX_TASKS;i>0;i--) {
- TaskTcb[i-1].TaskDly = 0;
- TaskTcb[i-1].SpawnExitFlag = 0;
- }
- }
- /********************************************************************************************************
- ** 函数名: SCH_TimeTick
- ** 输 入: 无
- ** 输 出: 无
- ** 功能说明:调度器时钟节拍函数,在定时中断中调用
- *********************************************************************************************************/
- void SCH_TimeTick(void)
- {
- INT8U i;
- for(i=SCH_MAX_TASKS;i>0;i--) {
- if(TaskTcb[i-1].TaskDly>0) { //任务延时时间处理
- TaskTcb[i-1].TaskDly --;
- }
- }
- }
-
复制代码
sch_cfg.h
- #ifndef SCH_CFG_H
- #define SCH_CFG_H
- #define SCH_MAX_TASKS 10 //最大任务数量,可以增加,最大255个
- #define SCH_MBOX_EN 1 // Enable (1) or Disable (0) 邮箱
- #define SCH_TICKS_PER_SEC 1000 //1秒钟多少个系统时钟数
- /**********************************************************************************************************
- * 与编译器相关数据类型定义
- **********************************************************************************************************/
- typedef unsigned char BOOLEAN;
- typedef unsigned char INT8U; /* Unsigned 8 bit quantity */
- typedef signed char INT8S; /* Signed 8 bit quantity */
- typedef unsigned short INT16U; /* Unsigned 16 bit quantity */
- typedef signed short INT16S; /* Signed 16 bit quantity */
- typedef unsigned int INT32U; /* Unsigned 32 bit quantity */
- typedef signed int INT32S; /* Signed 32 bit quantity */
- typedef float FP32; /* Single precision floating point */
- typedef double FP64; /* Double precision floating point */
- typedef unsigned int SCH_TICKS; //定义延时时钟数据类型
- #endif
复制代码
测试代码
- #include "includes.h"
- #include "app_cfg.h"
- SEM Sem1,Sem2; //
- MBOX mbox1,mbox2;
- /********************************************************************************************************
- ** 函数名: App_FunSemCreate
- ** 输 入:
- ** 输 出:
- ** 功能说明:信号量创建函数
- *********************************************************************************************************/
- static void App_FunSemCreate (void)
- {
- INT8U os_err;
-
- SCH_SemCreate(Sem1);
- SCH_SemCreate(Sem2);
- SCH_MboxCreate(mbox1);
- SCH_MboxCreate(mbox2);
- }
- void Ledred(void)
- {
- SCH_TaskBegin();
- while(1) {
- LEDOn(RED_LED);
- SCH_TimeDly(SCH_TICKS_PER_SEC/2);
- LEDOff(RED_LED);
- SCH_TimeDly(SCH_TICKS_PER_SEC/2);
- }
- SCH_TaskEnd();
-
- }
- void Ledgreen(void)
- {
- SCH_TaskBegin();
- while(1) {
- LEDOff(GREEN_LED);
- SCH_TimeDly(SCH_TICKS_PER_SEC/2);
- LEDOn(GREEN_LED);
- SCH_TimeDly(SCH_TICKS_PER_SEC/2);
- }
- SCH_TaskEnd();
- }
- void Delay(void)
- {
- static uint8_t i;
-
- SCH_TaskBegin();
- while(1) {
- for(i=0;i<5;i++) {
- printf("Delay Cnt = %d\r\n",i);
- SCH_TimeDly(SCH_TICKS_PER_SEC/2);
- }
- printf("Delay exit\r\n");
- }
- SCH_TaskEnd();
- }
- void Task_Sem1Test(void)
- {
- uint8_t err;
-
- SCH_TaskBegin();
- while(1) {
- printf("Sem1 等待置位...\r\n");
- SCH_SemPend(Sem1,0,err);
- printf("Sem1 等待成功...\r\n");
- }
- SCH_TaskEnd();
- }
- void Task_Sem2Test(void)
- {
- uint8_t err;
-
- SCH_TaskBegin();
- while(1) {
- printf("Sem2 等待置位,1秒钟超时...\r\n");
- SCH_SemPend(Sem2,SCH_TICKS_PER_SEC*10,err);
- if(err==SCH_ERR_TIMEOUT) {
- printf("【Sem2】 等待超时...\r\n");
- } else {
- printf("Sem2 等待成功...\r\n");
- }
- }
- SCH_TaskEnd();
- }
- void Task_Mbox1Test(void)
- {
- uint8_t err;
- char *p;
-
- SCH_TaskBegin();
- while(1) {
- printf("mbox1 等待置位,1秒超时...\r\n");
- SCH_MboxPend(mbox1,p,SCH_TICKS_PER_SEC*5,err);
- if(err==SCH_ERR_TIMEOUT) {
- printf("【mbox1】 等待超时...\r\n");
- } else {
- printf("mbox1 等待成功...\r\n");
- printf("mbox=[%s]\r\n",p);
- }
- }
- SCH_TaskEnd();
- }
- void Task_Swap(void *p_arg)
- {
- static uint8_t i;
-
- SCH_SubTaskBegin();
- for(i=0;i<5;i++) {
- printf("swap cnt = %d\r\n",i);
- SCH_TimeDly(SCH_TICKS_PER_SEC*2);
- }
-
- printf("Task_Swap Exit\r\n");
- SCH_SubTaskEnd();
-
- }
- void Task_Swap1(void *p_arg)
- {
- static uint8_t i;
- uint8_t xx;
-
- SCH_SubTaskBegin();
-
- //SCH_CallSubTask(Task_Swap(NULL));
-
- printf("swap exit \r\n");
- for(i=0;i<5;i++) {
- printf("swap1 cnt = %d\r\n",i);
- SCH_TimeDly(SCH_TICKS_PER_SEC*2);
- }
-
- printf("Task_Swap1 Exit\r\n");
- SCH_SubTaskEnd();
- }
- void Task_SwapTest(void)
- {
- uint8_t err;
- void *p;
-
- int test;
-
- SCH_TaskBegin();
- while(1) {
- printf("子任务调用测试...\r\n");
- SCH_CallSubTask(Task_Swap1(NULL));
-
- printf("子任务调用测试完成,延时2秒...\r\n");
- SCH_TimeDly(SCH_TICKS_PER_SEC*2);
- }
- SCH_TaskEnd();
- }
- /********************************************************************************************************
- ** 函数名:main
- ** 输 入:
- ** 输 出:
- ** 功能说明:main函数
- *********************************************************************************************************/
- int main (void)
- {
-
- uint32_t i = 0;
- uint32_t ConnectTime;
-
- uint8_t AppDownload = FALSE;
- uint8_t buf[256];
-
- uint32_t Test = 0,Test2 = 0;
-
- uint8_t ConnectStatus = FALSE;
- char GetKey;
-
- /*=========初始化核心代码=========*/
- SCH_Init(); //调度器初始化
-
- //初始化全局应用变量
- GlobalTime = 998; //计数器
- App_FunSemCreate();
-
- BSP_GPIOConfiguration(); //GPIO配置
- BSP_CpuPeriphInit(); //CPU相关硬件初始化
-
- BSP_WDT_HardInit(); //看门狗初始化
-
- LEDOff(GREEN_LED);
- LEDOff(RED_LED);
-
- BSP_WDTHardReset();
-
- while(1) {
-
- SCH_TaskRun(Ledred,0);
- //SCH_TaskRun(Delay,1);
-
- //SCH_TaskRun(Task_Sem1Test,2);
- //SCH_TaskRun(Task_Sem2Test,3);
- //SCH_TaskRun(Task_Mbox1Test,4);
- Task_Swap(NULL);
- SCH_TaskRun(Task_SwapTest,4);
- GetKey = _getkey();
- if(GetKey!=-1) {
- if(GetKey=='x') {
- printf("Test Sem1\r\n");
- SCH_SemPost(Sem1);
- } else if(GetKey=='y') {
- printf("Test Sem2\r\n");
- SCH_SemPost(Sem2);
- } else if(GetKey=='m') {
- printf("Test mobx1\r\n");
- sprintf((char*)buf,"Test mobx1\r\n");
- SCH_MobxPost(mbox1,buf);
- }
- }
- }
- }
- /**
- * @brief Reports the name of the source file and the source line number
- * where the assert_param error has occurred.
- * @param file: pointer to the source file name
- * @param line: assert_param error line source number
- * @retval None
- */
- #ifdef USE_FULL_ASSERT
- void assert_failed(uint8_t* file, uint32_t line)
- {
- static char str1[256];
- static uint32_t temp;
-
- memcpy((void*)str1,(const void*)file,strlen((const char*)file));
- temp = line;
- /* User can add his own implementation to report the file name and line number,
- ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
- //my_printf("Worng parameters value:file%s on line %d\r\n",file,line);
-
- /* Infinite loop */
- while(1) {
- }
- }
- #endif
- /*************************************************end of file********************************************/
复制代码
使用说明:
1,定时器中调用函数:SCH_TimeTick()
2,main函数开关调用SCH_Init()
=========================分割线==========================================
错误不合理之处,望大家指正,修改,一起完善。
|
阿莫论坛20周年了!感谢大家的支持与爱护!!
如果天空是黑暗的,那就摸黑生存;
如果发出声音是危险的,那就保持沉默;
如果自觉无力发光,那就蜷伏于牆角。
但是,不要习惯了黑暗就为黑暗辩护;
也不要为自己的苟且而得意;
不要嘲讽那些比自己更勇敢的人。
我们可以卑微如尘土,但不可扭曲如蛆虫。
|