STM32F103xx毫秒级任务管理器、调度器(动态任务创建的方式实现)

一、 任务数据类型结构体


/* 任务回调函数类型 */
typedef void(* TaskFunction)(void);

/* 字节对齐 */
#pragma pack(1)

typedef struct MsecTask
{
    TaskFunction TaskCallback;      //任务回调函数
    uint8_t  State;                 //任务状态
    uint32_t PeriodTimes;           //任务运行周期时间
    uint32_t PrevTimes;             //上次运行时间
    uint32_t CostTimes;             //花费时间
    uint32_t ErrorTimes;            //误差时间
    struct MsecTask * pNextTask;    //下一个任务
}MsecTask_Typedef, * MsecTask_Typedef_t;

二、 任务管理器数据类型结构体


typedef struct MsecTaskManager
{
    MsecTask_Typedef * pTaskHead;//任务链表头
    MsecTask_Typedef * pTaskTail;//任务链表尾


    /* 注册任务 */
    MsecTask_Typedef * (* Register)(struct MsecTaskManager * taskManager, TaskFunction taskCallback, uint32_t tims_ms, uint8_t state);

    /* 运行任务管理器 */
    void (* Running)(struct MsecTaskManager * taskManager, uint32_t tick);

    /* 设置任务运行时间 */
    uint8_t (* SetTaskPeriodTime)(struct MsecTaskManager * taskManager, TaskFunction taskCallback, uint32_t tims_ms);

    /* 获取任务状态 */
    uint8_t (* GetTaskState)(struct MsecTaskManager * taskManager, TaskFunction taskCallback);

    /* 设置任务状态 */
    uint8_t (* SetTaskState)(struct MsecTaskManager * taskManager, TaskFunction taskCallback, uint8_t state);

    /* 获取误差时间 */
    uint32_t (* GetTaskErrorTimes)(struct MsecTaskManager * taskManager, TaskFunction taskCallback);

    /* 查找任务 */
    MsecTask_Typedef * (* FindTask)(struct MsecTaskManager * taskManager, TaskFunction taskCallback);

    /* 获取上一个任务 */
    MsecTask_Typedef * (* GetPrevTask)(struct MsecTaskManager * taskManager, MsecTask_Typedef * task);

    /* 删除一个任务 */
    uint8_t (* DeleteTask)(struct MsecTaskManager * taskManager, TaskFunction taskCallback);


#if ( MTM_MCU_USE_RATIO_ENABLE > 0 )
    /* 获取处理器利用率 */
    uint8_t (* GetMicroProcessorUseRatio)(struct MsecTaskManager * taskManager);

    /* 获取任务运行的时间 */
    uint32_t (* GetTaskRunningTimes)(struct MsecTaskManager * taskManager, TaskFunction taskCallback);

    /* 所有任务运行的总时间 */
    uint32_t TaskRunTotalTimes;
#endif


}MsecTaskManager_Typedef, * MsecTaskManager_Typedef_t;

三、获取系统运行的Tick、获取时差

  1. 系统时钟72MHZ,SysTick_Handler()嘀嗒定时器1ms中断

#define SYSTICK_LOADVALUE       72000//(SystemCoreClock/1000U)
#define CYCLES_PER_MICROSECOND  72//(SystemCoreClock/1000000U)

/* 获取系统运行的Tick */
static uint32_t ulGetSystemTick(void)
{
    extern __IO uint32_t uwTick;
    return (uwTick * 1000 + (SYSTICK_LOADVALUE-SysTick->VAL)/CYCLES_PER_MICROSECOND); 
}


/* 获取时差 */
static uint32_t ulGetTickDifference(uint32_t curTick, uint32_t preTick)
{
    uint32_t diffTick = 0;

    if (curTick >= preTick)
    {
        diffTick = curTick - preTick;
    }
    else
    {
        diffTick = 0xFFFFFFFF - preTick + 1;
        diffTick += curTick;
    }

    return diffTick;
}

四、查找任务

在这里插入图片描述


/* 查找任务 */
static MsecTask_Typedef * pStuTaskManager_FindTask(struct MsecTaskManager * taskManager, TaskFunction taskCallback)
{
    MsecTask_Typedef * nowTask = NULL;
    MsecTask_Typedef * resTask = NULL;


	/* 从任务链表头部开始查找 */
    nowTask = taskManager->pTaskHead;

    while(nowTask != NULL)
    {
        /* 任务函数相同 */
        if (nowTask->TaskCallback == taskCallback)
        {
            resTask = nowTask;
            break;
        }

        /* 移动到下一个任务链表节点 */
        nowTask = nowTask->pNextTask;
    }

    return resTask;
}

五、注册任务

在这里插入图片描述

