RTC - DLPS

This example demonstrates the use of RTC to wake up from DLPS at scheduled intervals.

When the system is in the IDLE state, it will automatically enter the DLPS state. When the RTC timer ends, it will wake the system from DLPS and simultaneously trigger an RTC interrupt.

The system can be awakened by RTC’s tick interrupt, overflow interrupt, 4-channel comparator interrupt, and frequency divider comparator interrupt.

This example illustrates the wake-up process using the tick timer.

Requirements

The sample supports the following development kits:

Development Kits

Hardware Platforms

Board Name

RTL8752H HDK

RTL8752H EVB

For more requirements, please refer to Quick Start.

Building and Downloading

This sample can be found in the SDK folder:

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

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

Please follow these steps to build and run the example:

  1. Open sample project file.

  2. To build the target, follow the steps listed on the Generating App Image in Quick Start.

  3. After a successful compilation, the app bin app_MP_xxx.bin will be generated in the directory mdk\bin or gcc\bin.

  4. To download app bin into EVB board, follow the steps listed on the MP Tool Download in Quick Start.

  5. Press reset button on EVB board and it will start running.

Experimental Verification

  1. When the EVB is reset, the system enters the DLPS state. The corresponding information is printed in the Debug Analyzer.

    DLPS ENTER
    
  2. When the Tick timer ends (1s), the system is awakened and exits the DLPS state. Print the corresponding information in the Debug Analyzer.

    DLPS EXIT, wake up reason 0x200
    
  3. The system will trigger an RTC interrupt upon waking up, printing relevant information in the Debug Analyzer.

    RTC_Handler
    RTC_INT_TICK
    
  4. After exiting the interrupt handler, the system will re-enter the DLPS state and repeat the cycle.

Code Overview

This chapter will be introduced according to the following several parts:

  1. Source Code Directory.

  2. Peripheral initialization will be introduced in chapter Initialization.

  3. Functional implementation after initialization will be introduced in chapter Function Implementation.

Source Code Directory

  • Project directory: sdk\board\evb\io_sample\RTC\Dlps

  • Source code directory: sdk\src\sample\io_sample\RTC\Dlps

Source files are currently categorized into several groups as below.

└── 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

Initialization

When the EVB reset is initiated, the main() function will be called, executing the following process:

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;
}

The initialization process related to peripherals is as follows:

  1. Execute driver_rtc_init in driver_init, which initializes the RTC peripheral and includes the following steps:

    1. Reset the RTC peripheral.

    2. Set the RTC prescaler to (3200-1), with an RTC clock frequency of 10Hz.

    3. Enable the RTC tick interrupt RTC_INT_TICK.

    4. Configure and enable the RTC IRQ channel. Enable interrupt signal to CPU NVIC.

    5. Execute RTC_SystemWakeupConfig(), enable the RTC wakeup function.

    6. Reset the RTC counter value, enable the RTC peripheral.

    void driver_lpc_init(void)
    {
        DBG_DIRECT("driver_lpc_init");
        LPC_DeInit();
        LPC_InitTypeDef LPC_InitStruct;
        LPC_StructInit(&LPC_InitStruct);
    
        LPC_InitStruct.LPC_Channel   = LPC_CAPTURE_CHANNEL;
        LPC_InitStruct.LPC_Edge      = LPC_VOLTAGE_DETECT_EDGE;
        LPC_InitStruct.LPC_Threshold = LPC_VOLTAGE_DETECT_THRESHOLD;
        LPC_Init(&LPC_InitStruct);
        LPC_INTConfig(LPC_INT_LPCOMP_VOL, ENABLE);
    
        LPC_WKCmd(ENABLE);
        RTC_SystemWakeupConfig(ENABLE);
        LPC_Cmd(ENABLE);
    
        extern void nvic_lpc_init(void);
        nvic_lpc_init();
    }
    
    void nvic_lpc_init(void)
    {
        /* Config LPC interrupt */
        NVIC_InitTypeDef NVIC_InitStruct;
        NVIC_InitStruct.NVIC_IRQChannel = LPCOMP_IRQn;
        NVIC_InitStruct.NVIC_IRQChannelPriority = 3;
        NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStruct);
    
        LPC_INTCmd(ENABLE);
    }
    
  2. Execute pwr_mgr_init, this function sets the voltage mode for DLPS, including the following processes:

    1. Register the user-entering DLPS callback function app_enter_dlps_config, and register the user-exiting DLPS callback function app_exit_dlps_config.

      1. Enable the LPC voltage comparison interrupt LPC_INT_LPCOMP_VOL in app_enter_dlps_config.

        void app_enter_dlps_config(void)
        {
            DBG_DIRECT("DLPS ENTER");
        }
        
      2. In app_exit_dlps_config, print DLPS wake-up information and record the count +1.

        void app_exit_dlps_config(void)
        {
            allow_count ++;
            DBG_DIRECT("DLPS EXIT, wake up reason 0x%x", platform_pm_get_wakeup_reason());
        }
        
    2. Register the hardware control callback functions DLPS_IO_EnterDlpsCb and DLPS_IO_ExitDlpsCb. Entering DLPS will save CPU, PINMUX, Peripheral, etc., and exiting DLPS will restore CPU, PINMUX, Peripheral, etc.

    3. Set the power mode to DLPS mode.

    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);
    }
    

Functional Implementation

  1. Execute os_sched_start() to start task scheduling.

  2. When the TICK time arrives, wake up DLPS and trigger the RTC interrupt, enter the interrupt handler function RTC_Handler, clear the tick interrupt, and print relevant information.

    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);
        }
        ...
    }