找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

626

积分

1

好友

79

主题
发表于 16 小时前 | 查看: 1| 回复: 0

在资源受限的单片机项目中,性能和内存的局限往往使我们无法运行大型通用框架。此时,一个轻量级且功能完备的软件架构就显得至关重要。

本文将分享一款专为单片机裸机环境设计的开源软件框架——Zorb Framework。

Zorb简介

Zorb Framework 是一个基于面向对象思想构建的轻量级嵌入式框架。其开发初衷是为无法运行Linux的芯片提供快速应用开发支持,避免重复“造轮子”。

Zorb Framework 的初步设计功能包括:

  1. 时间系统功能 zf_time
  2. 环形缓冲区功能 zf_buffer
  3. 列表功能 zf_list
  4. 状态机功能 zf_fsm
  5. 事件功能 zf_event
  6. 定时器功能 zf_timer
  7. 任务功能 zf_task

仅使用前6个功能,即可实现纯事件驱动的程序,足以满足大多数中小型嵌入式应用的开发需求。加入任务功能,则是为了满足部分对实时性要求较高的应用场景。

当然,你也可以将前6个功能模块裁剪出来,运行在现有的嵌入式操作系统之上,以此满足实时性需求。

环境搭建

本文以STM32F429开发板作为硬件运行环境,主要使用串口1和SysTick定时器。串口1用于调试信息打印,SysTick提供系统时间计数。

硬件环境示意

关于硬件环境的具体搭建,可参考开发板提供的例程。以下为板级初始化代码,完成了调试串口和SysTick的初始化:

/******************************************************************************
 * 描述  :硬件环境初始化
 * 参数  :无
 * 返回  :无
******************************************************************************/
void BSP_init(void)
{
    /* 嵌套向量中断控制器组选择 */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    /* 初始化调试串口 */
    Debug_USART_init();
    /* Systick初始化 */
    SystemTick_init();
}

/******************************************************************************
 * 描述  :硬件底层程序
 * 参数  :无
 * 返回  :无
******************************************************************************/
void BSP_process(void)
{
}

调试

开发程序时,搭建良好的调试环境至关重要。我们使用串口1作为调试输出(重定向printf),并将调试信息分为三个等级,便于后续上位机进行高亮显示:

#ifndef __ZF_DEBUG_H__
#define __ZF_DEBUG_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "stdio.h"
#include "stdbool.h"

#define LOG_D 0; /* 信息等级:正常 */
#define LOG_W 1; /* 信息等级:告警 */
#define LOG_E 2; /* 信息等级:错误 */

#define _ZF_DEBUG             /* 定义调试功能 */
#define ZF_DEBUG_ON true      /* 启用调试功能 */

#ifdef _ZF_DEBUG
    #if ZF_DEBUG_ON
        #define ZF_DEBUG(rank, x...) do     \
        {                                    \
            char code[10] = "[rank=0]";     \
            code[6] = '0' + (char)rank;     \
            if (code[6] != '0')             \
            {                               \
                printf("%s", code);         \
            }                               \
            printf(x);                      \
        } while(0)
    #else
        #define ZF_DEBUG(rank, x...)
    #endif /* ZF_DEBUG_ON */
#endif /* _ZF_DEBUG */

#ifdef __cplusplus
}
#endif

#endif /* __ZF_DEBUG_H__ */

断言

在开发过程中,在关键位置加入断言(Assert),能有效帮助定位Bug。

断言头文件定义如下:

#ifndef __ZF_ASSERT_H__
#define __ZF_ASSERT_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "stdint.h"

#define _ZF_ASSERT              /* 定义断言功能 */
#define ZF_ASSERT_ON true       /* 启用断言功能 */

#ifdef _ZF_ASSERT
    #if ZF_ASSERT_ON
         #define ZF_ASSERT(expression_) ((expression_) ?\
            (void)0 : ZF_assertHandle((uint8_t *)__FILE__, (int)__LINE__));
    #else
         #define ZF_ASSERT(expression_)
    #endif /* ZF_ASSERT_ON */
#endif /* _ZF_ASSERT */

/* 断言产生时的处理 */
void ZF_assertHandle(uint8_t *pFileName, int line);

#ifdef __cplusplus
}
#endif

#endif /* __ZF_ASSERT_H__ */

断言的处理逻辑很简单,即告知我们出错的文件名和行号,具体实现如下:

#include "zf_assert.h"
#include "zf_debug.h"

/******************************************************************************
* 描述  :断言产生时的处理
* 参数  :(in)-pFileName 文件名
*         (in)-line 行数
* 返回  :无
******************************************************************************/
void ZF_assertHandle(uint8_t *pFileName, int line)
{
    ZF_DEBUG(LOG_E, "file:%s line:%d:asserted\r\n", pFileName, line);
    while (1);
}

调度时间

为了降低框架对系统资源的消耗,初步设定框架的最小时间周期为1ms。因此,我们需要配置SysTick的定时周期为1ms,并在其中断服务程序中为框架提供时间计数。

/******************************************************************************
* 描述  :SysTick中断服务程序
* 参数  :无
* 返回  :无
******************************************************************************/
void SysTick_Handler(void)
{
    /* 为zorb framework提供计时 */
    ZF_timeTick();
}

目前时间系统提供的基础功能包括系统滴答计数和阻塞式延时。后续开发定时器和任务功能时,会对此进行扩展。理解底层的时间调度和并发控制是嵌入式开发的核心,更多相关知识可以在网络/系统板块进行深入探讨。

时间系统的头文件定义如下:

#ifndef __ZF_TIME_H__
#define __ZF_TIME_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "stdbool.h"
#include "stdint.h"

/* 系统滴答周期(ms) */
#define ZF_TICK_PERIOD 1

/* 获取系统滴答数 */
#define ZF_SYSTICK() ZF_getSystemTick()

/* 获取系统时间(ms) */
#define ZF_SYSTIME_MS() ZF_getSystemTimeMS()

/* 系统延时(ms) */
#define ZF_DELAY_MS(ms_) do                         \
{                                                   \
    if (ms_ % ZF_TICK_PERIOD)                      \
    {                                               \
        ZF_delayTick((ms_ / ZF_TICK_PERIOD) + 1);  \
    }                                               \
    else                                            \
    {                                               \
        ZF_delayTick(ms_ / ZF_TICK_PERIOD);        \
    }                                               \
} while(0)

/* 获取系统滴答数 */
uint32_t ZF_getSystemTick(void);
/* 获取系统时间(ms) */
uint32_t ZF_getSystemTimeMS(void);
/* 系统延时 */
void ZF_delayTick(uint32_t tick);
/* 系统滴答程序(需挂在硬件的时间中断里边) */
void ZF_timeTick (void);

#ifdef __cplusplus
}
#endif

#endif /* __ZF_TIME_H__ */

最后

本篇介绍的功能是整个Zorb Framework开发的基石,后续所有扩展功能都需在此环境下进行。搭建完善的调试输出环境,能帮助我们快速定位问题,从而显著提升开发效率。

Github 地址
https://github.com/54zorb/Zorb-Framework

来源:上面的链接




上一篇:前端用户行为录制实战:基于rrweb实现无感知录屏与上传
下一篇:IntelliJ IDEA 2025.3深度体验:AI功能升级与统一版本全解析
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-10 20:50 , Processed in 0.081765 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表