6
7

More than 5 years have passed since last update.

nRF52 でSleepからGPIOで復帰

Posted at

「nRF52840 の sleep を試す (Nordic SDK/Softdevice)」
https://qiita.com/nanbuwks/items/c2f098793899001b5087
で、System OFF modeからの復帰について、

データーシートによると以下のトリガで復帰することができる。

1.The DETECT signal, optionally generated by the GPIO peripheral.
2.The ANADETECT signal, optionally generated by the LPCOMP module.
3.The SENSE signal, optionally generated by the NFC module to wake-on-field.
4.Detecting a valid USB voltage on the VBUS pin (V BUS,DETECT ).
5.A reset.

と書いた。このうち1.を実現するもの。

環境

  • Raytac MDBT50Q-DB ( Nordic nRF52840 SoC )
  • Nordic nRF5 SDK v15.2.0
  • SEGGER Embedded studio for ARM V4.10a
  • J-link v9(中華製)

ひながた

元々、Nordic の SDK 中のサンプルプログラム
examples/ble_peripheral/
に収録されているble_app_uart を使ってテスト。

これには、

sleep解除はボタン1または2で解除するようになっている。


static void sleep_mode_enter(void)
{
    uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE);
    APP_ERROR_CHECK(err_code);

    // Prepare wakeup buttons.
    err_code = bsp_btn_ble_sleep_mode_prepare();
    APP_ERROR_CHECK(err_code);

    // Go to system-off mode (this function will not return; wakeup will cause a reset).
    err_code = sd_power_system_off();
    APP_ERROR_CHECK(err_code);
}

これの、bsp_btn_ble_sleep_mode_prepare();によってボード上のタクトスイッチによって復帰する設定になっている。

bsp_btn_ble.c


uint32_t bsp_btn_ble_sleep_mode_prepare(void)
{
    uint32_t err_code;

    err_code = bsp_wakeup_button_enable(BTN_ID_WAKEUP);
    RETURN_ON_ERROR_NOT_NOT_SUPPORTED(err_code);

    err_code = bsp_wakeup_button_enable(BTN_ID_WAKEUP_BOND_DELETE);
    RETURN_ON_ERROR_NOT_NOT_SUPPORTED(err_code);

    return NRF_SUCCESS;
}

とあり、このBTN_ID_WAKEUがボタンスイッチ1,
BTN_ID_WAKEUP_BOND_DELETEがボタンスイッチ2になる。

これらのボタンスイッチはGPIOに接続しているので同じGPIOにセンサなり外部信号なりをつなげたらいいのであるが、自由にGPIOに接続したいですね。

ということでbsp_wakeup_button_enable を辿って行くと同じ bsp_btn_ble.c に


uint32_t bsp_wakeup_button_enable(uint32_t button_idx)
{
    return wakeup_button_cfg(button_idx, true);
}

uint32_t bsp_wakeup_button_disable(uint32_t button_idx)
{
    return wakeup_button_cfg(button_idx, false);
}

とあり、wakeup_button_cfg も同様に bsp_btn_ble.c で以下のように定義されている。

static uint32_t wakeup_button_cfg(uint32_t button_idx, bool enable)
{
#if !defined(BSP_SIMPLE)
    if (button_idx <  BUTTONS_NUMBER)
    {
        nrf_gpio_pin_sense_t sense = enable ?
                         (BUTTONS_ACTIVE_STATE ? NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW) :
                         NRF_GPIO_PIN_NOSENSE;
        nrf_gpio_cfg_sense_set(bsp_board_button_idx_to_pin(button_idx), sense);
        return NRF_SUCCESS;
    }
#else
    UNUSED_PARAMETER(button_idx);
    UNUSED_PARAMETER(enable);
#endif
    return NRF_ERROR_NOT_SUPPORTED;

}

ということなので、以下の処理を行えば良い。
 

HでSleep解除する場合


        nrf_gpio_cfg_sense_set(pin_number, NRF_GPIO_PIN_SENSE_HIGH);

LをSleep解除する場合


        nrf_gpio_cfg_sense_set(pin_number, NRF_GPIO_PIN_SENSE_LOW);

Sleep解除を無効にする場合


        nrf_gpio_cfg_sense_set(pin_number, NRF_GPIO_PIN_NOSENSE);

なお、この引数ですが

modules/nrfx/hal/nrf_gpio.h

において、


    NRF_GPIO_PIN_SENSE_HIGH = GPIO_PIN_CNF_SENSE_High,     ///<  Pin sense high level.

とあり、更に
modules/nrfx/mdk/nrf52_bitfields.h
において、


#define GPIO_PIN_CNF_SENSE_High (2UL)
#define GPIO_PIN_CNF_SENSE_Low (3UL) /*!< Sense for low level */

とあります。
また、 pin_number については、


modules/nrfx/hal/nrf_gpio.h
内で

__STATIC_INLINE void nrf_gpio_cfg_sense_set(uint32_t pin_number, nrf_gpio_pin_sense_t sense_config)
{
    NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number);

    /*lint -e{845} // A zero has been given as right argument to operator '|'" */
    reg->PIN_CNF[pin_number] &= ~GPIO_PIN_CNF_SENSE_Msk;
    reg->PIN_CNF[pin_number] |= (sense_config << GPIO_PIN_CNF_SENSE_Pos);
}

とあり、データーシートの「6.9.2.10 PIN_CNFn」にあるレジスタの記述を読むと、この説明のID=Eである「RW SENSE」に2を書き込むとHをディテクト、3を書き込むとLをディテクトするということで先の


#define GPIO_PIN_CNF_SENSE_High (2UL)
#define GPIO_PIN_CNF_SENSE_Low (3UL) /*!< Sense for low level */

に対応していることになります。

pullup

なお、外部にプルアップなどをつなげている場合はこのままでもいいですがそうではない場合、プルアップ指定をしているのがいいでしょう。
以下は、GPIO の P0.18 を(Reset指定を解除した上で)プルアップして、GNDレベルになるるとスリープ解除するようにした例です。


    nrf_gpio_cfg_input(NRF_GPIO_PIN_MAP(0,18),NRF_GPIO_PIN_PULLUP);
    nrf_gpio_cfg_sense_set(18, NRF_GPIO_PIN_SENSE_LOW);
6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7