嵌入式软件通用框架
前言
一个好的软件架构,能让代码逻辑更好的理解是如何运行的。在最开始写代码的时候,我总是一股脑的从头写道尾,想到什么功能就写上去。如今工作这么久了,重新审视一下自己的以前的代码和现在的在公司里写的代码,既可以发现:以前的代码很多功能上会出现相关干扰的风险。
常用三种架构
应用程序的架构大致有三种:
1、简单的前后台顺序执行程序,这类写法是大多数人使用的方法,不需用思考程序的具体架构,直接通过执行顺序编写应用程序即可。
2、时间片轮询法,此方法是介于顺序执行与操作系统之间的一种方法。
3、操作系统,此法应该是应用程序编写的最高境界。
本篇主要介绍时间片轮询法,适用于大多低端设备,在个人的一些DIY产品上使用也是刚好可以的。
时间片轮询法
介于前后台顺序执行法和操作系统之间的一种程序架构设计方案。该设计方案需能帮助嵌入式软件开发者更上一层楼,在嵌入式软件开发过程中,若遇到以下几点,那么该设计方案可以说是最优选择,适用于程序较复杂的嵌入式系统;
- 目前的需求设计需要完全没有必要上操作系统。
- 任务函数无需时刻执行,存在间隔时间(比如按键,一般情况下,都需要软件防抖,初学者的做法通常是延时10ms左右再去判断,但10ms极大浪费了CPU的资源,在这段时间内CPU完全可以处理很多其他事情)
- 实时性有一定的要求。
该设计方案需要使用一个定时器,一般情况下定时1ms即可(定时时间可随意定,但中断过于频繁效率就低,中断太长,实时性差),因此需要考虑到每个任务函数的执行时间,建议不能超过1ms(能通过程序优化缩短执行时间则最好优化,如果不能优化的,则必须保证该任务的执行周期必须远大于任务所执行的耗时时间),同时要求主循环或任务函数中不能存在毫秒级别的延时。
钩子函数实现方式
#include "app_task.h"
#include "bsp_mpu6050.h"
#include "elog.h"
#define TAG "app_task"
static void app_task_test(void);
/**
* @brief 任务函数相关信息结构体定义.
*/
typedef struct
{
uint8_t m_runFlag; /*!< 程序运行标记:0-不运行,1运行 */
uint16_t m_timer; /*!< 计时器 */
uint16_t m_itvTime; /*!< 任务运行间隔时间 */
void (*m_pTaskHook)(void); /*!< 要运行的任务函数 */
} app_task_type_t;
#define APP_TASKS_MAX 2 // 定义任务数目
/** 任务函数相关信息 */
static app_task_type_t gs_tTaskInfo[APP_TASKS_MAX] = {
// {0, 1, 1, NULL}, // 任务 1ms
// {0, 10, 10, NULL}, // 任务 10ms
// {0, 20, 20, NULL}, // 任务 20ms
{0, 500, 500, app_task_test}, // 任务 500ms
{0, 1000, 1000, MPU6050_test_demo}, // 任务 1000ms
};
static void app_task_test(void)
{
elog_i(TAG,"app_task_test");
}
/**
* @brief 任务函数运行标志处理.
* @note 该函数由1ms定时器中断调用
* @param None.
* @return None.
*/
void TASK_Remarks(void)
{
uint8_t i;
for (i = 0; i < APP_TASKS_MAX; i++)
{
if (gs_tTaskInfo[i].m_timer)
{
gs_tTaskInfo[i].m_timer--;
if (0 == gs_tTaskInfo[i].m_timer)
{
gs_tTaskInfo[i].m_timer = gs_tTaskInfo[i].m_itvTime;
gs_tTaskInfo[i].m_runFlag = 1;
}
}
}
}
/**
* @brief 任务函数运行处理.
* @note 该函数由主循环调用
* @param None.
* @return None.
*/
void TASK_Polling(void)
{
uint8_t i;
for (i = 0; i < APP_TASKS_MAX; i++)
{
if (gs_tTaskInfo[i].m_runFlag)
{
gs_tTaskInfo[i].m_pTaskHook(); // 运行任务
gs_tTaskInfo[i].m_runFlag = 0; // 标志清0
}
}
}
这里使用的一种C语言的高级用法[钩子函数],这也是一种高级的代码编写技巧。
总结
对于其他两种方式,这里也不过多说明,总体上来说在轻量级设备中,这总方式可以不用占用过多资源即可实现的一种软件架构。详细文章可以参考:嵌入式软件开发常用的三种架构你知道吗? (qq.com)
本文来自博客园,作者:一月一星辰,转载请注明原文链接:https://www.cnblogs.com/tangwc/p/18107001