本帖最后由 pzsh 于 2021-8-31 13:41 编辑
最近在网上看到个TMT,简单的定时器调度系统~这不,我来看一下~
其实PIC18F16Q41的FLASH空间不小了,按道理移植RTOS都绰绰有余。
但是本质上都是定时器的调度~
不废话,先上MCC配置:
CLOCK(64M):
USART1(9600,N,8,1):
TIMER0(设置成1ms中断):
PIN(UART,LED,KEY):
编译生成代码:
加载TMT文件:
tmt.h(其中,进临界和出临界改成自己MCU对于的函数)
/*
* File: tmt.h
* Author: Administrator
*
* Created on August 31, 2021, 9:45 AM
*/
#ifndef TMT_H
#define TMT_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] 硬件平台相关的头文件,提供硬件运行的基本环境,一般是寄存器头文件。
* [url=home.php?mod=space&uid=1543424]@Details[/url] The header files related to the hardware platform provide
* the basic environment for hardware operation, generally
* register header files..
**/
#include "../mcc_generated_files/mcc.h"
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] 进入TMT临界区宏函数,需要关闭相关定时器的中断。
* [url=home.php?mod=space&uid=1543424]@Details[/url] Enter the TMT critical section macro function.
* It is necessary to turn off the interrupt of the related timer.
* [url=home.php?mod=space&uid=536309]@NOTE[/url] 需要根据硬件平台,移植合适的关定时器中断代码。
* It is necessary to transplant the appropriate off-timer
* interrupt code according to the hardware platform.
**/
//#define ENTER_TMT_CRI_AREA() do{ __HAL_TIM_DISABLE_IT(&htim1,TIM_IT_UPDATE); }while(0) //32版本
#define ENTER_TMT_CRI_AREA() do{ TMR0_StopTimer(); }while(0) //51版本
/**
* @brief 退出TMT临界区宏函数,需要打开相关定时器的中断。
* @details Enter the TMT critical section macro function.
* It is necessary to turn on the interrupt of the related timer.
* [url=home.php?mod=space&uid=536309]@NOTE[/url] 需要根据硬件平台,移植合适的开定时器中断代码。
* 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{ TMR0_StartTimer(); }while(0) //51版本
/**
* @brief TMT的变量类型重定义,如果有冲突,请配置为0。
* @details The variable type of TMT 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 任务数量控制宏,用来确定TMT需要调度的最大任务数量。
* @details The number of tasks control macro is used to
* determine the maximum number of tasks that TMT
* needs to schedule.
**/
#define TMT_TASK_NUM (8)
/*-----------------------------------------------------------------------
| DATA |
-----------------------------------------------------------------------*/
/**
* @brief 任务的执行状态枚举体。
* @details The execution status enumerator of the task.
**/
typedef enum
{
Task_Stop = 1, /*!< 停止运行状态。*/
Task_Continue = !Task_Stop /*!< 继续运行状态。*/
}TaskState_Type;
/**
* @brief TMT函数自检枚举体,指示函数是否正常执行。
* TMT function self checks enumerator.
* indicating whether the function is normally executed.
***/
typedef enum
{
TMT_NOK= 1, /* Function self checking failed */
TMT_OK = !TMT_NOK /* Function self checking successfed */
}TMT_FunState_Type;
/*-----------------------------------------------------------------------
| API FUNCTION |
-----------------------------------------------------------------------*/
/**
* @brief TMT初始化函数,注册相关元素。
* @details The TMT initializes the function
* and registers the associated elements.
* @param None.
* [url=home.php?mod=space&uid=266161]@return[/url] None.
**/
void TMT_Init(void);
/**
* @brief TMT的API操作函数结构体。
* @details The TMT API manipulates the function structure.
**/
typedef struct
{
/**
* @brief TMT更新任务调度tick时间。
* @details TMT update task schedule tick time.
* @param[in] None.
* [url=home.php?mod=space&uid=266161]@return[/url] None.
* @note 在定时器中断服务函数中调用。
* Called in the timer interrupt service function.
* [url=home.php?mod=space&uid=389923]@example[/url] TMT.Tick();
**/
void (*Tick) (void);
/**
* @brief TMT运行函数,是任务调度器。
* @details TMT runs the function, which is the task scheduler.
* @param[in] None.
* @return None.
* @note 在main函数的无限循环中调用。
* Called in the infinite loop of main.
* [url=home.php?mod=space&uid=389923]@example[/url] TMT.Run();
**/
void (*Run) (void);
/**
* @brief TMT创建一个任务函数。
* @details TMT creates a task function.
* @param[in] entry 任务函数入口指针.
* A pointer function without formal parameters.
* @param[in] setTime 任务调度的时间 task run time (ticks)
* @return [TMT_OK]创建成功.Create successfully.
* @return [TMT_NOK]创建失败. Create failed.
* @note 在main函数的无限循环中调用。
* Called in the infinite loop of main.
* @example TMT.Create(enrty,500); //定时entry任务为500ticks调度一次
**/
TMT_FunState_Type (*Create) (void (*entry) (void), uint16_t setTime);
/**
* @brief TMT删除一个任务函数。
* @details TMT creates a task function.
* @param[in] entry 任务函数入口指针.
* A pointer function without formal parameters.
* @return [TMT_OK]删除成功.Delete successfully.
* @return [TMT_NOK]删除失败. Delete failed.
* @example TMT.Delete(enrty); //删除entry任务
**/
TMT_FunState_Type (*Delete) (void (*entry) (void));
/**
* @brief TMT控制一个任务的调度时间函数。
* @details The TMT 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 [TMT_OK]修改成功.The modification was successful.
* @return [TMT_NOK]修改失败.The modification was failed.
* @example TMT.TimeCtrl(enrty,100); //修改entry任务为100ticks调度一次
**/
TMT_FunState_Type (*TimeCtrl) (void (*entry) (void), uint16_t setTime);
/**
* @brief TMT控制一个任务运行状态函数。
* @details TMT controls a task running state function.
* @param[in] entry 任务函数入口指针.
* A pointer function without formal parameters.
* @param[in] state 任务运行状态.Task running status
* @return [TMT_OK]修改成功.The modification was successful.
* @return [TMT_NOK]修改失败.The modification was failed.
* @example TMT.RunCtrl(enrty,Task_Stop); //修改entry任务为停止运行.
**/
TMT_FunState_Type (*RunCtrl) (void (*entry) (void), TaskState_Type state);
}TMT_Type;
/**
* @brief 对外声明的TMT操作函数结构体。
* @details TMT operation function structure declared externally.
* @note 所有需要被外部调用的函数,都包含在这个结构体中.
* All functions that need to be called externally
* are included in this structure.
**/
extern TMT_Type TMT;
#ifdef __cplusplus
}
#endif
#endif /* TMT_H */
TMT.C
/*-----------------------------------------------------------------------
| FILE DESCRIPTION |
-----------------------------------------------------------------------*/
/*----------------------------------------------------------------------
- File name : TMT.c
- Author : zeweni
- Update date : 2020.06.26
- Copyright(c) : 2020-2021 zeweni. All rights reserved.
-----------------------------------------------------------------------*/
/*------------------------------------------------------------------------
| COPYRIGHT NOTICE |
------------------------------------------------------------------------*/
/*
* Copyright (C) 2021, zeweni (17870070675@163.com)
* This file is part of task management time slice framework.
* Abbreviated as TMT.
* Task management time slice framework is free software: you can redist-
* ribute it and/or modify it under the terms of the Apache-2.0 License.
* Task management time slice framework is distributed in the hope that it
* will be useful,but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Apache-2.0 License for more details.
* You should have received a copy of the Apache-2.0 License.Task management
* time slice framework. If not, see <http://www.apache.org/licenses/>.
**/
/*-----------------------------------------------------------------------
| INCLUDES |
-----------------------------------------------------------------------*/
#include "TMT.h"
/*-----------------------------------------------------------------------
| DATA |
-----------------------------------------------------------------------*/
/**
* @brief 最大任务数量宏,再封装一层。
* @details The maximum number of tasks is a macro,
* and then one layer is encapsulated.
**/
#define TASKS_MAX TMT_TASK_NUM
/**
* @brief 定义TMT相关操作函数结构体。
* @details Define the structure of the TMT related operation functions.
**/
TMT_Type TMT;
/**
* @brief TMT的类,包含公共和私有两个属性。
* @details Class of TMT, containing both public and private properties.
**/
static struct Class
{
TMT_Type Public; /*!< 公共部分,对外开放的属性,具体定义在头文件。*/
struct Private /*!< 私有部分,仅限本文件内调用。*/
{
struct
{
void (* Entry) (void); /*!< 任务函数入口指针。*/
uint16_t TIMCount; /*!< 任务调度时间计数器。*/
uint16_t SetTime; /*!< 任务设置的调度时间。*/
uint8_t State; /*!< 任务运行状态。*/
}Comp[TASKS_MAX];
uint8_t Num; /*!< 已经创建的任务数量。*/
}Private;
}Object;
/*-----------------------------------------------------------------------
| FUNCTION |
-----------------------------------------------------------------------*/
/**
* @brief TMT更新任务调度tick时间。
* @details TMT update task schedule tick time.
* @param[in] None.
* @return None.
**/
static void TMT_Update_Tick_t(void)
{
uint8_t i;
for(i = 0; i< Object.Private.Num; i++)
{
/* If time arrives */
if(Object.Private.Comp[i].TIMCount > 0 )
{
Object.Private.Comp[i].TIMCount--;
}
}
}
/**
* @brief TMT运行函数,是任务调度器。
* @details TMT runs the function, which is the task scheduler.
* @param[in] None.
* @return None.
**/
static void TMT_Run_t(void)
{
uint8_t index;
for(index = 0; index < Object.Private.Num; index++)
{
/* If time arrives */
if(Object.Private.Comp[index].TIMCount == 0 && Object.Private.Comp[index].State != Task_Stop)
{
Object.Private.Comp[index].TIMCount = Object.Private.Comp[index].SetTime;
/*
To prevent process conflict,
only one process can be executed in the same time period.
*/
if(Object.Private.Comp[index].Entry != (void*)(0) )
{
Object.Private.Comp[index].Entry(); /* Run task */
}
}
}
}
/**
* @brief TMT创建一个任务函数。
* @details TMT creates a task function.
* @param[in] entry 任务函数入口指针.
* A pointer function without formal parameters.
* @param[in] setTime 任务调度的时间 task run time (ticks)
* @return [TMT_OK]创建成功.Create successfully.
* @return [TMT_NOK]创建失败. Create failed.
**/
static TMT_FunState_Type TMT_Create_t(void (*entry) (void),uint16_t setTime)
{
static uint8_t task_num = 0; /* Initialize to 0 */
if(task_num < TASKS_MAX)
{
Object.Private.Comp[task_num].Entry = entry;
Object.Private.Comp[task_num].SetTime = setTime;
Object.Private.Comp[task_num].TIMCount = setTime;
Object.Private.Comp[task_num].State = Task_Continue;
task_num += 1;
Object.Private.Num = task_num;
return TMT_OK;
}
else
{
return TMT_NOK;
}
}
/**
* @brief TMT删除一个任务函数。
* @details TMT creates a task function.
* @param[in] entry 任务函数入口指针.
* A pointer function without formal parameters.
* @return [TMT_OK]删除成功.Delete successfully.
* @return [TMT_NOK]删除失败. Delete failed.
**/
static TMT_FunState_Type TMT_Delete_t(void (*entry) (void))
{
uint8_t index;
if(Object.Private.Num > 0)
{
ENTER_TMT_CRI_AREA();
for(index = 0; index < Object.Private.Num; index++)
{
if(Object.Private.Comp[index].Entry == entry)
{
Object.Private.Num--;
Object.Private.Comp[index].Entry = Object.Private.Comp[Object.Private.Num].Entry;
Object.Private.Comp[index].SetTime = Object.Private.Comp[Object.Private.Num].SetTime;
Object.Private.Comp[index].TIMCount = Object.Private.Comp[Object.Private.Num].TIMCount;
Object.Private.Comp[index].State = Object.Private.Comp[Object.Private.Num].State;
EXTI_TMT_CRI_AREA();
return TMT_OK;
}
}
}
EXTI_TMT_CRI_AREA();
return TMT_NOK;
}
/**
* @brief TMT控制一个任务运行状态函数。
* @details TMT controls a task running state function.
* @param[in] entry 任务函数入口指针.
* A pointer function without formal parameters.
* @param[in] state 任务运行状态.Task running status
* @return [TMT_OK]修改成功.The modification was successful.
* @return [TMT_NOK]修改失败.The modification was failed.
**/
static TMT_FunState_Type TMT_RunCtrl_t(void (*entry)(void),TaskState_Type state)
{
uint8_t index;
for(index = 0; index<Object.Private.Num; index++)
{
if(Object.Private.Comp[index].Entry == entry)
{
Object.Private.Comp[index].State = state;
return TMT_OK;
}
}
return TMT_NOK;
}
/**
* @brief TMT控制一个任务的调度时间函数。
* @details The TMT controls the scheduling time function of a task.
* @param[in] *taskFunc (void) 任务函数入口指针.
* A pointer function without formal parameters.
* @param[in] setTime 任务调度的时间 task run time (ticks)
* @return [TMT_OK]修改成功.The modification was successful.
* @return [TMT_NOK]修改失败.The modification was failed.
**/
static TMT_FunState_Type TMT_TimeCtrl_t(void (*entry) (void),uint16_t setTime)
{
uint8_t index;
for(index = 0; index< Object.Private.Num; index++)
{
if(Object.Private.Comp[index].Entry == entry)
{
Object.Private.Comp[index].TIMCount = setTime;
Object.Private.Comp[index].SetTime = setTime;
return TMT_OK;
}
}
return TMT_NOK;
}
/**
* @brief TMT初始化函数,注册相关元素。
* @details The TMT initializes the function
* and registers the associated elements.
* @param None.
* @return None.
**/
void TMT_Init(void)
{
Object.Public.Run = TMT_Run_t;
Object.Public.Tick = TMT_Update_Tick_t;
Object.Public.Create = TMT_Create_t;
Object.Public.Delete = TMT_Delete_t;
Object.Public.TimeCtrl = TMT_TimeCtrl_t;
Object.Public.RunCtrl = TMT_RunCtrl_t;
Object.Private.Num = 0;
TMT = Object.Public;
}
/*-----------------------------------------------------------------------
| END OF FLIE. (C) COPYRIGHT zeweni |
-----------------------------------------------------------------------*/
在timer0中断函数里面添加TMT核心任务处理函数:
#include "../TMT/tmt.h"
volatile uint32_t mscnt=0;
void TMR0_CallBack(void)
{
// Add your custom callback code here
mscnt++;
if(mscnt>=500)
{
//LED0_Toggle();
mscnt=0;
}
TMT.Tick();
if(TMR0_InterruptHandler)
{
TMR0_InterruptHandler();
}
}
在main函数里面新建2个任务,并运行(主要开总中断):
#include "mcc_generated_files/mcc.h"
#include "tmt/tmt.h"
void TMT_Demo0(void)
{
LED0_Toggle();
}
uint8_t j=0;
void TMT_Demo1(void)
{
printf("the j is %d!\r\n",j++);
}
/*
Main application
*/
void main(void)
{
uint8_t i=0;
// Initialize the device
SYSTEM_Initialize();
// If using interrupts in PIC18 High/Low Priority Mode you need to enable the Global High and Low Interrupts
// If using interrupts in PIC Mid-Range Compatibility Mode you need to enable the Global Interrupts
// Use the following macros to:
TMT_Init();
TMT.Create(TMT_Demo0,500);
TMT.Create(TMT_Demo1,500);
// Enable the Global Interrupts
INTERRUPT_GlobalInterruptEnable();
// Disable the Global Interrupts
//INTERRUPT_GlobalInterruptDisable();
while (1)
{
// Add your application code
//printf("the i is %d!\r\n",i++);
// __delay_ms(300);
TMT.Run();
}
}
下载,运行:
看串口输出端:
看板上LED:
虽然简单,但是很好的诠释了系统调度的流程,好了,今天就到这!
谢谢观看~
|