NRF52832开启HFCLK后遇到低功耗和睡眠问题
在验证NRF52832的低功耗,没有使用softdevice,外接高速、低速晶振,并使用外部的晶振为时钟源。现在做了一个简答的测试,功能主要是:
a、将HFCLK、LFCLK开启,分别使用外部晶振。
b、使能一个GPIO作为Led电灯,开启rtc0的比较中断0,作为唤醒,设置时间为5秒,rtc的中断中再次设置下次超时时间为5秒
c、while循环中包含以下几个步骤:
- 关闭HFCLK(即HFXO)(降低功耗)
- 进入休眠(这里为了测试,验证了几种写法:WFI、WFE、WFE SEV WFE、SEV WFE WFE)
- 因rtc中断退出休眠,重新开启HFCLK(即HFXO)
- 电量Led灯,循环等待一段时间,然后关闭Led,这样Led发光更为明显
预期结果:每隔5秒
测试遇到如下问题:
1、在main中的循环中,睡眠之前不关闭HFCLK,功耗比较高有280uA左右,如果关闭HCLK,低功耗可以到3uA。但是我从手册里面看HFCLK描述的是如果没有peripheral需要HCLK,不需要关闭,他自动会进入节能模式,这里的200uA已经是节能模式了吗?感觉还是在运行。从sdk里面看无softdevice的低功耗例程,睡眠之前并没有对HFCLK进行处理。
2、基于1中的需要在睡眠之前进行HCLK的开启和关闭,如果睡眠使用WFI,整个功能是正常的,但是使用WFE或WFE SEV WFE都是不正常的,其实也就是意味着执行WFE的时候,有“原因导致”无法进入低功耗。如果在睡眠前后不对HFCLK进行开启、关闭,则可以正常睡眠,只是功耗高,后定位与HFCLK关闭没有关系,主要是开启导致的问题。但是SEV WFE WFE是正常的,因为SEV WFE会把所有事件清除,后面的WFE会让MCU进入低功耗状态。但是这种方式是有风险的,先清除事件,会导致某个真实的唤醒没有阻止进入休眠。
这里的问题在于clock的中断都是开启的,低功耗后面的HFCLK开启时触发的中断已经在ISR进行事件清除,为什么还会影响接下来的睡眠呢?
以下是测试的代码:
static void _rtc0_timer_callback(nrfx_rtc_int_type_t int_type);
#define LED_PIN 13
static void led_init(void)
{
nrf_gpio_cfg_output(LED_PIN);
}
static void led_turn_on(void)
{
nrf_gpio_pin_write(LED_PIN, 0);
}
static void led_turn_off(void)
{
nrf_gpio_pin_write(LED_PIN, 1);
}
void _rtc_timer_start(void)
{
nrfx_rtc_t timer_inst = NRFX_RTC_INSTANCE(0);
nrfx_rtc_config_t timer_cfg = NRFX_RTC_DEFAULT_CONFIG;
// low frequency clock
nrf_clock_lf_src_set((nrf_clock_lfclk_t)1);
nrfx_clock_lfclk_start();
// config
timer_cfg.prescaler = RTC_FREQ_TO_PRESCALER(32768);
nrfx_rtc_init(&timer_inst, &timer_cfg, _rtc0_timer_callback);
nrfx_rtc_counter_clear(&timer_inst);
nrfx_rtc_overflow_enable(&timer_inst, true);
nrfx_rtc_enable(&timer_inst);
}
void _rtc_timer_set_next(uint32_t time_us)
{
uint32_t tick;
tick = (uint32_t)(time_us / (1000000.0 / 32768));
nrfx_rtc_t timer_inst = NRFX_RTC_INSTANCE(0);
tick = (tick + nrfx_rtc_counter_get(&timer_inst));
nrfx_rtc_cc_set(&timer_inst, 0, tick, true);
}
static void _rtc0_timer_callback(nrfx_rtc_int_type_t int_type)
{
// set next timeout
_rtc_timer_set_next(5000000);
}
static void clk_event_handler(nrfx_clock_evt_type_t event)
{
}
int main(void)
{
nrfx_clock_init(clk_event_handler);
nrfx_clock_enable();
nrfx_clock_hfclk_start();
while(nrfx_clock_hfclk_is_running() == false)
{
}
nrfx_clock_lfclk_start();
while(nrfx_clock_lfclk_is_running() == false)
{
}
led_init();
led_turn_off();
_rtc_timer_start();
_rtc_timer_set_next(5000000);
while(1)
{
// 关闭外部高速晶振,切换到内部,降低功耗
nrfx_clock_hfclk_stop();
// 使用这个睡眠,灯一直在点亮,无法进入低功耗
// __WFE();
// __SEV();
// __WFE();
// 使用这个睡眠,行为符合预期,但是可能前面的某个事件无法中止进入睡眠
// __SEV();
// __WFE();
// __WFE();
// 使用这个睡眠,行为符合预期
__WFI();
// 使用这个睡眠,灯一直在点亮,无法进入低功耗
// __WFE();
// 重新开启外部高速晶振
// 只要把这一行注释掉,上面的几种睡眠行为都符合预期,
// 但是clock的中断是使能的,为什么会影响wfe的行为?
nrfx_clock_hfclk_start();
while(nrfx_clock_hfclk_is_running() == false)
{
}
// 点亮一会Led,使其观察明显
led_turn_on();
for(uint32_t i = 1000000; i > 0; i--)
{
__NOP();
}
led_turn_off();
}
}
页:
[1]