裸机程序架构-时间片轮询架构

本文介绍了XxxTimeSlice,一种基于定时器中断的裸机程序架构,它允许任务按预设频率执行,适合资源有限的单片机项目。文章详细描述了如何配置、注册任务并启动时间片轮询,以及注意事项,如结合状态机优化任务执行效率。
摘要由CSDN通过智能技术生成

XxxTimeSlice

介绍

简介

XxxTimeSlice时间片轮询,是一种裸机程序架构。基于外部提供的tick(systick中断或定时器中断),根据注册生成多种时间片(支持0*tick)提供给任务当tick,让多个任务按指定频率依次执行。其核心思想是定时器的分时复用。适合中小型项目的裸机开发,结合状态机可以有效消除程序中不合理的delay阻塞延时。

获取方式

我的CSDN资源
源码仓库

特性

  • 基于链表,注册时方便且不限数量;
  • 支持0tick,即非定时任务的注册;

本人实际应用场景

1. 资源比较紧张的单片机项目中;

期待别的小伙伴能应用到其他的场景中,最大化开发驱动潜力

格式

编码格式:UTF-8
注释格式:doxygen

文件介绍

Example

提供了示例例程;

README_Picture

README文档内用到的图片

LICENSE

许可证,遵循MIT协议

README.md

说明文档

XxxTimeSlice.c 和 XxxTimeSlice.h

核心代码


注意事项

  • 该架构并没有中途切换任务、上下文切换等操作系统的功能,所以仍然存在裸机开发的通病,每个任务会相互影响实时性,所以应当尽可能设计让任务占用cpu时间越短(特别是频繁执行的),建议结合状态机思想编程,合理让功能分段执行,且有效消除代码中不合理的delay阻塞延时;

使用流程

提醒

  • 由于使用到"for(声明;表达式;表达式)"的特性,请选择C99或以上的标准;

移植

把XxxTimeSlice.c与XxxTimeSlice.h两个文件复制粘贴到自己工程内即可。

应用步骤

  1. 配置好systick或定时器中断;
  2. XxxTimeSlice_Produce()填进对应中断服务函数中;
  3. 定义STR_XxxTimeSlice对象;
  4. 准备好任务函数;
  5. 调用XxxTimeSlice_Register()注册任务;
  6. 调用XxxTimeSlice_Start()启动时间片轮询;
应用模版
#include "XxxTimeSlice.h"
#include "stm32f10x.h"


/********************************************systick中断服务函数********************************************/
/*2.在systick中断服务函数中调用XxxTimeSlice_Produce*/
void SysTick_Handler(void)
{
    XxxTimeSlice_Produce();
}
/********************************************systick中断服务函数 End********************************************/
/*3.定义时间片对象*/
STR_XxxTimeSlice m_timeSlice_1;
/*4.任务函数*/
void Task_1(void)
{
    ...
    return;                         /* 可以仿真打断点看进来的时间是否对应 或 自行添加打印语句 */
}
STR_XxxTimeSlice m_timeSlice_2;
void Task_2(void)
{
    ...
    return;                         /* 可以仿真打断点看进来的时间是否对应 或 自行添加打印语句 */
}


int main(void)
{
    /*1.配置systick*/
    SysTick_Config(SystemCoreClock/ 1000);                  /* 1ms的Tick */

    /*5.注册任务*/
    XxxTimeSlice_Register(&m_timeSlice_1, Task_1, 0);       /* 0,即非定时任务(每次轮询都会执行) */
    XxxTimeSlice_Register(&m_timeSlice_2, Task_2, 10);      /* 10*1ms,即10ms运行一次 */

    /*6.启动时间片轮询*/
    XxxTimeSlice_Start();
}

完整示例MDK工程在源码仓库


代码说明

头文件XxxTimeSlice.h

数据结构

STR_XxxTimeSlice结构体

typedef struct _STR_XxxTimeSlice{
    volatile unsigned char runFlag;         /**< 可运行标志(1:可运行/0:不可运行) */
    volatile unsigned short count;          /**< 计数器 */
    unsigned short reloadVal;               /**< 重载值 */
    void (*taskFunc)(void);                 /**< 任务函数的函数指针 */
    struct _STR_XxxTimeSlice* pNext;        /**< 指向下一个对象 */
}STR_XxxTimeSlice;
成员
调用者
初始化/读/写
权限
赋值范围限制作用
runFlagxxx任务函数可运行标志(1:可运行/0:不可运行)
countxxx计数器,用于计时
reloadVal✔xx[0,65535]重载值,重载值*tick即任务函数的执行间隔。非零则为定时任务,零则非定时任务
taskFunc✔xx任务函数的函数指针
pNextxxx指向下一个对象,用于链表操作

源文件XxxTimeSlice.c

部分源码展示

/**
* @brief        时间片生成(放到systick或定时器中断处理函数内)
* @param        null
* @return       null
* @par          注意事项:
* - null
*/
void XxxTimeSlice_Produce(void)
{
    /*遍历时间片链表*/
    for(STR_XxxTimeSlice* pTemp = pTimeSliceList; pTemp != NULL; pTemp = pTemp->pNext)
    {
        if(pTemp->reloadVal)                            /* 重载值不为0,即定时任务 */
        {
            --pTemp->count;                             /* 计数器递减 */
            if(0 == pTemp->count)                       /* 计数器递减到零 */
            {
                pTemp->runFlag = 1;                     /* 允许执行 */
                pTemp->count = pTemp->reloadVal;        /* 计数器重载 */
            }
        }
	}
}



/**
* @brief        启动时间片错位轮询(代替main的while循环)
* @param        null
* @return       null
* @par          注意事项:
* - null
*/
void XxxTimeSlice_Start(void)
{
    while(1)                                            /* 代替main的while循环 */
    {
        /*遍历时间片链表*/
        for(STR_XxxTimeSlice* pTemp = pTimeSliceList; pTemp != NULL; pTemp = pTemp->pNext)
        {
            if(pTemp->runFlag)                          /* 可运行则调用任务函数 */
            {
                if(pTemp->reloadVal)                    /* 重载值不为0,即定时任务 */
                {
                    pTemp->runFlag = 0;                 /* 可运行标志清零,开启新一轮倒计时 */
                }
                pTemp->taskFunc();
            }
        }
    }
}

完整源码在源码仓库


  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小星星星球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值