一、实验平台:
测试板:PCA10028
协议栈版本:nRF5_SDK_12.3.0_d7731ad
例程所在位置:nRF5_SDK_12.3.0_d7731adexamplesperipheralpwr_mgmt
官方解释:http://infocenter.nordicsemi.com/index.jsp
二、流程解释
根据官方的测试流程:按下BUTTON1后,进入bsp_evt_handler()的BSP_EVENT_KEY_0分支,将m_is_ready设置为true。
case BSP_EVENT_KEY_0:
if (m_is_ready)
{
m_is_ready = false;
NRF_LOG_INFO("System is not ready for shutdown
");
}
else
{
m_is_ready = true;
NRF_LOG_INFO("System is ready for shutdown
");
}
if (m_sysoff_started && m_is_ready)
{
NRF_LOG_INFO("m_sysoff_started && m_is_ready is true
");
nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_CONTINUE);
}
break;
在按BUTTON2,进入BSP_EVENT_SLEEP分支,因为m_stay_in_sysoff=false,执行nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);函数。事件类型的定义是一个enmu。NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF=0。
case BSP_EVENT_SLEEP:
if (m_stay_in_sysoff)
{
NRF_LOG_INFO("m_stay_in_sysoff is true
");
nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_STAY_IN_SYSOFF);
}
else
{
NRF_LOG_INFO("m_stay_in_sysoff is false
");
nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
}
break;
nrf_pwr_mgmt_shutdown()函数内,将形参赋给m_pwr_mgmt_evt,之后执行shutdown_process();关机处理函数。
在shutdown_process();中执行if ((*PWR_MGMT_SECTION_VARS_GET(m_next_handler))(m_pwr_mgmt_evt))时会执行 执行关机回调函数,将事件类型做为参数传入。该回调函数是在main.c中注册的
bool app_shutdown_handler(nrf_pwr_mgmt_evt_t event);
//lint -esym(528, m_app_shutdown_handler)
NRF_PWR_MGMT_REGISTER_HANDLER(m_app_shutdown_handler) = app_shutdown_handler;
进入到bool app_shutdown_handler(nrf_pwr_mgmt_evt_t event)
if (m_is_ready == false)
{
m_sysoff_started = true;
NRF_LOG_INFO(" m_sysoff_started = true
");
return false;
}
switch (event)
{
case NRF_PWR_MGMT_EVT_PREPARE_SYSOFF:
NRF_LOG_INFO("NRF_PWR_MGMT_EVT_PREPARE_SYSOFF..
");
err_code = bsp_buttons_disable(); //关闭按键中断 睡眠之后无法唤醒
APP_ERROR_CHECK(err_code);
break;
case NRF_PWR_MGMT_EVT_PREPARE_WAKEUP:
err_code = bsp_wakeup_button_enable(BTN_ID_WAKEUP); //设置按键唤醒
APP_ERROR_CHECK(err_code);
NRF_LOG_INFO("NRF_PWR_MGMT_EVT_PREPARE_WAKEUP
");
err_code = bsp_nfc_sleep_mode_prepare(); //设置NFCT为唤醒源
// Suppress NRF_ERROR_NOT_SUPPORTED return code.
UNUSED_VARIABLE(err_code);
break;
case NRF_PWR_MGMT_EVT_PREPARE_DFU:
NRF_LOG_ERROR("Entering DFU is not supported by this example.
");
APP_ERROR_HANDLER(NRF_ERROR_API_NOT_IMPLEMENTED);
break;
}
m_is_ready=true,进入NRF_PWR_MGMT_EVT_PREPARE_WAKEUP分支。
之后跳转到bool app_shutdown_handler(nrf_pwr_mgmt_evt_t event)回调函数中的NRF_PWR_MGMT_EVT_PREPARE_WAKEUP分支,首先执行bsp_wakeup_button_enable(BTN_ID_WAKEUP);设置按键唤醒
bsp_nfc_sleep_mode_prepare();设置NFCT为唤醒源
之后回到shutdown_process();
最后执行NRF_POWER->SYSTEMOFF = POWER_SYSTEMOFF_SYSTEMOFF_Enter;执行休眠