RP2040のDORMANT modeを試す
RP2040 Datasheetではdormant modeの消費電流はTypicalで0.18mA、もちろんこれはChip単体での数字ですので、ボードとしての消費電流を把握する必要があります。Seeed XIAO RP2040と構成がほぼ同じのPaspberry Pi Pico Datasheetを調べると、dormant modeでの平均消費電流は0.8mAとのこと。機器に組込むことを考えると1mA以下に出来れば及第点といえるのですが。。
いきなりですが下記が今回試したコードになります。
dormant_test.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
// dormant mode sample for Seeed XIAO RP2040 #undef SHOW_MESSAGE #include <stdio.h> #include "pico/stdlib.h" #include "pico/sleep.h" #include "hardware/clocks.h" #include "hardware/rosc.h" #define LedPinBlue 25 // output: the number of the LED pin of Blue #define LedPinGreen 16 // output: the number of the LED pin of Green #define LedPinRed 17 // output: the number of the LED pin of Red #define WakeupTrigger 6 // input : wakeup trigger by GPIO #ifdef SHOW_MESSAGE void measure_freqs(void) { uint f_pll_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_SYS_CLKSRC_PRIMARY); uint f_pll_usb = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_USB_CLKSRC_PRIMARY); uint f_rosc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC); uint f_clk_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_SYS); uint f_clk_peri = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_PERI); uint f_clk_usb = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_USB); uint f_clk_adc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_ADC); uint f_clk_rtc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_RTC); printf("pll_sys = %dkHz\n", f_pll_sys); printf("pll_usb = %dkHz\n", f_pll_usb); printf("rosc = %dkHz\n", f_rosc); printf("clk_sys = %dkHz\n", f_clk_sys); printf("clk_peri = %dkHz\n", f_clk_peri); printf("clk_usb = %dkHz\n", f_clk_usb); printf("clk_adc = %dkHz\n", f_clk_adc); printf("clk_rtc = %dkHz\n", f_clk_rtc); uart_default_tx_wait_blocking(); } #endif int main() { // reduce system clock set_sys_clock_khz(18000, true); stdio_init_all(); #ifdef SHOW_MESSAGE printf("\nBoot\n"); measure_freqs(); #endif // GPIO initialization (LEDs on XIAO-RP2040 board) gpio_init(LedPinBlue); gpio_set_dir(LedPinBlue, GPIO_OUT); gpio_put(LedPinBlue, 1); gpio_init(LedPinGreen); gpio_set_dir(LedPinGreen, GPIO_OUT); gpio_put(LedPinGreen, 1); gpio_init(LedPinRed); gpio_set_dir(LedPinRed, GPIO_OUT); gpio_put(LedPinRed, 1); // Intialization & activation of the trigger pin for waking up from sleep mode gpio_init(WakeupTrigger); gpio_set_dir(WakeupTrigger, GPIO_IN); gpio_pull_down(WakeupTrigger); gpio_set_input_enabled(WakeupTrigger, true); while (true) { sleep_ms(5000); sleep_run_from_xosc(); // Go to sleep until to get high edge on WakeupTrigger (GPIO 6) sleep_goto_dormant_until_edge_high(WakeupTrigger); // ----- ここでP6の立ち上がりエッジ待ちとなる ----- // ----- ↓↓↓Wakeup後の処理↓↓↓ ----- // Re-enable ring Oscillator control rosc_write(&rosc_hw->ctrl, ROSC_CTRL_ENABLE_BITS); // reset clocks clocks_init(); set_sys_clock_khz(18000, true); stdio_init_all(); #ifdef SHOW_MESSAGE printf("\nWake-up\n"); measure_freqs(); #endif } } |
ビルドには「pico-extras」を導入します。pico-sdkを入れたフォルダにて、下記のようにします。
1 2 |
$ git clone -b master https://github.com/raspberrypi/pico-extras.git $ cp pico-extras/external/pico_extras_import.cmake work/ |
CMakeLists.txtを変更します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
cmake_minimum_required(VERSION 3.13) # Pull in SDK (must be before project) include(../pico_sdk_import.cmake) # We also need PICO EXTRAS include(../pico_extras_import.cmake) # project name set(ProjectName "dormant_test") project(${ProjectName} C CXX ASM) set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 17) set(PICO_SDK_PATH="[SDKをインストールしたフォルダ]/pico-sdk") set(PICO_EXTRAS_PATH="[SDKをインストールしたフォルダ]/pico-extras") pico_sdk_init() # executable name add_executable(${ProjectName} dormant_test.c ) # enable serial output pico_enable_stdio_usb(${ProjectName} 1) pico_enable_stdio_uart(${ProjectName} 1) # pull in common dependencies target_link_libraries(${ProjectName} pico_stdlib hardware_sleep) # create map/bin/hex file etc. pico_add_extra_outputs(${ProjectName}) |
前回作成したbuildフォルダを削除し、cmakeからやり直します。(buildフォルダの丸ごと削除でスッキリ初期化出来るので便利です)
1 2 3 4 5 6 |
rm -rf build mkdir build cd build export PICO_SDK_PATH="[SDKをインストールしたフォルダ]/pico-sdk" cmake .. make |
起動後、5秒後にdormant modeへ移行、GPIO P6への立ち上がりエッジ入力でWake-up&通常動作へ復帰、再度5秒後にdormant modeへ、というループです。色々と試してみたのですが、dormant mode後に通常動作へ完全に復帰させるには上記のサンプルコードのようにするのが唯一見つけられた方法でした。(もっとスマートに出来そうな気はするのですが、、)
冒頭の「SHOW_MESSAGE」にてRP2040のUART(Tx)からクロック設定の様子をモニタ出来るようにしてあります(115200baud)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
Boot pll_sys = 18000kHz pll_usb = 48000kHz rosc = 5483kHz clk_sys = 18000kHz clk_peri = 48000kHz clk_usb = 48000kHz clk_adc = 48000kHz clk_rtc = 47kHz Wake-up pll_sys = 18000kHz pll_usb = 48000kHz rosc = 5483kHz clk_sys = 18000kHz clk_peri = 48000kHz clk_usb = 48000kHz clk_adc = 48000kHz clk_rtc = 47kHz |
実際に動作させてみると、クロック18MHzの設定で通常動作=9.1mA、dormant mode=2.3mA程でした。
どうもPaspberry Pi Picoボードに比べてSeeed XIAO RP2040は消費電流が多いような気がします。比較する良い方法が無いかとPaspberry Pi Pico Datasheetを眺めていたら、BOOTSEL mode (USB idle)での消費電流が8.7mAとの記載を見つけました。
Seeed XIAO RP2040に5V電源のみ与えて、BOOTSEL modeに入れてみる(bootボタンを押しながらリセットする)と12.5mAでした。PicoとXIAOの回路的な差は殆ど無いので、余計なLED分か3.3Vレギュレータの効率の差か??
いずれにしてもSeeed XIAO RP2040の限界は見えた気はします。非常に小さなボードであることと、別途デバッガやプログラマを用意せずにソフト開発が可能なこと(つまり安く済ませたい)で選んだのですが、消費電力面でやはりちょっと厳しいという結果になりました。尤も「RP2040を触ってみたい」という別の面の欲求は満たされたわけですが。。
もうちょっと良い使い途を考えてみます → RP2040
コメント