介紹
一種無OS的MCU實用軟件框架,包括任務(wù)輪詢管理,命令管理器、低功耗管理、環(huán)形緩沖區(qū)等實用模塊。系統(tǒng)中廣泛利用自定義段技術(shù)減少各個模塊間的耦合關(guān)系,大大提供程序的可維護(hù)性。
主要功能
支持模塊自動化管理,并提供不同優(yōu)先等級初始化聲明接口。
支持任務(wù)輪詢管理,通過簡單的宏聲明即可實現(xiàn),不需要復(fù)雜的聲明調(diào)用。
支持低功耗管理,休眠與喚醒通知。
支持命令行解析,命令注冊與執(zhí)行。
blink設(shè)備支持,統(tǒng)一管理LED、震動馬達(dá)、蜂鳴器
使用說明
完整的代碼可以參考工程文件,系統(tǒng)開發(fā)平臺如下:
MCU:STM32F401RET6
IDE:IAR 7.4或者Keil MDK 4.72A
任務(wù)初始化及任務(wù)輪詢管理(module)
使用此模塊前需要系統(tǒng)提供滴答定時器,用于驅(qū)動任務(wù)輪詢作業(yè)。
//定時器中斷(提供系統(tǒng)滴答) voidSysTick_Handler(void) { systick_increase(SYS_TICK_INTERVAL);//增加系統(tǒng)節(jié)拍 }
注冊初始化入口及任務(wù)(參考自key_task.c)
staticvoidkey_init(void) { /*dosomething*/ } staticvoidkey_scan(void) { /*dosomething*/ } module_init("key",key_init);//注冊按鍵初始化接口 driver_register("key",key_scan,20);//注冊按鍵任務(wù)(20ms輪詢1次)
命令管理器(cli)
適用于在線調(diào)試、參數(shù)配置等(參考使用cli_task.c),用戶可以通過串口輸出命令行控制設(shè)備行為、查詢設(shè)備狀態(tài)等功能。
命令格式
cli支持的命令行格式如下:
每行命令包含一個命令名稱+命令參數(shù)(可選),命令名稱及參數(shù)可以通過空格或者','進(jìn)行分隔。
系統(tǒng)默認(rèn)命令
cli系統(tǒng)自帶了2條默認(rèn)命令,分別是"?"與"help"命令,輸入他們可以列出當(dāng)前系統(tǒng)包含的命令列表,如下所示:
?-aliasfor'help' help-listallcommand. pm-Lowpowercontrolcommand reset-resetsystem sysinfo-showsysteminfomation.
適配命令管理器
完整的例子可以參考cli_task.c.
staticcli_obj_tcli;/*命令管理器對象*/ /* *@brief命令行任務(wù)初始化 *@returnnone */ staticvoidcli_task_init(void) { cli_port_tp={tty.write,tty.read};/*讀寫接口*/ cli_init(&cli,&p);/*初始化命令行對象*/ cli_enable(&cli); cli_exec_cmd(&cli,"sysinfo");/*顯示系統(tǒng)信息*/ } /* *@brief命令行任務(wù)處理 *@returnnone */ staticvoidcli_task_process(void) { cli_process(&cli); } module_init("cli",cli_task_init); task_register("cli",cli_task_process,10);/*注冊命令行任務(wù)*/
命令注冊
以復(fù)位命令為例(參考cmd_devinfo.c):
#include"cli.h" //... /* *@brief復(fù)位命令 */ intdo_cmd_reset(structcli_obj*o,intargc,char*argv[]) { NVIC_SystemReset(); return0; }cmd_register("reset",do_cmd_reset,"resetsystem");
低功耗管理器(pm)
控制間歇運行,降低系統(tǒng)功耗。其基本的工作原理是通過輪詢系統(tǒng)中各個模塊是否可以允許系統(tǒng)進(jìn)入低功耗。實際上這是一種判決機(jī)制,所有模塊都具有有票否決權(quán),即只要有一個模塊不允許休眠,那么系統(tǒng)就不會進(jìn)入休眠狀態(tài)。pm模塊在休眠前會統(tǒng)計出各個模塊會返回最小允許休眠時長,并以最小休眠時長為單位進(jìn)行休眠。
如何適配
使用前需要通過pm_init進(jìn)行初始化適配,并提供當(dāng)前系統(tǒng)允許的最大休眠時間,進(jìn)入休眠的函數(shù)接口,基本的接口定義如下:
/*低功耗適配器---------------------------------------------------------*/ typedefstruct{ /** *@brief系統(tǒng)最大休眠時長(ms) */ unsignedintmax_sleep_time; /** *@brief進(jìn)入休眠狀態(tài) *@param[in]time-期待休眠時長(ms) *@retval實際休眠時長 *@note休眠之后需要考慮兩件事情,1個是需要定時起來給喂看門狗,否則會在休眠 *期間發(fā)送重啟.另外一件事情是需要補(bǔ)償休眠時間給系統(tǒng)滴答時鐘,否則會 *造成時間不準(zhǔn)。 */ unsignedint(*goto_sleep)(unsignedinttime); }pm_adapter_t; voidpm_init(constpm_adapter_t*adt); voidpm_enable(void); voidpm_disable(void); voidpm_process(void);
完成的使用例子可以參考platform-lowpower.c,默認(rèn)情況下是禁用低功耗功能的,讀者可以去除工程中原來不帶低功耗版本的platform.c,并加入platform-lowpower.c文件進(jìn)行編譯即可使用。
注冊低功耗設(shè)備
以按鍵掃描為例,正常情況下,如果按鍵沒有按下,那么系統(tǒng)休眠可以進(jìn)入休眠狀態(tài),對按鍵功能是沒有影響的。如果按鍵按下時,那么系統(tǒng)需要定時喚醒并輪詢按鍵任務(wù)。
所以在一個低功耗系統(tǒng)下,為了不影響按鍵實時性需要處理好兩個事情:
系統(tǒng)休眠狀態(tài)下,如果有按鍵按下,那系統(tǒng)系統(tǒng)應(yīng)立即喚醒,以便處理接下來的掃描工作。
如果按鍵按下時,系統(tǒng)可以進(jìn)入休眠,但需要定時喚醒起來輪詢按鍵任務(wù)。
對于第一種情況,將按鍵配置為邊沿中斷喚醒即可,以STM32F4為例(參考key_task.c),它支持外部中斷喚醒功能。
/* *@brief按鍵io初始化 *PC0->key; *@returnnone */ staticvoidkey_io_init(void) { /*EnableGPIOAclock*/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); gpio_conf(GPIOC,GPIO_Mode_IN,GPIO_PuPd_UP,GPIO_Pin_0); //低功耗模式下,為了能夠檢測到按鍵,配置為中斷喚醒 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,EXTI_PinSource0); exti_conf(EXTI_Line0,EXTI_Trigger_Falling,ENABLE); nvic_conf(EXTI0_IRQn,0x0F,0x0F); key_create(&key,readkey,key_event);/*創(chuàng)建按鍵*/ }
對于第二種情況,可以通過pm_dev_register來處理,當(dāng)系統(tǒng)請求休眠時,如果此時按鍵按下,則返回下次喚醒時間即可,如下面的例子所示。
//參考key_task.c #include"pm.h" /* *@brief休眠通知 */ staticunsignedintkey_sleep_notify(void) { returnkey_busy(&key)||readkey()?20:0;/*非空閑時20ms要喚醒1次*/ }pm_dev_register("key",NULL,key_sleep_notify,NULL);
blink模塊
具有閃爍特性(led, motor, buzzer)的設(shè)備(led, motor, buzzer)管理
使用步驟:
需要系統(tǒng)提供滴答時鐘,blick.c中是通過get_tick()接口獲取,依賴module模塊
需要在任務(wù)中定時進(jìn)行輪詢
或者通過"module"模塊的任務(wù)注冊來實現(xiàn)
task_register("blink",blink_dev_process,50);//50ms輪詢1次
blink_dev_tled;//定義led設(shè)備 /* *@brief紅色LED控制(GPIOA.8) *@param[in]on-亮滅控制 */ staticvoidled_ctrl(inton) { if(on) GPIOA->ODR|=(1<8); ????else? ????????GPIOA->ODR&=~(1<8); } /* ?*@brief?????led初始化程序 ?*/ void?led_init(void) { ????led_io_init(void);??????????????????//led?io初始化 ????blink_dev_create(&led,?led_ctrl);???//創(chuàng)建led設(shè)備 ???? ????blink_dev_ctrl(&led,?50,?100,?0);???//快閃(50ms亮,?100ms滅) }
按鍵管理模塊
類似blink模塊,使用之前有兩個注意事項:
需要系統(tǒng)提供滴答時鐘,key.c中是通過get_tick()接口獲取,依賴module模塊
需要在任務(wù)中定時進(jìn)行輪詢
key_tkey;//定義按鍵管理器 /* *@brief按鍵事件 *@param[in]type-按鍵類型(KEY_PRESS,KEY_LONG_DOWN,KEY_LONG_UP) *@param[in]duration-長按持續(xù)時間 */ voidkey_event(inttype,unsignedintduration) { if(type==KEY_PRESS){//短按 }elseif(type==KEY_LONG_DOWN){//長按 } } //讀取鍵值(假設(shè)按鍵輸出口為STM32MCUPA8) intread_key(void) { returnGPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)==Bit_RESET; } /* *@brief按鍵初始化 */ voidkey_init(void) { //打開GPIO時鐘 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //配置成輸入模式 gpio_conf(GPIOA,GPIO_Mode_IN,GPIO_PuPd_NOPULL,GPIO_Pin_8); //創(chuàng)建1個按鍵 key_create(&key,read_key,key_event); }
-
嵌入式
+關(guān)注
關(guān)注
5150文章
19665瀏覽量
317429 -
接口
+關(guān)注
關(guān)注
33文章
9000瀏覽量
153712 -
軟件框架
+關(guān)注
關(guān)注
0文章
22瀏覽量
10036
原文標(biāo)題:【分享】一種實用的嵌入式無 OS 軟件框架
文章出處:【微信號:工程師進(jìn)階筆記,微信公眾號:工程師進(jìn)階筆記】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
一種無OS的STM32實用軟件框架
一種無OS的MCU實用軟件框架
一種無OS的MCU實用軟件框架
cola os程序框架介紹
一種適用于智能家電嵌入式軟件的框架構(gòu)件模型
一種適用于智能家電嵌入式軟件的框架構(gòu)件模型
介紹一種新的框架式嵌入式UI開發(fā)平臺
嵌入式應(yīng)用框架EAF詳解
關(guān)于嵌入式應(yīng)用框架(EAF)的分析
嵌入式系統(tǒng)框架----軟件篇

嵌入式開發(fā)|嵌入式軟件框架《二》前后臺任務(wù)框架-cola os系統(tǒng)

一種無OS的STM32實用軟件框架編程案例
基于一種無OS的MCU實用軟件框架
一種應(yīng)用于智能家電嵌入式軟件的框架構(gòu)件規(guī)范

評論