近期 RT-Thread 工程師完成了基于瑞薩CPK-RA2L1 開發板的BSP適配,支持了GPIO、UART、I2C、SPI、ADC、DAC、PWM、CAN、on-chip Flash、Watchdog、RTC等外設驅動,并在瑞薩工程師支持下完成了電源組件(低功耗LPM)適配,經實際測量,芯片在Software Standby階段可達到的最低平均電流約為0.696uA,本篇筆記記錄低功耗的適配和應用。
可通過以下鏈接查看RA MCU BSP:
https://github.com/RT-Thread/rt-thread/tree/master/bsp/renesas
瑞薩 RA 系列 MCU 開發板的 BSP 制作教程:
https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/tutorial/make-bsp/renesas-ra/RA%E7%B3%BB%E5%88%97BSP%E5%88%B6%E4%BD%9C%E6%95%99%E7%A8%8B
在開始介紹低功耗前,先了解一下 RA2L1 MCU 產品群關鍵特性
-
支持1.6V-5.5V寬范圍工作電壓
-
超低功耗,提供64μA/MHz工作電流和250nA軟件待機電流,快速喚醒時間小于5μs
-
采用瑞薩110nm低功耗工藝,用于運行和睡眠/待機模式,并且專門為電池驅動應用設計了特殊掉電模式
-
靈活的供電模式可實現更低的平均功耗,以滿足多種應用需求
-
后臺運行的數據閃存,支持一百萬次擦除/編程循環
-
采用LQFP封裝,產品涵蓋48引腳至100引腳封裝
低功耗基礎
低功耗的本質是系統空閑時 CPU 停止工作,中斷或事件喚醒后繼續工作。在 RTOS 中,通常包含一個 IDLE 任務,該任務的優先級最低且一直保持就緒狀態,當高優先級任務未就緒時,OS 執行 IDLE 任務。一般地,未進行低功耗處理時,CPU 在 IDLE 任務中循環執行空指令。RT-Thread 的電源管理組件在 IDLE 任務中,通過對 CPU 、時鐘和設備等進行管理,從而有效降低系統的功耗。
在上圖所示,當高優先級任務運行結束或被掛起時,系統將進入 IDLE 任務中。在 IDLE 任務執行后,它將判斷系統是否可以進入到休眠狀態(以節省功耗)。如果可以進入休眠, 將根據芯片情況關閉部分硬件模塊,OS Tick 也非常有可能進入暫停狀態。此時電源管理框架會根據系統定時器情況,計算出下一個超時時間點,并設置低功耗定時器,讓設備能夠在這個時刻點喚醒,并進行后續的工作。當系統被(低功耗定時器中斷或其他喚醒中斷源)喚醒后,系統也需要知道睡眠時間長度是多少,并對OS Tick 進行補償,讓系統的OS tick值調整為一個正確的值。
PM組件
PM組件是RT-Thread系統中針對電源管理而設計的基礎功能組件, 組件采用分層設計思想,分離架構和芯片相關的部分,提取公共部分作為核心。支持多種運行模式和休眠模式的管理切換,以及低功耗定時器的管理。
PM 組件有以下特點:
-
PM 組件是基于模式來管理功耗
-
PM 組件可以根據模式自動更新設備的頻率配置,確保在不同的運行模式都可以正常工作
-
PM 組件可以根據模式自動管理設備的掛起和恢復,確保在不同的休眠模式下可以正確的掛起和恢復
-
PM 組件支持可選的休眠時間補償,讓依賴 OS Tick 的應用可以透明使用
-
PM 組件向上層提供設備接口,如果使用了設備文件系統組件,那么也可以用文件系統接口來訪問
PM組件支持的休眠模式有
RA系列LPM功能
RA2 MCU支持的LPM類型有:
-
Sleep mode
-
Software Standby mode
-
Snooze mode
低功耗模式轉換和觸發源如圖所示:
不同模式間的切換如圖所示,從圖中也可以看出三種模式的功耗關系是Sleep>Snooze>Standby。
RA2芯片的休眠模式對應PM組件的模式關系:
配置LPM功能
要使用RA2系列芯片的LPM功能,需要進入bsp enesas a2l1-cpk目錄。
-
在menuconfig中使能LPM驅動,并勾選要開啟的休眠模式,然后保存配置,生成MDK5工程。
-
打開PM組件和驅動后,需要增加idle的線程棧大小,可改為1024。
-
打開生成的MDK5工程project.uvprojx,然后打開FSP配置工具添加LPM相關配置。下圖是需要添加的stack,包括三種LPM模式的配置以及低功耗定時器AGT1。
-
創建LPM如下圖所示新建r_lpm,需要根據使用的模式進行配置且不同模式要創建不同的r_lpm。下面將分別介紹三種不同模式的配置,創建步驟就不再贅述。
Sleep mode休眠模式
創建出r_lpm后需要修改Name和Low Power Mode這兩個配置項。Name需要改為g_lpm_sleep,因為在驅動文件中已經定義了sleep模式對應的stack名稱。Low Power Mode選擇Sleep mode即可。
Standby mode軟件待機模式
Name需要改為g_lpm_sw_standby。Low Power Mode選擇Software Standby mode即可。
另外在此模式下還需要配置喚醒MCU的中斷源,因為會使用到AGT1做為低功耗定時器所以AGT1的中斷需要勾選。如果在應用中還需要其他中斷源在此模式下喚醒MCU,則勾選對應選項即可。
Snooze mode小睡模式
Name需要改為g_lpm_sw_standby_with_snooze。Low Power Mode選擇Snooze mode即可。
另外在此模式下同樣要配置喚醒MCU的中斷源,因為會使用到AGT1做為低功耗定時器所以AGT1的中斷需要勾選。如果在應用中還需要其他中斷源在此模式下喚醒MCU,則勾選對應選項即可。
AGT1低功耗定時器
在驅動中使用了MCU的AGT1做為PM組件的低功耗定時器,用于在休眠狀態下的系統時鐘補償。
完成上述配置步驟就已經把LPM低功耗模式的相關配置做完了。然后再根據應用要實現的功能配置其他外設。
低功耗DEMO
上文介紹了在RT-Thread的RA2L1上怎么配置LPM的不同模式,接下來就用一個小DEMO來驗證下MCU在各種模式下的工作情況。
低功耗DEMO要實現的功能是,在CPK-RA2L1開發板上用S1按鈕切換不同的低功耗模式,并在msh中打印出模式切換的提示信息。要實現這個功能需要在剛才的基礎上添加一個低功耗的喚醒源。
添加配置
-
創建IRQ中斷,IRQ中斷選擇通道3,詳細配置如下。
-
在剛才的Snooze和Standby模式的配置里添加IRQ3的喚醒源
-
然后保存并生成配置代碼。
添加測試代碼
#include
#ifdef BSP_USING_LPM
#include
#include
#include
#define WAKEUP_APP_THREAD_STACK_SIZE 512
#define WAKEUP_APP__THREAD_PRIORITY RT_THREAD_PRIORITY_MAX / 3
#define WAKEUP_EVENT_BUTTON (1 << 0)
static rt_event_t wakeup_event;
#define USER_INPUT "P004"
#define LED2_PIN "P501" /* Onboard LED pins */
void rt_lptimer_init(rt_lptimer_t timer,
const char *name,
void (*timeout)(void *parameter),
void *parameter,
rt_tick_t time,
rt_uint8_t flag);
rt_err_t rt_lptimer_detach(rt_lptimer_t timer);
rt_err_t rt_lptimer_start(rt_lptimer_t timer);
rt_err_t rt_lptimer_stop(rt_lptimer_t timer);
rt_err_t rt_lptimer_control(rt_lptimer_t timer, int cmd, void *arg);
static struct rt_lptimer lptimer;
static void timeout_cb(void *parameter)
{
rt_interrupt_enter();
rt_kprintf(" lptimer callback ");
rt_interrupt_leave();
}
static void lptimer_init(void)
{
rt_lptimer_init(&lptimer,
"lpm",
timeout_cb,
(void*)&wakeup_event,
1000,
RT_TIMER_FLAG_PERIODIC);
}
static void lptimer_stop(void)
{
rt_lptimer_stop(&lptimer);
}
static void lptimer_start(void)
{
rt_lptimer_start(&lptimer);
}
static void led_app(void)
{
static uint8_t key_status = 0x00;
rt_uint32_t led2_pin = rt_pin_get(LED2_PIN);
rt_pin_write(led2_pin, PIN_HIGH);
switch(key_status%4)
{
case 0:/* IDLE */
lptimer_stop();
rt_pm_release(PM_SLEEP_MODE_NONE);
rt_kprintf(" request:IDLE ");
rt_pm_request(PM_SLEEP_MODE_IDLE);
break;
case 1:/* DEEP */
lptimer_stop();
lptimer_start();
rt_pm_release(PM_SLEEP_MODE_IDLE);
rt_kprintf(" request:DEEP ");
rt_pm_request(PM_SLEEP_MODE_DEEP);
break;
case 2:/* STANDBY */
lptimer_stop();
lptimer_start();
rt_pm_release(PM_SLEEP_MODE_DEEP);
rt_kprintf(" request:STANDBY ");
rt_pm_request(PM_SLEEP_MODE_STANDBY);
break;
case 3:/* NONE */
lptimer_stop();
rt_pm_release(PM_SLEEP_MODE_STANDBY);
rt_kprintf(" request:NONE ");
rt_pm_request(PM_SLEEP_MODE_NONE);
break;
default:
break;
}
key_status++;
rt_pin_write(led2_pin, PIN_LOW);
}
static void wakeup_callback(void* p)
{
rt_event_send(wakeup_event, WAKEUP_EVENT_BUTTON);
}
void wakeup_sample(void)
{
/* init */
rt_uint32_t pin = rt_pin_get(USER_INPUT);
rt_kprintf(" pin number : 0x%04X ", pin);
rt_err_t err = rt_pin_attach_irq(pin, PIN_IRQ_MODE_RISING, wakeup_callback, RT_NULL);
if (RT_EOK != err)
{
rt_kprintf(" attach irq failed. ");
}
err = rt_pin_irq_enable(pin, PIN_IRQ_ENABLE);
if (RT_EOK != err)
{
rt_kprintf(" enable irq failed. ");
}
}
static void wakeup_init(void)
{
wakeup_event = rt_event_create("wakup", RT_IPC_FLAG_FIFO);
RT_ASSERT(wakeup_event != RT_NULL);
wakeup_sample();
}
static void pm_mode_init(void)
{
rt_pm_release_all(RT_PM_DEFAULT_SLEEP_MODE);
rt_pm_request(PM_SLEEP_MODE_NONE);
}
void pm_test_entry(void* para)
{
/* 喚醒回調函數初始化 */
wakeup_init();
/* 電源管理初始化 */
pm_mode_init();
lptimer_init();
while (1)
{
/* 等待喚醒事件 */
if (rt_event_recv(wakeup_event,
WAKEUP_EVENT_BUTTON,
RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR,
RT_WAITING_FOREVER, RT_NULL) == RT_EOK)
{
led_app();
}
}
}
int pm_test(void)
{
rt_thread_t tid = rt_thread_create(
"pmtest",pm_test_entry,RT_NULL,512,10,10);
if(tid)
rt_thread_startup(tid);
return 0;
}
MSH_CMD_EXPORT(pm_test, pm_test);
// INIT_APP_EXPORT(pm_test);
#endif
將DEMO代碼加入到工程中,可以直接添加到hal_entry.c或新建一個源文件。
測試驗證
然后編譯下載。開發板連接串口工具,輸入pm_test
命令啟動測試DEMO。
按下S1按鈕切換工作模式,在DEEP、STANDBY模式下會啟動低功耗定時器,當定時喚醒后會打印出回調接口的提示信息。
經測試:
(1)串口通中輸入“pm_test”,觀測到電流在8.6mA和5.8mA之間變化。
(2)按下S1后,串口通中打印信息為“requestIDLE”,此時電流約為2.2mA。
(3)再次按下S1后,串口通中打印信息為“requestDEEP”,此時電流約為1593uA,并間隔產生lptimer中斷。
(4)再次按下S1后,串口通中打印信息為“requestSTANDBY”,此時電流約為2.4uA,并間隔產生lptimer中斷。
(5)再次按下S1后,串口通中打印信息為“requestNONE”,恢復為(1)的電流值,然后可循環執行此流程。
-
mcu
+關注
關注
146文章
17123瀏覽量
350992 -
瑞薩
+關注
關注
35文章
22308瀏覽量
86240 -
RT-Thread
+關注
關注
31文章
1285瀏覽量
40085
原文標題:基于瑞薩 RA2L1 MCU 的RT-Thread 低功耗應用筆記
文章出處:【微信號:RTThread,微信公眾號:RTThread物聯網操作系統】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論