/* 注册任务 */
static MsecTask_Typedef * pStuTaskManager_Register(struct MsecTaskManager * taskManager, TaskFunction taskCallback, uint32_t tims_ms, uint8_t state)
{
    MsecTask_Typedef * task = NULL;


    /* 任务是否存在 */
    task = taskManager->FindTask(taskManager, taskCallback);

    /* 任务已存在 更新周期和状态 上次运行的时刻 */
    if (task != NULL)
    {
        task->State       = state; /* 任务状态 */
        task->PrevTimes   = ulGetSystemTick(); //上次运行的时刻
        task->PeriodTimes = tims_ms; /* 任务运行周期时间 */
		return task;
    }

    /* 任务不存在 为新任务申请内存 */
    task = (MsecTask_Typedef *)malloc(sizeof(MsecTask_Typedef));

    /* 内存申请失败 */
    if (task == NULL)
    {
        return NULL;
    }
	

    /* 初始化任务参数 */
    task->CostTimes    = 0;             //任务运行花费时间
    task->ErrorTimes   = 0;             //任务运行误差时间
    task->pNextTask    = NULL;          //从任务链表尾部插入任务
    task->State        = state;         //任务状态
    task->PeriodTimes  = tims_ms;       //任务运行周期时间
    task->TaskCallback = taskCallback;  //任务回调
    task->PrevTimes    = ulGetSystemTick(); //上次运行的时刻


    /* 任务链表为空 第一个任务为头部 */
    if (taskManager->pTaskHead == NULL)
    {
        /* 链表头部任务 */
        taskManager->pTaskHead = task;
    }
    else
    {
        /* 从任务链表尾部插入新任务 */
        taskManager->pTaskTail->pNextTask = task;
    }

    /* 更新链表尾部任务 新插入的任务作为链表尾部 */
    taskManager->pTaskTail = task;

	return task;
}

六、设置、获取任务状态


/* 设置任务状态 */
static uint8_t ubTaskManager_SetTaskState(struct MsecTaskManager * taskManager, TaskFunction taskCallback, uint8_t state)
{
    MsecTask_Typedef * memTask = NULL;

    /* 从任务链表中查找任务是否存在 */
    memTask = taskManager->FindTask(taskManager, taskCallback);
	
    /* 任务不存在*/
    if (memTask == NULL)
    {
        return 1;
    }

    /* 设置任务状态 */
	memTask->State = state;
	
	return 0;
}


/* 获取任务状态 */
static uint8_t ubTaskManager_GetTaskState(struct MsecTaskManager * taskManager, TaskFunction taskCallback)
{
    MsecTask_Typedef * memTask = NULL;
    uint8_t taskState = 0xFF;


    /* 从任务链表中查找任务是否存在 */
    memTask = taskManager->FindTask(taskManager, taskCallback);

    /* 任务不存在*/
    if (memTask == NULL)
    {
        return 1;
    }

    /* 获取任务状态 */
    taskState = memTask->State;

    return taskState;
}

七、设置任务运行周期时间


/* 设置任务运行周期时间 */
uint8_t ubTaskManager_SetTaskPeriodTime(struct MsecTaskManager * taskManager, TaskFunction taskCallback, uint32_t tims_ms)
{
    MsecTask_Typedef * memTask = NULL;

    /* 从任务链表中查找任务是否存在 */
    memTask = taskManager->FindTask(taskManager, taskCallback);

    /* 任务不存在*/
    if (memTask == NULL)
    {
        return 1;
    }

    /* 设置任务运行周期时间 */
	memTask->PeriodTimes = tims_ms;
	
	return 0;
}

八、获取任务误差时间

/* 获取任务误差时间 */
static uint32_t ulTaskManager_GetTaskErrorTimes(struct MsecTaskManager * taskManager, TaskFunction taskCallback)
{
    MsecTask_Typedef * memTask = NULL;
	uint32_t errorTimes = 0;


    /* 从任务链表中查找任务是否存在 */
    memTask = taskManager->FindTask(taskManager, taskCallback);

    /* 任务不存在*/
    if (memTask == NULL)
    {
        return 0xFFFFFFFFUL;
    }

    /* 获取任务误差时间 */
	errorTimes = memTask->ErrorTimes;
	
	return errorTimes;
}

九、获取上一个任务

/* 获取上一个任务 */
static MsecTask_Typedef * pStuTaskManager_GetPrevTask(struct MsecTaskManager * taskManager, MsecTask_Typedef * task)
{
    MsecTask_Typedef * nowTask = NULL;
    MsecTask_Typedef * resTask = NULL;

    /* 从任务链表头开始处理 */
    nowTask = taskManager->pTaskHead;

    while (1)
    {
        /* 空任务节点 */
        if (nowTask == NULL)
        {
            break;
        }

        /* 下个任务与查找的任务相同 */
        if (nowTask->pNextTask == task)
        {
            /* 当前任务为上一个任务 */
            resTask = nowTask;
            break;
        }

        /* 下一个任务节点 */
        nowTask = nowTask->pNextTask;
    }

    return resTask;
}

