物联网开发——TencentOS Tiny 功耗管理

低功耗

概述

TencentOS tiny提供了多级低功耗管理框架。初级低功耗的方案是,当系统处于“空闲”状态,也即进入idle任务时,系统调用处理器(目前支持的架构是arm v7m)低功耗接口进入短暂的睡眠模式。

API讲解

编程实例

对于初级低功耗模式,无需用户编写任何代码,直接通过在tos_config.h打开TOS_CFG_PMR_MGR_EN开关即可:

#define TOS_CFG_PWR_MGR_EN 1u

运行效果

 

 tickless

概述

TencentOS tiny的tickless机制提供了一套非周期性时钟的方案,在系统无需systick驱动调度的情况下,停掉systick。

初级功耗管理方案下,因为还有系统systick的存在,因此系统进入idle任务后,并不会在睡眠模式下停留太久。要想进入到更极致的低功耗状态,需要暂停systick。

arm架构提供三级低功耗模式,sleep、stop、standby模式,三种模式运行功耗逐次降低,standby模式最低。TencentOS tiny的内核提供了简洁清晰的接口来管理各级模式。

API讲解

void tos_tickless_wkup_alarm_install(k_cpu_lpwr_mode_t mode, k_tickless_wkup_alarm_t *wkup_alarm);

此接口用以安装各低功耗模式下的唤醒闹钟。当内核进入tickless模式下后,systick以及停止了,因此需要其他计时器来将CPU从低功耗模式下唤醒。

根据arm v7m的芯片规格,三种模式下的唤醒源分别为:

  • sleep

    CPU进入sleep模式后,可以由systick、硬件timer、RTC时钟唤醒(wakeup/alarm中断)。

  • stop

    CPU进入stop模式后,可以由RTC时钟(wakeup/alarm中断)唤醒。

  • standby

    CPU进入standby模式后,只可由RTC时钟的alarm中断唤醒(还可以通过外部管脚唤醒,但这不属于TencentOS tiny内核机制设计的范畴)。

k_tickless_wkup_alarm_t定义如下:

typedef struct k_tickless_wakeup_alarm_st {
    int         (*init)(void);
    int         (*setup)(k_time_t millisecond);
    int         (*dismiss)(void);
    k_time_t    (*max_delay)(void); /* in millisecond */
} k_tickless_wkup_alarm_t;

一个唤醒闹钟有四个成员方法:

  • init

    闹钟初始化函数。

  • setup

    闹钟设定函数,入参为闹钟到期时间(单位毫秒)。此闹钟在设定完毕后的millisecond毫秒时来中断。

  • dismiss

    闹钟解除函数,执行完后闹钟中断不会再来。

  • max_delay

    此闹钟最长的到期时间(单位为毫秒)。

k_err_t tos_tickless_wkup_alarm_init(k_cpu_lpwr_mode_t mode);

此函数用来初始化特定模式下的唤醒闹钟(实际上调用的是tos_tickless_wkup_alarm_install接口中安装的k_tickless_wkup_alarm_t的init方法)。

k_err_t tos_pm_cpu_lpwr_mode_set(k_cpu_lpwr_mode_t cpu_lpwr_mode);

设置内核在tickless模式下进入的CPU低功耗模式。

编程实例

1、在tos_config.h中,配置低功耗组件开关TOS_CFG_PWR_MGR_EN:

#define TOS_CFG_PWR_MGR_EN 1u

2、在tos_config.h中,配置tickless组件开关TOS_CFG_TICKLESS_EN:

#define TOS_CFG_TICKLESS_EN 1u

3、编写main.c示例代码:

#include "tos.h"
#include "mcu_init.h"

#define STK_SIZE_TASK_DEMO      512 

#define PRIO_TASK_DEMO          4
 
k_stack_t stack_task_demo[STK_SIZE_TASK_DEMO]; 

k_task_t task_demo;

extern void entry_task_demo(void *arg);

void timer_callback(void *arg)
{
    printf("timer callback: %lld\n", tos_systick_get());
}

void entry_task_demo(void *arg)
{
    k_timer_t tmr;

    // 创建一个软件定时器,每6000个tick触发一次
    tos_timer_create(&tmr, 0u, 6000u, timer_callback, K_NULL, TOS_OPT_TIMER_PERIODIC);
    tos_timer_start(&tmr);

    // 此任务体内每3000个tick运行一次
    while (K_TRUE) {
        printf("entry task demo: %lld\n", tos_systick_get());
        tos_task_delay(3000);
    }
}

int main(void)
{
    board_init();
    tos_knl_init(); 
    (void)tos_task_create(&task_demo, "demo1", entry_task_demo, NULL,
                            PRIO_TASK_DEMO, stack_task_demo, STK_SIZE_TASK_DEMO,
                            0); 
    tos_knl_start();
}

4、实现tos_bsp_tickless_setup回调(参考board\TOS_tiny_EVK_STM32L431CBT6\BSP\Src\tickless\bsp_pwr_mgr.c、board\TOS_tiny_EVK_STM32L431CBT6\BSP\Src\tickless\bsp_tickless_alarm.c):

#include "tos.h"
#include "tickless/bsp_pm_device.h"
#include "tickless/bsp_tickless_alarm.h"

int tos_bsp_tickless_setup(void)
{
#if TOS_CFG_TICKLESS_EN > 0u
    // sleep模式下的唤醒源,基本定时器
    tos_tickless_wkup_alarm_install(TOS_LOW_POWER_MODE_SLEEP, &tickless_wkup_alarm_tim);
    // 初始化唤醒源闹钟
    tos_tickless_wkup_alarm_init(TOS_LOW_POWER_MODE_SLEEP);
    // 设置tickless状态时进入sleep模式
    tos_pm_cpu_lpwr_mode_set(TOS_LOW_POWER_MODE_SLEEP);
#endif
}

5、为了观察在tickless时是否确实没有systick中断,在tos_sys.c的idle任务体内加一句调试代码:

__STATIC__ void knl_idle_entry(void *arg)
{
    arg = arg; // make compiler happy

    while (K_TRUE) {
        // 这里在idle任务体内加上一句打印,如果systick正常开启,在没有用户任务运行时,此调试信息会不断打印;如果是tickless状态,此调试信息应该只会第一次进入idle任务时,或在用户任务等待到期,或用户的软件定时器到期时,才打印一次。
        printf("idle entry: %lld\n", tos_systick_get());
#if TOS_CFG_PWR_MGR_EN > 0u
        pm_power_manager();
#endif
    }
}

运行效果

entry task demo: 0 idle entry: 2 entry task demo: 3002 idle entry: 3002 timer callback: 6000 idle entry: 6000 entry task demo: 6002 idle entry: 6002 entry task demo: 9002 idle entry: 9002 timer callback: 12000 idle entry: 12000 entry task demo: 12002 idle entry: 12002 entry task demo: 15002 idle entry: 15002 timer callback: 18000 idle entry: 18000 entry task demo: 18002 idle entry: 18002

你可能感兴趣的:(物联网)