Cortex M0 不进入睡眠模式

Posted

技术标签:

【中文标题】Cortex M0 不进入睡眠模式【英文标题】:Cortex M0 doesn't enter sleep mode 【发布时间】:2016-05-16 12:55:47 【问题描述】:

在解释的专业开发板上遇到了 Atmel SAMB11 问题。我从 Atmel 加载了一个非常简单的示例,其中初始化了一个 32KHz 定时器以将 µC 从睡眠中唤醒并打开 LED。问题是,控制器根本不睡觉。它只是立即激活 LED 而不会等待中断。

#include <asf.h>

// Callback Func to enable LED
static void aon_sleep_timer_callback(void)

    gpio_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);

//Configure LED
static void configure_gpio_pins(void)

    struct gpio_config config_gpio_pin;
    gpio_get_config_defaults(&config_gpio_pin);
    config_gpio_pin.direction = GPIO_PIN_DIR_OUTPUT;
    gpio_pin_set_config(LED_0_PIN, &config_gpio_pin);
    gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);

// Configure Timer with 10sec to overflow
static void configure_aon_sleep_timer(void)

    struct aon_sleep_timer_config config_aon_sleep_timer;
    aon_sleep_timer_get_config_defaults(&config_aon_sleep_timer);
    config_aon_sleep_timer.counter = 320000; // Wait about 10sec
    aon_sleep_timer_init(&config_aon_sleep_timer);

// Configure Callback and enable Interrupt
static void configure_aon_sleep_timer_callback(void)

    aon_sleep_timer_register_callback(aon_sleep_timer_callback);
    NVIC_EnableIRQ(AON_SLEEP_TIMER_IRQn);


int main(void)

    // Setup Clock, LED and Timer
    system_clock_config(CLOCK_RESOURCE_XO_26_MHZ, CLOCK_FREQ_26_MHZ);
    configure_gpio_pins();
    configure_aon_sleep_timer();
    configure_aon_sleep_timer_callback();

    // wait for timer to be active
    while(!aon_sleep_timer_sleep_timer_active());
    // Go to sleep
    asm volatile ("wfi");
    asm volatile ("nop");
    // Enable LED immediately if sleep doesn't work
    gpio_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
    while (true) 

代码似乎不言自明,但 WFI 命令在这里不起作用。有人可以帮忙吗?

【问题讨论】:

aon_sleep_timer_sleep_timer_active() 做了什么——它只是轮询状态寄存器还是什么?使用两个不同的 LED 会很方便,这样您就可以知道您是真的立即接受中断,还是由于其他事件而中断。 【参考方案1】:

只是为了补充 Prestige Worldwide 的答案。

确保 AO_GPIO0/1/2 为低电平(建议下拉),并且没有发生 AON 睡眠定时器中断,因为这些会从 ULP 唤醒 SAMB11。

另请注意,通过 SWD 运行调试会话时,ULP 模式似乎无法按预期工作。

在运行调试和睡眠/唤醒时,我有各种奇怪的行为,但在不调试的情况下运行相同的代码时完全没有问题。请注意,这是使用 Atmel ICE。 Xplored 板包含 EDBG,而且这个调试器似乎可以与 ULP 一起工作。

resume 回调从未对我触发,可能是 ASF 中的错误。但我不需要它,因为我可以在平台等待后设置所有 GPIO/设备。

【讨论】:

这没有提供问题的答案。一旦你有足够的reputation,你就可以comment on any post;相反,provide answers that don't require clarification from the asker。 - From Review 我提供了 3 个导致“Cortex M0 无法进入睡眠模式”的原因,作者需要检查它是否能解决问题。这怎么不是答案?【参考方案2】:

WFI 调用有效,它只是在调用后几乎立即收到一个中断,这导致 WFI 调用停止阻塞,然后继续执行下一行。

您可以安全地删除// Go to sleep 下面的所有内容,这将允许主函数返回。 AON 计时器仍将执行其回调。但是,这种方法有几个潜在的缺点:

这将不允许 SAMB11 转换到低功耗模式。 这会删除 main 末尾的 while 循环。在当前状态下,不需要 while 循环,但您可能计划稍后向其中添加代码。