十、查找任务


/* 删除一个任务 */
uint8_t ubTaskManager_DeleteTask(struct MsecTaskManager * taskManager, TaskFunction taskCallback)
{
    MsecTask_Typedef * memTask  = NULL;
    MsecTask_Typedef * prevTask = NULL;
    MsecTask_Typedef * nextTask = NULL;

    /* 从任务链表中查找任务是否存在 */
    memTask = taskManager->FindTask(taskManager, taskCallback);

    /* 任务不存在*/
    if (memTask == NULL)
    {
        return 1;
    }

    /* 查找当前任务的上一个任务是否存在 */
    prevTask = taskManager->GetPrevTask(taskManager, memTask);

    /* 获取当前任务的下一个任务 */
    nextTask = memTask->pNextTask;

    if((prevTask == NULL) && (nextTask == NULL))
    {
        /* 当前任务列表只有一个任务 */
        taskManager->pTaskHead = taskManager->pTaskTail = NULL;
    }
    else if((prevTask == NULL) && (nextTask != NULL))
    {
        /* 当前任务为任务链表的头部任务 */
        taskManager->pTaskHead = nextTask;
    }
    else if((prevTask != NULL) && (nextTask == NULL))
    {
        /* 当前任务为任务链表的尾部任务 */
        taskManager->pTaskTail = prevTask;
        prevTask->pNextTask = NULL;
    }
    else if((prevTask != NULL) && (nextTask != NULL))
    {
        /*当前任务为中间任务 上一个和下一个任务都存在 */
        prevTask->pNextTask = nextTask;
    }
    else
    {
        return 2;
    }

    /* 释放任务内存 */
    free(memTask);

    memTask = NULL;

    return 0; 
}


十一、获取处理器利用率 、任务运行时间


#if ( MTM_MCU_USE_RATIO_ENABLE > 0 )

/* 获取处理器利用率 */
static uint8_t usTaskManager_GetMicroProcUseRatio(struct MsecTaskManager * taskManager)
{
    static uint32_t startTick = 0;
    uint8_t useRatio = 0;

    useRatio = taskManager->TaskRunTotalTimes / (ulGetSystemTick() - startTick);

    if (useRatio > 100)
    {
        useRatio = 100;
    }

    taskManager->TaskRunTotalTimes = 0;
    startTick = ulGetSystemTick();

    return useRatio;
}



/* 获取任务运行花费时间 */
static uint32_t ulTaskManager_GetTaskRunTimes(struct MsecTaskManager * taskManager, TaskFunction taskCallback)
{
    MsecTask_Typedef * memTask = NULL;
	uint32_t takeTimes = 0;


    /* 从任务链表中查找任务是否存在 */
    memTask = taskManager->FindTask(taskManager, taskCallback);

    /* 任务不存在*/
    if (memTask == NULL)
    {
        return 0;
    }

    /* 获取任务运行时间 */
	takeTimes = memTask->CostTimes;
	
	return takeTimes;

}
#endif

十二、运行任务管理


/* 运行任务管理 */
static void vTaskManager_Running(struct MsecTaskManager * taskManager, uint32_t tick)
{
    MsecTask_Typedef * nowTask = NULL;
    uint32_t diffTick = 0;


    /* 从任务链表头开始处理 */
    nowTask = taskManager->pTaskHead;

    while (1)
    {
        /* 任务不存在 */
        if (nowTask == NULL)
        {
            break;
        }

        /* 任务状态和任务回调有效 */
        if ((nowTask->State) && (nowTask->TaskCallback != NULL))
		{
            /* 获取时间差 */
            diffTick = ulGetTickDifference(tick, nowTask->PrevTimes);

            /* 时间差大于任务运行周期时间 */
            if (diffTick >= nowTask->PeriodTimes)
            {
                /* 保存误差时间 */
				nowTask->ErrorTimes = diffTick - nowTask->PeriodTimes;
				
                /* 记录任务运行时刻 */
                nowTask->PrevTimes = tick;

                #if ( MTM_MCU_USE_RATIO_ENABLE > 0 )

                /* 获取当前时刻 */
                uint32_t startTick = ulGetSystemTick();

                /* 运行任务回调 */
				nowTask->TaskCallback();

                /* 记录任务回调运行花费的时间 */
                nowTask->CostTimes = ulGetTickDifference(ulGetSystemTick(), startTick);
				
				/* 所有任务运行花费总时间 */
                taskManager->TaskRunTotalTimes += nowTask->CostTimes;

                #else

                /* 运行任务回调 */
				nowTask->TaskCallback();

                #endif

            }
		}

        /* 下一个任务 */
        nowTask = nowTask->pNextTask;
    }
}

