作者 |Github -?54zorb ? ? ? ? ?
很多时候,做单片机项目,会因为性能和内存资源的限制,没办法运行一些“大型”的通用框架,这个时候,一些轻量级的软件框架有显得尤为重要了。 ? 这里就给大家分享一款一款适合单片机裸机的开源软件框架:Zorb
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 ",?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的所在,从而提高开发效率。
审核编辑:黄飞
?
评论