这是一个配置 AON、配置 SAMB11 以使用低功耗模式,然后循环等待平台和/或 BLE 事件的示例。目前没有任何事件可供循环接收。如果您希望循环接收事件,则可以修改 AON 回调以使用 at_ble_event_user_defined_post 函数发布事件或修改 main() 以在进入循环之前配置 BLE 模块。

使用 ASF 向导将任何 BLE 模块添加到您的项目中以编译此示例。

#include <asf.h>
#include "platform.h"

// Configure LED
static void configure_gpio_pins(void)

    struct gpio_config config_gpio_pin;
    gpio_get_config_defaults(&config_gpio_pin);
    config_gpio_pin.direction = GPIO_PIN_DIR_OUTPUT;
    gpio_pin_set_config(LED_0_PIN, &config_gpio_pin);
    gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);


// Callback Func to toggle LED
static bool led_is_on = false;
static void aon_sleep_timer_callback(void)

    configure_gpio_pins();
    if(led_is_on) 
        gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
        led_is_on = false;
     else 
        gpio_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
        led_is_on = true;
    


// Configure Timer to fire periodically
static void configure_aon_sleep_timer(void)

    struct aon_sleep_timer_config config_aon_sleep_timer;
    aon_sleep_timer_get_config_defaults(&config_aon_sleep_timer);
    config_aon_sleep_timer.counter = 32000; // Wait about 1 sec
    config_aon_sleep_timer.mode = AON_SLEEP_TIMER_RELOAD_MODE;
    aon_sleep_timer_init(&config_aon_sleep_timer);

// Configure Callback and enable Interrupt
static void configure_aon_sleep_timer_callback(void)

    aon_sleep_timer_register_callback(aon_sleep_timer_callback);
    NVIC_EnableIRQ(AON_SLEEP_TIMER0_IRQn);


int main(void)

    // Setup Clock
    system_clock_config(CLOCK_RESOURCE_XO_26_MHZ, CLOCK_FREQ_26_MHZ);

    plf_drv_status plf_status;
    if((plf_status = platform_driver_init()) == STATUS_SUCCESS) 

        // Setup LED and Timer
        configure_gpio_pins();
        configure_aon_sleep_timer();
        configure_aon_sleep_timer_callback();

        // wait for timer to be active
        while(!aon_sleep_timer_sleep_timer_active());

        // Go to sleep
        release_sleep_lock();
        while(true) 
            // Replace platform_event_wait with at_ble_event_get if you would like to read the received event.
            plf_status = platform_event_wait(0);
        
    


关于WFI,下面的例子展示了如何关闭大部分中断并使用WFI来阻塞main()。每次接收到中断时,LED 都会切换。我不建议使用它,因为我不确定为什么最初启用这些中断。这只是为了展示 WFI 如何阻止 SAMB11。

#include <asf.h>
#include "platform.h"

// Configure LED
static void configure_gpio_pins(void)

    struct gpio_config config_gpio_pin;
    gpio_get_config_defaults(&config_gpio_pin);
    config_gpio_pin.direction = GPIO_PIN_DIR_OUTPUT;
    gpio_pin_set_config(LED_0_PIN, &config_gpio_pin);
    gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);


// Callback Func to toggle LED
static bool led_is_on = false;
static void toggle_led(void)

    configure_gpio_pins();
    if(led_is_on) 
        gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
        led_is_on = false;
     else 
        gpio_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
        led_is_on = true;
    


int main(void)

    // Setup Clock
    system_clock_config(CLOCK_RESOURCE_XO_26_MHZ, CLOCK_FREQ_26_MHZ);

    // Clear all interrupts.
    NVIC->ICER[0] = 0xFFFFFFFF;

    // During testing, interrupts were received about once per second; stopped receiving interrupts (LED stopped flashing) after about 2 minutes.
    int loop_count = 0;
    while(true) 
        __WFI();
        toggle_led();
    

【讨论】:

以上是关于Cortex M0 不进入睡眠模式的主要内容,如果未能解决你的问题,请参考以下文章

CentOS 7合盖后黑屏但不进入睡眠模式修改

使计算机进入睡眠状态是啥意思

睡眠模式是啥?

有没有办法阻止我的 Razer 笔记本电脑随机进入睡眠模式? [关闭]

电脑进入睡眠模式后再点开窗口变模糊了,怎么办

如何使用 Swift 以编程方式让 Mac 进入睡眠状态