依据时间片调度的原理以及根据github上开源项目TMT,将TMT重新按照自己的风格编写了一遍做出了如今的STS(简易任务调度器),并做出一点小小改动,如有兴趣可在github找到TMT开源项目用于学习。
头文件
/*
* @Author: Qiu Weian
* @Date: 2022-05-07 19:49:14
* @LastEditors: Qiu Weian
* @LastEditTime: 2022-05-08 15:24:26
* @Description:
*/
/*-----------------------------------------------------------------------
| FILE DESCRIPTION |
-----------------------------------------------------------------------*/
/*----------------------------------------------------------------------
- File name : stms.h
- Author : wan
- Update date : 2022.05.07
- Copyright(c) : All rights reserved.
-----------------------------------------------------------------------*/
/*------------------------------------------------------------------------
| COPYRIGHT NOTICE |
------------------------------------------------------------------------*/
/*****
* Statement:This is a simple task scheduler,basede on the open project TMT
* task manager on the github,rewire it with my own code style.
* ***/
/*-----------------------------------------------------------------------
| TRANSPLANT |
-----------------------------------------------------------------------*/
#ifndef __STS_H_
#define __STS_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Includes -------------------------------------------------------------*/
/**
* @brief 硬件平台(MCU)相关的头文件,提供硬件运行的基本环境,一般是寄存器头文件。
* @details The header files related to the hardware platform(MCU) provide
* the basic environment for hardware operation, generally
* register header files..
**/
//example:#include "reg52.h"
/* Defines --------------------------------------------------------------*/
/**
* @brief 进入STS临界区宏函数,需要关闭相关定时器的中断。
* @details Enter the STS critical section macro function.
* It is necessary to turn off the interrupt of the related timer.
* @note 需要根据硬件平台,移植合适的关定时器中断代码。
* It is necessary to transplant the appropriate off-timer
* interrupt code according to the hardware platform.
**/
//ENTER_TMT_CRI_AREA() do{ __HAL_TIM_DISABLE_IT(&htim1,TIM_IT_UPDATE); }while(0) //32版本
//ENTER_TMT_CRI_AREA() do{ IT0 = 0; }while(0) //51版本
#define ENTER_STS_CRI_AREA()
/**
* @brief 退出STS临界区宏函数,需要打开相关定时器的中断。
* @details Enter the STS critical section macro function.
* It is necessary to turn on the interrupt of the related timer.
* @note 需要根据硬件平台,移植合适的开定时器中断代码。
* It is necessary to transplant the appropriate on-timer
* interrupt code according to the hardware platform.
*
**/
//#define EXTI_TMT_CRI_AREA() do{ __HAL_TIM_ENABLE_IT(&htim1,TIM_IT_UPDATE); }while(0) //32版本
//#define EXTI_TMT_CRI_AREA() do{ IT0 = 1; }while(0) //51版本
#define EXTI_STS_CRI_AREA()
/**
* @brief STS的变量类型重定义,如果有冲突,请配置为0。
* @details The variable type of STS is redefined.
* If there is a conflict, please configure it to 0..
**/
#if (0)
typedef unsigned char uint8_t; /*!< 8 bits */
typedef unsigned int uint16_t; /*!< 16 bits */
#endif
/*-----------------------------------------------------------------------
| CONFIG |
-----------------------------------------------------------------------*/
/**
* @brief 任务数量控制宏,用来确定STS需要调度的最大任务数量。
* @details The number of tasks control macro is used to
* determine the maximum number of tasks that STS
* needs to schedule.
**/
#define STS_TASK_NUM (8)
/**
* @brief 删除任务的风格,用来确定删除任务时是否按照创建任务的顺序排序,
* 用来确定任务同样的时间片调度时确定任务调用顺序。
* 1:按照创建任务顺序排序
* 0:删除任务时将最后一位任务放入将被删除的任务的位置
* @details The style of deleting tasks is used to determine whether to delete
* tasks in the order in which they were created, and to determine the
* order in which tasks are called when they are scheduled in the same
* time slice.
* 1:Sort by task creation order
* 0:When deleting a task, put the last task in the position of the task that will be deleted
**/
#define STS_DELETE_TASK_STYLE (0)
/*-----------------------------------------------------------------------
| DATA |
-----------------------------------------------------------------------*/
/**
* @brief 任务的执行状态枚举体。
* @details The execution status enumerator of the task.
**/
typedef enum
{
TASK_STOP = 1, /*!< 停止运行状态。*/
TASK_RUN = !TASK_STOP /*!< 继续运行状态。*/
} TASK_STATE_TYPE_E;
/**
* @brief STS函数自检枚举体,指示函数是否正常执行。
* STS function self checks enumerator.
* indicating whether the function is normally executed.
***/
typedef enum
{
FSC_FAIL = 1, /* Function self checking failed */
FSC_SUCCESS = !FSC_FAIL /* Function self checking successfed */
} FSC_STATE_TYPE_E;
/* Externs --------------------------------------------------------------*/
/*-----------------------------------------------------------------------
| API FUNCTION |
-----------------------------------------------------------------------*/
/**
* @brief STS的API操作函数结构体。
* @details The STS API manipulates the function structure.
**/
typedef struct
{
/**
* @brief STS更新任务调度tick时间。
* @details STS update task schedule tick time.
* @param[in] None.
* @return None.
* @note 在定时器中断服务函数中调用。
* Called in the timer interrupt service function.
* @example STS.Ticks();
**/
void (*Update_Tick) (void);
/**
* @brief STS运行函数,是任务调度器。
* @details STS runs the function, which is the task scheduler.
* @param[in] None.
* @return None.
* @note 在main函数的无限循环中调用。
* Called in the infinite loop of main.
* @example STS.Run();
**/
void (*Run) (void);
/**
* @brief STS创建一个任务函数。
* @details STS creates a task function.
* @param[in] entry 任务函数入口指针.
* A pointer function without formal parameters.
* @param[in] setTime 任务调度的时间 task run time (ticks)
* @return [FSC_SUCCESS]创建成功.Create successfully.
* @return [FSC_FAIL]创建失败. Create failed.
* @note 在main函数的无限循环中调用。
* Called in the infinite loop of main.
* @example STS.Create(Entry,500); //定时Entry任务为500ticks调度一次
**/
FSC_STATE_TYPE_E (*CreateTask) (void (*Entry) (void), uint16_t Set_Time);
/**
* @brief STS删除一个任务函数。
* @details STS creates a task function.
* @param[in] entry 任务函数入口指针.
* A pointer function without formal parameters.
* @return [FSC_SUCCESS]删除成功.Delete successfully.
* @return [FSC_FAIL]删除失败. Delete failed.
* @example STS.Delete(Enrty); //删除entry任务
**/
FSC_STATE_TYPE_E (*DeleteTask) (void (*Entry) (void));
/**
* @brief STS控制一个任务的调度时间函数。
* @details The STS controls the scheduling time function of a task.
* @param[in] entry 任务函数入口指针.
* A pointer function without formal parameters.
* @param[in] setTime 任务调度的时间 task run time (ticks)
* @return [FSC_SUCCESS]修改成功.The modification was successful.
* @return [FSC_FAIL]修改失败.The modification was failed.
* @example STS.Set_Task_Tick(Enrty,100); //修改entry任务为100ticks调度一次
**/
FSC_STATE_TYPE_E (*Set_Task_Tick) (void (*Entry) (void), uint16_t Set_Time);
/**
* @brief STS控制一个任务运行状态函数。
* @details STS controls a task running state function.
* @param[in] entry 任务函数入口指针.
* A pointer function without formal parameters.
* @param[in] state 任务运行状态.Task running status
* @return [FSC_SUCCESS]修改成功.The modification was successful.
* @return [FSC_FAIL]修改失败.The modification was failed.
* @example STS.Set_Task_RunState(Enrty,TASK_STOP); //修改entry任务为停止运行.
**/
FSC_STATE_TYPE_E (*Set_Task_RunState) (void (*Entry) (void), TASK_STATE_TYPE_E State);
} STS_TYPE_S;
/**
* @brief STS初始化函数,注册相关元素。
* @details The STS initializes the function
* and registers the associated elements.
* @param None.
* @return None.
**/
extern void STS_Init(void);
/**
* @brief 对外声明的STS操作函数结构体。
* @details TMT operation function structure declared externally.
* @note 所有需要被外部调用的函数,都包含在这个结构体中.
* All functions that need to be called externally
* are included in this structure.
**/
extern STS_TYPE_S STS;
#ifdef __cplusplus
}
#endif
#endif /*__STS_H_*/
c文件
/*
* @Author: Qiu Weian
* @Date: 2022-05-07 19:49:14
* @LastEditors: Qiu Weian
* @LastEditTime: 2022-05-09 12:09:10
* @Description:
*/
/*-----------------------------------------------------------------------
| FILE DESCRIPTION |
-----------------------------------------------------------------------*/
/*----------------------------------------------------------------------
- File name : stms.h
- Author : wan
- Update date : 2022.05.07
- Copyright(c) : All rights reserved.
-----------------------------------------------------------------------*/
/* Includes -------------------------------------------------------------*/
#include "sts.h"
/*-----------------------------------------------------------------------
| DATA |
-----------------------------------------------------------------------*/
/**
* @brief 最大任务数量宏,再封装一层。
* @details The maximum number of tasks is a macro,
* and then one layer is encapsulated.
**/
#define TASKS_MAX STS_TASK_NUM
STS_TYPE_S STS;
/**
* @brief STS的类,包含公共和私有两个属性。
* @details Class of STS, containing both pbl and pvt properties.
**/
typedef struct
{
void (*Entry) (void); /*!< 任务函数入口指针。*/
uint16_t Tim_Cnt; /*!< 任务调度时间计数器。*/
uint16_t Set_Time; /*!< 任务设置的调度时间。*/
uint8_t State; /*!< 任务运行状态。*/
} TASK_INFO_S;
typedef struct
{
TASK_INFO_S Tasks[TASKS_MAX]; /*!< 任务信息。*/
uint8_t Task_Num; /*!< 已经创建的任务数量。*/
} STS_PRIVATE_TYPE_S;
typedef struct
{
STS_TYPE_S public; /*!< 公共部分,对外开放的属性,具体定义在头文件。*/
STS_PRIVATE_TYPE_S private; /*!< 私有部分,仅限本文件内调用。*/
} STS_OBJECT_S;
static STS_OBJECT_S STS_Object; /*!< 创建内部对象,私有部分,仅限本文件内调用。*/
/*-----------------------------------------------------------------------
| FUNCTION |
-----------------------------------------------------------------------*/
/**
* @brief STS更新任务调度tick时间。
* @details STS update task schedule tick time.
* @param[in] None.
* @return None.
**/
static void STS_Update_Tick(void)
{
uint8_t i;
for (i = 0; i < STS_Object.private.Task_Num; i++)
{
/* If time arrives */
if (STS_Object.private.Tasks[i].Tim_Cnt > 0)
{
STS_Object.private.Tasks[i].Tim_Cnt--;
}
}
}
/**
* @brief STS运行函数,是任务调度器。
* @details STS runs the function, which is the task scheduler.
* @param[in] None.
* @return None.
**/
static void STS_Run(void)
{
uint8_t i;
for (i = 0; i < STS_Object.private.Task_Num; i++)
{
/* If time arrives */
if ((STS_Object.private.Tasks[i].Tim_Cnt == 0) && (STS_Object.private.Tasks[i].State != TASK_STOP))
{
STS_Object.private.Tasks[i].Tim_Cnt = STS_Object.private.Tasks[i].Set_Time;
/*
To prevent process conflict,
only one process can be executed in the same time period.
*/
if (STS_Object.private.Tasks[i].Entry != (void *)(0))
{
STS_Object.private.Tasks[i].Entry(); /* Run the task once */
}
}
}
}
/**
* @brief STS创建一个任务函数。
* @details STS creates a task function.
* @param[in] entry 任务函数入口指针.
* A pointer function without formal parameters.
* @param[in] set_time 任务调度的时间 task run time (ticks)
* @return [FSC_SUCCESS]创建成功.Create successfully.
* @return [FSC_FAIL]创建失败. Create failed.
**/
static FSC_STATE_TYPE_E STS_CreateTask(void (*Entry) (void), uint16_t Set_Time)
{
if (Entry == (void*)(0)) return FSC_FAIL;
if (STS_Object.private.Task_Num < TASKS_MAX)
{
STS_Object.private.Tasks[STS_Object.private.Task_Num].Entry = Entry;
STS_Object.private.Tasks[STS_Object.private.Task_Num].Set_Time = Set_Time;
STS_Object.private.Tasks[STS_Object.private.Task_Num].State = TASK_RUN;
STS_Object.private.Tasks[STS_Object.private.Task_Num].Tim_Cnt = Set_Time;
STS_Object.private.Task_Num++;
return FSC_SUCCESS;
}
else
{
return FSC_FAIL;
}
}
/**
* @brief STS删除一个任务函数。
* @details STS creates a task function.
* @param[in] entry 任务函数入口指针.
* A pointer function without formal parameters.
* @return [FSC_SUCCESS]删除成功.Delete successfully.
* @return [FSC_FAIL]删除失败. Delete failed.
**/
FSC_STATE_TYPE_E STS_DeleteTask(void (*Entry) (void))
{
#if (STS_DELETE_TASK_STYLE == 1)
uint8_t i,j,index;
TASK_INFO_S TasksTempInfo[TASKS_MAX] = {0};
#elif (STS_DELETE_TASK_STYLE == 0)
uint8_t i;
#endif
if (STS_Object.private.Task_Num > 0)
{
ENTER_STS_CRI_AREA();
for (i = 0; i < STS_Object.private.Task_Num; i++)
{
if (STS_Object.private.Tasks[i].Entry == Entry)
{
#if (STS_DELETE_TASK_STYLE == 1)
//record the task information after the task to be deleted
index = i;
for (j = 0;j < (STS_Object.private.Task_Num-index-1);j++)
{
TasksTempInfo[j].Entry = STS_Object.private.Tasks[index+1+j].Entry;
TasksTempInfo[j].Set_Time = STS_Object.private.Tasks[index+1+j].Set_Time;
TasksTempInfo[j].State = STS_Object.private.Tasks[index+1+j].State;
TasksTempInfo[j].Tim_Cnt = STS_Object.private.Tasks[index+1+j].Tim_Cnt;
}
//delete the task that needs to be deleted, and move the task behind it one space forward
for (j = 0; j < (STS_Object.private.Task_Num-index-1);j++)
{
STS_Object.private.Tasks[index+j].Entry = TasksTempInfo[j].Entry;
STS_Object.private.Tasks[index+j].Set_Time = TasksTempInfo[j].Set_Time;
STS_Object.private.Tasks[index+j].State = TasksTempInfo[j].State;
STS_Object.private.Tasks[index+j].Tim_Cnt = TasksTempInfo[j].Tim_Cnt;
}
//clear the last task information after the task is moved forward to 0
STS_Object.private.Tasks[STS_Object.private.Task_Num].Entry = (void*)(0);
STS_Object.private.Tasks[STS_Object.private.Task_Num].Set_Time = 0;
STS_Object.private.Tasks[STS_Object.private.Task_Num].State = TASK_STOP;
STS_Object.private.Tasks[STS_Object.private.Task_Num].Tim_Cnt = 0;
STS_Object.private.Task_Num--;
#elif (STS_DELETE_TASK_STYLE == 0)
//put the last task information in the position of the task that will be deleted
STS_Object.private.Task_Num--;
STS_Object.private.Tasks[i].Entry = STS_Object.private.Tasks[STS_Object.private.Task_Num].Entry;
STS_Object.private.Tasks[i].Set_Time = STS_Object.private.Tasks[STS_Object.private.Task_Num].Set_Time;
STS_Object.private.Tasks[i].State = STS_Object.private.Tasks[STS_Object.private.Task_Num].State;
STS_Object.private.Tasks[i].Tim_Cnt= STS_Object.private.Tasks[STS_Object.private.Task_Num].Tim_Cnt;
#endif
EXTI_STS_CRI_AREA();
return FSC_SUCCESS;
}
}
EXTI_STS_CRI_AREA();
}
EXTI_STS_CRI_AREA();
return FSC_FAIL;
}
/**
* @brief STS控制一个任务运行状态函数。
* @details STS controls a task running state function.
* @param[in] entry 任务函数入口指针.
* A pointer function without formal parameters.
* @param[in] state 任务运行状态.Task running status
* @return [FSC_SUCCESS]修改成功.The modification was successful.
* @return [FSC_FAIL]修改失败.The modification was failed.
**/
FSC_STATE_TYPE_E STS_Set_Task_Tick(void (*Entry) (void), uint16_t Set_Time)
{
uint8_t i;
for (i = 0; i < STS_Object.private.Task_Num; i++)
{
if (STS_Object.private.Tasks[i].Entry == Entry)
{
STS_Object.private.Tasks[i].Set_Time = Set_Time;
return FSC_SUCCESS;
}
}
return FSC_FAIL;
}
/**
* @brief STS控制一个任务运行状态函数。
* @details STS controls a task running state function.
* @param[in] entry 任务函数入口指针.
* A pointer function without formal parameters.
* @param[in] state 任务运行状态.Task running status
* @return [FSC_SUCCESS]修改成功.The modification was successful.
* @return [FSC_FAIL]修改失败.The modification was failed.
**/
FSC_STATE_TYPE_E STS_Set_Task_RunState(void (*Entry) (void), TASK_STATE_TYPE_E State)
{
uint8_t i;
for (i = 0; i < STS_Object.private.Task_Num; i++)
{
if (STS_Object.private.Tasks[i].Entry == Entry)
{
STS_Object.private.Tasks[i].State = State;
return FSC_SUCCESS;
}
}
return FSC_FAIL;
}
/**
* @brief STS初始化函数,注册相关元素。
* @details The STS initializes the function
* and registers the associated elements.
* @param None.
* @return None.
**/
void STS_Init(void)
{
STS_Object.public.CreateTask = STS_CreateTask;
STS_Object.public.DeleteTask = STS_DeleteTask;
STS_Object.public.Run = STS_Run;
STS_Object.public.Set_Task_RunState = STS_Set_Task_RunState;
STS_Object.public.Set_Task_Tick = STS_Set_Task_Tick;
STS_Object.public.Update_Tick = STS_Update_Tick;
STS_Object.private.Task_Num = 0;
STS = STS_Object.public;
}
/*-----------------------------------------------------------------------
| END OF FLIE. (C) COPYRIGHT zeweni |
-----------------------------------------------------------------------*/
说明
ENTER_STS_CRI_AREA()
EXTI_STS_CRI_AREA()
//进入/退出临街区域,作用用于一些不希望被中断打断的代码区域,因为这段代码的数据不希望被中断所修改。
//原TMT中只是关闭了定时器中断,但是遇到有其他中断也会修改数据时,最好的办法是将总中断关闭,这个地方需要移植。
#if (0)
//用于内部文件的变量定义,方便移植
typedef unsigned char uint8_t; /*!< 8 bits */
typedef unsigned int uint16_t; /*!< 16 bits */
#endif
//任务的最大数量,依据项目情况而定。
#define STS_TASK_NUM (8)
//删除任务的方式,
//定义为1:将会按照创建任务的顺序删除,比如有0->1->2->3->4时,需要删除2,那么删除之后会成为0->1->3->4
//定义为0:会将最后一个任务移动至删除的任务的位置,如:0->1->2>->3->4,删除2,会变成0->1->4->3
#define STS_DELETE_TASK_STYLE (0)
//移植时需要将STS.Update_Tick();放入定时器中断中,然后STS便会以这个时间基准来进行调度
void STS.Update_Tick();
//之后进行初始化然后在死循环中调用STS调度器即可
int main()
{
USE_USART_Init(115200);
USE_TIM_Init(7199,10);
STS_Init();
STS.CreateTask(Printf_100ms, 100);
STS.CreateTask(Printf_200ms, 100);
while(1)
{
STS.Run();
}
}
以上纯属个人见解,有误之处还望大家指正。