十三、初始化毫秒级任务管理器


/* 初始化毫秒级任务管理器 */
void vInit_MsecTaskManager(MsecTaskManager_Typedef * taskManager)
{
    taskManager->pTaskHead = NULL;  /* 任务链表头 */
    taskManager->pTaskTail = NULL;  /* 任务链表尾 */


    taskManager->Running             = vTaskManager_Running;                /* 运行任务管理 */
    taskManager->FindTask            = pStuTaskManager_FindTask;            /* 查找任务 */
    taskManager->Register            = pStuTaskManager_Register;            /* 注册任务 */
    taskManager->DeleteTask          = ubTaskManager_DeleteTask;            /* 删除一个任务 */
    taskManager->SetTaskState        = ubTaskManager_SetTaskState;          /* 设置任务状态 */
    taskManager->GetTaskState        = ubTaskManager_GetTaskState;          /* 获取任务状态 */
    taskManager->GetPrevTask         = pStuTaskManager_GetPrevTask;         /* 获取上一个任务 */
    taskManager->GetTaskErrorTimes   = ulTaskManager_GetTaskErrorTimes;     /* 获取误差时间 */
    taskManager->SetTaskPeriodTime   = ubTaskManager_SetTaskPeriodTime;     /* 设置任务运行周期时间 */
    
	
#if ( MTM_MCU_USE_RATIO_ENABLE > 0 )
    taskManager->GetTaskRunningTimes       = ulTaskManager_GetTaskRunTimes;      /* 获取任务运行时间 */
    taskManager->GetMicroProcessorUseRatio = usTaskManager_GetMicroProcUseRatio; /* 获取处理器利用率 */
#endif
	
}

十四、验证例程

static void vTask1_Demo(void)
{
	HAL_GPIO_TogglePin(USER_LED0_GPIO_Port, USER_LED0_Pin);
}

static void vTask2_Demo(void)
{
	HAL_GPIO_TogglePin(USER_LED0_GPIO_Port, USER_LED6_Pin);
}

static void vTask3_Demo(void)
{
	HAL_GPIO_TogglePin(USER_LED0_GPIO_Port, USER_LED2_Pin);
}

static void vDebug_Demo(void)
{
	uint32_t takeTimer[3]  = {0};
	uint32_t errorTimer[3] = {0};
	
	takeTimer[0] = AppMsecTaskManager.GetTaskRunningTimes(&AppMsecTaskManager, vTask1_Demo);
	takeTimer[1] = AppMsecTaskManager.GetTaskRunningTimes(&AppMsecTaskManager, vTask2_Demo);
	takeTimer[2] = AppMsecTaskManager.GetTaskRunningTimes(&AppMsecTaskManager, vTask3_Demo);
	
	errorTimer[0] = AppMsecTaskManager.GetTaskErrorTimes(&AppMsecTaskManager, vTask1_Demo);
	errorTimer[1] = AppMsecTaskManager.GetTaskErrorTimes(&AppMsecTaskManager, vTask2_Demo);
	errorTimer[2] = AppMsecTaskManager.GetTaskErrorTimes(&AppMsecTaskManager, vTask3_Demo);
	
	printf("Name    Period    Take    Error\r\n");
	printf("Task1   %-8d  %-8d  %d\r\n", 1000, takeTimer[0] , errorTimer[0]);
	printf("Task2   %-8d  %-8d  %d\r\n", 500,  takeTimer[1] , errorTimer[1]);
	printf("Task3   %-8d  %-8d  %d\r\n", 200,  takeTimer[2] , errorTimer[2]);
}


void vRegister_Task(void)
{
    AppMsecTaskManager.Register(&AppMsecTaskManager, vTask1_Demo, 1000, 1);
    AppMsecTaskManager.Register(&AppMsecTaskManager, vTask2_Demo, 500,  1);
    AppMsecTaskManager.Register(&AppMsecTaskManager, vTask3_Demo, 2000, 1);
	
	AppMsecTaskManager.Register(&AppMsecTaskManager, vDebug_Demo, 5000, 1);
}

十五、主函数


int main(void)
{
	HAL_Init();
    SystemClock_Config();
	SystemCoreClockUpdate();

    MX_GPIO_Init();
    MX_USART1_UART_Init();
	printf("Init USART OK...\r\n");
	
	vInit_MsecTaskManager(&AppMsecTaskManager);
	printf("Msec Task Manager OK...\r\n");
	vRegister_Task();
	
    while (1)
    {
		AppMsecTaskManager.Running(&AppMsecTaskManager, HAL_GetTick());
    }
}

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值