RTC - DLPS

该示例通过使用 RTC 定时进行 DLPS 唤醒。

当系统处于 IDLE 状态时,会自动进入 DLPS 状态。当 RTC 定时结束后会将系统从 DLPS 唤醒,同时触发 RTC 中断。

RTC 的 Tick 中断,溢出中断,4 路比较器中断和分频比较器中断均可以唤醒系统。

该示例以 Tick 定时唤醒进行说明举例。

环境需求

该示例支持以下开发套件:

开发套件

Hardware Platforms

Board Name

RTL8752H HDK

RTL8752H EVB

更多信息请参考 快速入门

编译和下载

该示例的工程路径如下:

Project file: board\evb\io_sample\RTC\Dlps\mdk

Project file: board\evb\io_sample\RTC\Dlps\gcc

请按照以下步骤操作构建并运行该示例:

  1. 打开工程文件。

  2. 按照 快速入门编译 APP Image 给出的步骤构建目标文件。

  3. 编译成功后,在路径 mdk\bingcc\bin 下会生成 app bin app_MP_xxx.bin 文件。

  4. 按照 快速入门MP Tool 给出的步骤将 app bin 烧录至 EVB 内。

  5. 按下 reset 按键,开始运行。

测试验证

  1. 当 EVB 复位后,系统进入 DLPS 状态。在 Debug Analyzer 工具内打印相应信息。

    DLPS ENTER
    
  2. 当 Tick 定时结束后(1s),系统被唤醒,退出 DLPS 状态。在 Debug Analyzer 工具内打印相应信息。

    DLPS EXIT, wake up reason 0x200
    
  3. 系统被唤醒的同时会触发 RTC 中断,在 Debug Analyzer 工具内打印相应信息。

    RTC_Handler
    RTC_INT_TICK
    
  4. 退出中断处理函数后,系统会重新进入 DLPS 状态,循环往复。

代码介绍

该章节分为以下几个部分:

  1. 源码路径

  2. 初始化函数将在 初始化 章节介绍。

  3. 初始化后的功能实现将在 功能实现 章节介绍。

源码路径

  • 工程路径: sdk\board\evb\io_sample\RTC\Dlps

  • 源码路径: sdk\src\sample\io_sample\RTC\Dlps

该工程的工程文件代码结构如下:

└── Project: rtc_dlps
    └── secure_only_app
        └── include
            ├── app_define.h
            └── rom_uuid.h
        ├── cmsis                    includes CMSIS header files and startup files
            ├── overlay_mgr.c
            ├── system_rtl876x.c
            └── startup_rtl876x.s
        ├── lib                      includes all binary symbol files that user application is built on
            ├── rtl8752h_sdk.lib
            ├── gap_utils.lib
            └── ROM.lib
        ├── peripheral               includes all peripheral drivers and module code used by the application
            ├── rtl876x_rcc.c
            ├── rtl876x_nvic.c
            ├── rtl876x_io_dlps.c
            └── rtl876x_rtc.c
        ├── profile
        └── app                      includes the ble_peripheral user application implementation
            ├── main.c
            └── io_rtc.c

初始化

当 EVB 复位启动时,调用 main() 函数,将执行以下流程:

int main(void)
{
    extern uint32_t random_seed_value;
    srand(random_seed_value);

    board_init();
    driver_init();
    pwr_mgr_init();
    os_sched_start();

    return 0;
}

其中与外设相关的初始化流程如下:

  1. driver_init 中执行 driver_rtc_init ,该函数为 RTC 外设的初始化,包含如下流程:

    1. 复位 RTC 外设。

    2. 设置 RTC 分频系数为(3200-1),RTC 时钟频率为 10Hz。

    3. 使能 RTC 滴答中断 RTC_INT_TICK

    4. 配置并使能 RTC 的 IRQ 通道,开启 CPU 的 NVIC 中断。

    5. 执行 RTC_SystemWakeupConfig() ,使能 RTC 唤醒功能。

    6. 复位 RTC 计数值,使能 RTC 外设。

    void driver_rtc_init(void)
    {
        RTC_DeInit();
        RTC_SetPrescaler(RTC_PRESCALER_VALUE);
        RTC_SetPreCompValue(0);
    
        RTC_INTConfig(RTC_INT_TICK, ENABLE);
    
        ...
    
        /* Config RTC interrupt */
        NVIC_InitTypeDef NVIC_InitStruct;
        NVIC_InitStruct.NVIC_IRQChannel = RTC_IRQn;
        NVIC_InitStruct.NVIC_IRQChannelPriority = 2;
        NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStruct);
    
        RTC_NvCmd(ENABLE);
        RTC_SystemWakeupConfig(ENABLE);
    
        /* Start RTC */
        RTC_ResetCounter();
        RTC_Cmd(ENABLE);
    }
    
  2. 执行 pwr_mgr_init ,该函数为 DLPS 的电压模式设置,包含如下流程:

    1. 注册用户进入 DLPS 回调函数 app_enter_dlps_config ,注册用户退出 DLPS 回调函数 app_exit_dlps_config

      1. app_enter_dlps_config 内打印进入 DLPS 信息。

        void app_enter_dlps_config(void)
        {
            DBG_DIRECT("DLPS ENTER");
        }
        
      2. app_exit_dlps_config 内打印 DLPS 唤醒信息,记录唤醒次数 +1。

        void app_exit_dlps_config(void)
        {
            allow_count ++;
            DBG_DIRECT("DLPS EXIT, wake up reason 0x%x", platform_pm_get_wakeup_reason());
        }
        
    2. 注册硬件控制回调函数 DLPS_IO_EnterDlpsCbDLPS_IO_ExitDlpsCb ,进入 DLPS 会保存 CPU、PINMUX、Peripheral 等,退出 DLPS 会恢复 CPU、PINMUX、Peripheral 等。

    3. 设置电源模式为 DLPS 模式。

    void pwr_mgr_init(void)
    {
        dlps_check_cb_reg(app_dlps_check_cb);
        DLPS_IORegUserDlpsEnterCb(app_enter_dlps_config);
        DLPS_IORegUserDlpsExitCb(app_exit_dlps_config);
        DLPS_IORegister();
        lps_mode_set(PLATFORM_DLPS_PFM);
    }
    

功能实现

  1. 执行 os_sched_start() ,开启任务调度。

  2. TICK 设定时间到,唤醒 DLPS,并触发 RTC 中断,进入中断处理函数 RTC_Handler ,清除滴答中断,打印相关信息。

    void RTC_Handler(void)
    {
        DBG_DIRECT("RTC_Handler");
    
        /* RTC tick interrupt handle */
        if (RTC_GetINTStatus(RTC_INT_TICK) == SET)
        {
            DBG_DIRECT("RTC_INT_TICK");
            RTC_ClearINTPendingBit(RTC_INT_TICK);
        }
        ...
    }