《如何提高嵌入式软件可维护性?.docx》由会员分享,可在线阅读,更多相关《如何提高嵌入式软件可维护性?.docx(13页珍藏版)》请在课桌文档上搜索。
1、想要软件具有好的维护性,就需要减少各个模块之间的他合性,今天给大家分享个无OS的MCU实用软件框架,介绍一种无OS的MCU实用软件框架,包括任务轮询管理,命令管理器、低功耗管理、环形缓冲区等实用模块.系统中广泛利用自定义段技术减少各个模块间的耦合关系.大大提供程序的可维护性.主要功能支持模块自动化管理,并提供不同优先等级初始化声明接II,支挣任务轮询管理.通过简单的宏声明即可实现.不能要更杂的声明调川.支持低功耗管理,休眠与唤醒通知.支持命令行解析,命令注册与执行.b1.ink设备支持.统管理1.ED.震动马达、好呜擀使用说明完整的代码可以参考工程文件,系统开发平台如I:MCU:STM32F4
2、01RET6IDE;IAR7.4或者Ke1.1.MDK4.72A任务初始化及任务轮询管理(modu1.e)使用此模块前毋要系统提供滴答定时零,用于骗动任务轮询作业.(参考P1.atformx)定时静中断(提供系统滴答)voidSysTIck-HandIer(VOid)(SySHCkMreaSe(SYSJnCKNTERVA1.);增加系统节拍)注册初始化入门及任务(参考自key,task.c)staticvoidkeyjnit(void)/dosomething*/)staticvoidkey.scan(Vo1.d)*dosomething*/modu1.eJnitrkey”,keyjnit);
3、注册按迸初始化接I1.dr1.ver-register(key,key_$can,20);注册按键任务(2OmS轮询1次)命令管理器(di)适用于在线调试、参数配置等(参考使用C1.1.taskx),用户可以通过用1.1.输出命令行控制设备行为、伐血设备状态等功能。命令格式di支持的命令行格式如下:Vparam1.Vrn,号行命令包含一个命令名称+命令参数(可选),命令名称及参数UJ以通过空格或者;进行分隔.系统默认命令C1.i系统自带了2条默认命令,分别是?与he1.p命令,输入他们UJ以列出当前系统包含的命令列衣,如下所示:-a1.iasforhe1.phe1.p-mand.-mandre
4、set-resetsystemsysinfo-showsysteminfomation.适配命令管理器/命令管理潞对软/完整的例子可以参考C1.1.taSkCstaticc1.1.-objtc1.i;(brief命令行任务初始化returnnone7staticvoidC1.iJaskJnit(void)c1.i_port_tp=tty.write,tty.read);初始化命令行对象7C1.1.enab1.e/显示系统信息/c1.i_exec_cmd(&c1.i,sy$info);)brief命令行任务处理,(returnnone7staticvoidc1.i_task_process(vo
5、id)c1.i_process(&c1.i);)modu1.eJn1.t(wc,c1.1._teskJn1.t);/*注册命令行任务*/task.register(c1.i,C1.1.taSk.process,10);命令注册以双位命令为例(参考cmd_devinfo.c):A1.ndude*d1.h*(brief史位命令intdo_cmd_reset(structc1.i-obj*o,intargc,char*argv()NVIJSyStemReSet0;return0;Jcmd_register(reset,do_cmd_reset,resetsystem!;低功耗管理器(Pm)控制向歇运
6、行,降低系统功耗.其条本的工作原理是通过轮询系统中各个馍块是否可以允许系统进入低功耗.实际上这是一种判决机制所有模块都具行有票否决权,即只要有一个模块不允许休眠,那么系统就不会进入休眠状态,pm模块在休眠前会统计出各个模块会返I可最小允许休眠时长,并以最小休眠时长为单位进行休眠.如何适充使用前需要通过pm_init进行初始化选配,并提供当前系统允许的G人休眠时间,进入休眠的函数接口,基本的接口定义如下:/低功耗适配器-/tpedefstruct/*brief系统最大休眠时K(ms)unsignedIntmax_$1.eep_t1.me;* brief进入休眠状态* Paramin)time-期
7、待休眠时长(ES)* (retva1.实际休眠时长* note休眠之后需要考虑两件事情,1个是需要定时起来给喂存门狗,否则会在休眠* 期间发送常启.另外一件事情是需要补偿休眠时间给系统滴答时钟,否则会* 造成时间不准“7unsignedint(*goto-s1.eep)(unsig11edinttime);pm_adapter_t;voidpmjnit(constpm_adapter_tMadt);voidpm-e11ab1.e(void);voidpm-disab1.e(void);voidPm-ProCeSS(VOid);完成的使用例子可以参考PIatfOrm-IOWPOWerC默认情况下
8、是禁用低功耗功能的.读者可以去除工程中晚来不带低功耗成本的patform.c,并加I入PIatfOrm-Iowpowenc文件进行编洋即可使用.注册低功耗设备以按键扫描为例,正常情况下,如果按键没有按下,那么系统休眠可以进入休眠状态.对按根功能是没有影响的.如果按段按下时,那么系统3要定时唤醒并轮询按械任务.所以在一个低功耗系统下,为了不影响按迸实时性需要处理好两个事情:系统休眠状态下,如果有按键按下,那系统系统府立即唤醒.以便处理接下来的扫描工作。如果按谈按下时,系统可以进入休眠,但制要定时唤解起来轮前按键任务。对于第一种情况,将按键配置为边沿中断唤醒即可,以STM32F4为例(参考key.
9、task.c),它支持外部中断唤醒功能./brief按键io初始化*PCO-key;returnnonestaticvoidkey_ioJnIt(Void)/Endb1.eGpiOAcIock*/RCJAHB1.PeriPhaOCkCmd(RCJAHBIPeriPh_GPIOA,ENAB1.E);gpio_conf(GPIOC,GPIO_Mode_IN,GPIO_PuPd_UP,GPIO_Pin_0);低功耗模式E为了能够检冽到按tit能置为中断唤胆RCC_APB2PeriphC1.ockCmd(RCC_APB2Penph_SYSCFG,ENAB1.E);SYSCFG_ExT1.1.ineCO
10、nfig(EXT1.POrtsoUrCeGPIOCEXTI-PinSourceO);ext1._conf(EXTI_1.ineO,EXT1.TriggerJaIIing1ENAB1.E);nvic_conf(EXT10_IRQn,OxOF,OxOF;key_create(&key,readkey,key_event);/创建按键”/)对于第一二种情况,可以通过pm/evjegister来处理,当系统谛求休眠时,如果此时按Ut按下,W1.返I可下次唤醒时间即可,如下面的例子所示.参考key_task.cinc1.udepm.hbrief休眠通知staticunsignedintkey_$1.ee
11、p_notify(vo1.d)returnkey_busy(&kcy)11readkey()?20:0;非空闲时20ms要唤酢1次7pm-dev-registerf,key,NU1.1.,key_s1.eep_notify,NU1.1.);b1.ink模块具干i闪烁特性(1.ed,motor,buzzer)的设备(1.ed,motor,buzzer)管理使用步骤:需要系统提供滴答时钟,bMk中是通过gejHck()接口获取,依极modu1.e模块需要在仟务中定时进行轮询谯者通过modu1.e”模块的任务注册来实现task-register(b1.ink,b1.ink_dev_processz5
12、0);/SOms轮询1次1.ED驱动b1.ink_dev_t1.ed;bnef红色1.ED控制(GP1.OA.8)“Param1.in)On-亮灭控制7staticvoid1.ed-ctr1.(inton)if(on)GPIOAODR=(1ODR&=(18);)*brief1.ed初始化程序7voidIedJnIUVOid)(IedJoJnit(VOid);定义Ied设符/1.edio初始化b1.ink_dev_create(&1.ed,Ied-ctr1);创建1.ed设备b1.ink_dev_ctr1.(&1.ed,50,100,0);/yiW(SOms亮,1.ms灭)按键管理模块类似b1.
13、ink模块,使用之前有两个注意事项:需要系统提供滴答时钟,key.c中是通过gejtick()接1.1.获取.依敕modu1.e铁块掰要在任务中定时进行轮泡key_tkey;定义按械管理涕/bnef按键犷件Paramintype-按键类型(KEY_PRESsKEY_1.ONG_DOWN,KEYONGJJP)Param1.in)duration长按持续时WJ7voidkey_event(inttype,unsignedntduration)(if(type=KEY,PRESS)短按e1.seif(type=KEY_1.ONG_DOWN)长按谈取犍(1假设按犍输出1.1.为STM32MCUPA8)intread_key(vo1.d)(returnGPO-Read1.nputDataBit(GPOA,GPiO_Pin_8)=BiJRESET;)*brief按键初始化7voidkejnit(vod)(打开GP1.O时钟RCjAHBIPeriPhQoCkCmd(RCjAHBIPeriPh_GPIoA,ENAB1.E);配置成输入模式gpio_conf(GPIOA,GPIO_Mode_IN,GP1.o_PUPd_NOPU1.1.GPI0_Pin_8|;创建1个按键key_create&key,read_key,key_event);