Voltage Detection - DLPS

This example uses LPC for DLPS wake-up.

When the system is in IDLE state, it will automatically enter DLPS state.

When the input voltage at pin P2_4 meets the LPC voltage comparison condition, it will wake up the system from DLPS and simultaneously trigger an LPC interrupt.

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.

Wiring

Connect LPC voltage comparator pin P2_4 to the external input voltage.

Building and Downloading

This sample can be found in the SDK folder:

Project file: board\evb\io_sample\LPC\VolatgeDetection_DLPS\mdk

Project file: board\evb\io_sample\LPC\VolatgeDetection_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 resets, the system enters the DLPS state. Corresponding information is printed in the Debug Analyzer.

    DLPS ENTER
    
  2. When P2_4 detects a voltage input lower than 2000mV, the system wakes up and exits the DLPS state. The relevant information is printed in the Debug Analyzer.

    DLPS EXIT, wake up reason 0x200
    
  3. The system being awakened will trigger an LPC interrupt, and the corresponding information will be printed in the Debug Analyzer.

    LPCOMP_Handler
    LPC AON
    

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\LPC\VolatgeDetection_DLPS

  • Source code directory: sdk\src\sample\io_sample\LPC\VolatgeDetection_DLPS

Source files are currently categorized into several groups as below.

└── Project: voltage_detect_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
            └── adc.lib
        ├── peripheral               includes all peripheral drivers and module code used by the application
            ├── rtl876x_rcc.c
            ├── rtl876x_pinmux.c
            ├── rtl876x_nvic.c
            ├── rtl876x_io_dlps.c
            └── rtl876x_lpc.c
        ├── profile
        └── app                      includes the ble_peripheral user application implementation
            ├── main.c
            └── io_lpc.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. In board_init, execute board_lpc_init, which is responsible for PAD/PINMUX settings and includes the following process:

    1. Configure PAD: Set pin, SW mode, PowerOn, internal pull-none, output disabled.

    2. Configure PINMUX: Set pin to IDLE mode.

    void board_lpc_init(void)
    {
        Pad_Config(LPC_CAPTURE_PIN, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE,
                PAD_OUT_HIGH);
        Pinmux_Config(LPC_CAPTURE_PIN, IDLE_MODE);
    }
    
  2. Execute driver_lpc_init in driver_init, which initializes the LPC peripheral and includes the following steps:

    1. Set the LPC comparison channel to the P2_4 pin channel.

    2. Set the LPC voltage detection polarity to LPC_Vin_Below_Vth, which triggers LPC comparison when the voltage is below the set threshold.

    3. Set the voltage threshold to 2000mV.

    4. Enable LPC voltage detection and configure the LPC voltage comparison interrupt LPC_INT_LPCOMP_VOL.

    5. Execute LPC_WKCmd() to enable the LPC wake-up function.

    6. Execute nvic_lpc_init to configure and enable the LPC IRQ channel.

    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);
    }
    
  3. 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");
        
            LPC_INTConfig(LPC_INT_LPCOMP_VOL, ENABLE);
        }
        
      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. When P2_4 detects an input voltage lower than 2000mV, it triggers the LPC_INT_LPCOMP_VOL interrupt and enters the interrupt handler function LPCOMP_Handler.

    1. Check if the interrupt flag is LPC_FLAG_LPCOMP_AON.

    2. Disable the LPC interrupt.

    void LPCOMP_Handler(void)
    {
        DBG_DIRECT("LPCOMP_Handler");
    
        if (LPC_GetFlagStatus(LPC_FLAG_LPCOMP_AON) == SET)
        {
            DBG_DIRECT("LPC AON");
        }
    
        LPC_INTConfig(LPC_INT_LPCOMP_VOL, DISABLE);
    }