打造嵌入式轻量级调试环境:一个简单框架的介绍
一起学嵌入式 2023-12-01


一、Zorb简介

Zorb Framework是一个基于面向对象的思想来搭建一个轻量级的嵌入式框架。

搭建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映射),然后调试信息分为三个等级,后续上位机可以根据不同等级进行高亮提示:

/**
  *****************************************************************************
  * @file    zf_debug.h
  * @author  Zorb
  * @version V1.0.0
  * @date    2018-06-28
  * @brief   调试输出的头文件
  *****************************************************************************
  * @history
  *
  * 1. Date:2018-06-28
  *    Author:Zorb
  *    Modification:建立文件
  *
  *****************************************************************************
  */ #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__ */ /******************************** END OF FILE ********************************/ 

四、实现断言

在开发过程中,在关键地方进行一些断言,可以方便定位bug。

/**
  *****************************************************************************
  * @file    zf_assert.h
  * @author  Zorb
  * @version V1.0.0
  * @date    2018-06-28
  * @brief   断言的头文件
  *****************************************************************************
  * @history
  *
  * 1. Date:2018-06-28
  *    Author:Zorb
  *    Modification:建立文件
  *
  *****************************************************************************
  */ #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__ */ /******************************** END OF FILE ********************************/ 

断言的处理很简单,就是告诉我们在哪个文件哪一行出错就可以,实现如下

/**
  *****************************************************************************
  * @file    zf_assert.c
  * @author  Zorb
  * @version V1.0.0
  * @date    2018-06-28
  * @brief   断言的实现
  *****************************************************************************
  * @history
  *
  * 1. Date:2018-06-28
  *    Author:Zorb
  *    Modification:建立文件
  *
  *****************************************************************************
  */ #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);
} /******************************** END OF FILE ********************************/ 

五、建立时间系统

为了减少框架对资源的消耗,所以初步设定框架的最小时间周期为1ms,因此我们需要设置systick的定时周期为1ms,然后每次进入中断为我们的框架计数即可。

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

现在时间系统提供的功能比较基础,只有系统滴答计数和系统死等待延时,后面我们开发定时器功能和任务功能的时候会重新扩展时间系统。

/**
  *****************************************************************************
  * @file    zf_time.h
  * @author  Zorb
  * @version V1.0.0
  * @date    2018-06-28
  * @brief   系统时间的头文件
  *****************************************************************************
  * @history
  *
  * 1. Date:2018-06-28
  *    Author:Zorb
  *    Modification:建立文件
  *
  *****************************************************************************
  */ #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__ */ /******************************** END OF FILE ********************************/ 

六、最后

本篇实现的功能比较基础,但是整个框架开发的根基,后面所有扩展的功能都需要在此环境下进行开发。

搭建良好的调试输出环境,可以帮我们快速定位bug的所在,从而提高开发效率。



声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
  • 【立即预约】Keysight直播:搞懂介电常数那些事儿


  • 相关技术文库
  • 单片机
  • 嵌入式
  • MCU
  • STM
  • 深谈嵌入式系统,嵌入式系统是如何组成的?

    嵌入式系统在生活中有诸多应用,大家对于嵌入式系统或多或少有所耳闻。在前两篇文章中,小编对嵌入式系统进行过详细介绍。为继续增进大家对嵌入式系统的认识,本文将对嵌入式系统的组成加以说明。如果你对嵌入式系...

    06-27
  • 嵌入式系统秘籍共享,最全嵌入式系统解析

    嵌入式系统的应用十分广泛,因此越来越多的人学习嵌入式系统。由此,在学习嵌入式系统之前,我们应当对嵌入式系统具备一些认识。所以在本文余下部分,小编将对嵌入式系统进行全面解析。如果你对嵌入式系统具有兴趣...

    06-27
  • 51单片机超声波测距程序详解

    51单片机超声波测距程序详解 超声波四通道测距:超声波测距实现分为三大块: 其一是12864带字库的液晶驱动程序: 代码如下: /////////////////12864驱动程序/////////////////////////// //1写数据 void WriteDat...

    06-25
  • 51系列单片机的引脚图

    51系列单片机的引脚图 端子介绍 l P0.0~P0.7 P0口8位双向口线(在引脚的39~32号端子)。 l P1.0~P1.7 P1口8位双向口线(在引脚的1~8号端子)。 l P2.0~P2.7 P2口8位双向口线(在引脚的21~28号端子)。 l P3.0~P3.7 P2口8...

    06-25
  • 51单片机串口通信需要加超时中断吗?

    接收数据时,超过一定时间就算出错. 这个超时的时间是单片机自己算出的吗?超时的时间是由编程序的人定的,他定多长就多长从一段程序开始 实现电脑向 单片机发送一些数据,单片机返回Iget +数据 #include #define u...

    06-25
  • 51单片机电机pid控制系统程序

    51单片机电机pid控制系统程序 本程序来源网上,小编进行了简单修改,还未验证。 /************************* 应用背景:直流电机的额定功率12V,额定转速3000rpm,光码盘12孔, 晶振为12MHz,定时/计数器T0检测转...

    06-25
  • 51单片机指令集设计实例

    当你编写完一个程序后,通过软件调试,你可以看到程序的指令集,从指令集你就能知道单片机内部是如何工作的,比如数据存取的寄存器与地址,下面是电工之家找的一篇指令集,讲的蛮好的。 一、数据传送类指令(7种助...

    06-25
  • 51单片机定时器工作原理及用法

    TMOD : 控制定时器的工作方式。8个bit,高四位 bit 控制 T1,、低四位 bit 控制 T0。因为定时器有4种工作方式;TMOD = 0x00(工作方式0),TMOD = 0x01(工作方式0),TMOD = 0x02(工作方式2),TMOD = 0x03(工作方式3)。...

    06-25
  • 51单片机指令系统寻址方式

    指令给出参与运算的数据方式称为寻址方式。换句话说,寻址方式就是寻找确定参与操作的数的真正地址。 在MCS-51系列单片机的指令系统中寻址方式共有7种,立即寻址方式,mcs-51单片机的一种寻址方式,操作数就写在指...

    06-25
  • 51单片机学习单片机之路总结

    学习单片机有一学期了,现在也由51转到STM32了。一直想对51的学习做一个总结。也希望对别人有一些启发。也给后学者提供一些建议。当然本文是我对自己学习过程的总结,若有不对的地方,还请高手指出。 我想,再看本...

    06-25
  • 入手STM32单片机的知识点总结

    从STM32新建工程、编译下载程序出发,让新手由浅入深,尽享STM32标准库开发的乐趣

    06-23
  • 单片机定时器之改良版:时间轮定时器

    前段时间把自己以前用的单片机定时器整理出来,我称之为简单定时器,这种简单定时器比较适合定时器使用量少的程序中,如果定时器数量要求多,精度要求高,效率就会有问题,为此,俺就实现了一个时间轮定时器,简单测...

    06-23
下载排行榜
更多
评测报告
更多
EE直播间
更多
广告