Prescaler Comparator
This example achieves timing functionality using the frequency divider comparator of the RTC.
After the RTC clock source (32kHz) undergoes pre-division, the regular comparator timing can only time in integer multiples of the RTC clock cycle. (For example, if the pre-divided RTC clock cycle is 0.1s, then the RTC comparator can only support timing in integer multiples of 0.1s.) To achieve more precise timing, frequency divider comparator timing can be used.
If the desired timing is less than the RTC clock cycle, the RTC_INT_PRE_COMP
interrupt should be used for timing. The timing duration is PreCompValue * (1/32kHz).
If the desired timing is greater than the RTC clock cycle, the RTC_INT_PRE_COMP3
interrupt should be used for timing, along with RTC_COMP3
. The timing duration is RTC_COMP3_VALUE * (RTC_Clock) + PreCompValue * (1/32kHz).
Requirements
The sample supports the following development kits:
Hardware Platforms |
Board Name |
---|---|
RTL8752H HDK |
RTL8752H EVB |
For more requirements, please refer to Quick Start.
Configurations
The macros that can be configured in this example are as follows:
RTC_PRECOMP3_INT
: Configuring this macro allows for selecting the RTC pre-divider comparator mode:
1
: indicates using theRTC_INT_PRE_COMP3
interrupt for timing, meaning the timing duration exceeds the RTC clock cycle.0
: indicates using theRTC_INT_PRE_COMP
interrupt for timing, meaning the timing duration is less than the RTC clock cycle.
Building and Downloading
This sample can be found in the SDK folder:
Project file: board\evb\io_sample\RTC\Pre_comp3\mdk
Project file: board\evb\io_sample\RTC\Pre_comp3\gcc
Please follow these steps to build and run the example:
Open sample project file.
To build the target, follow the steps listed on the Generating App Image in Quick Start.
After a successful compilation, the app bin
app_MP_xxx.bin
will be generated in the directorymdk\bin
orgcc\bin
.To download app bin into EVB board, follow the steps listed on the MP Tool Download in Quick Start.
Press reset button on EVB board and it will start running.
Experimental Verification
If the macro
RTC_PRECOMP3_INT
is enabled, the RTC timer period is 1.1 seconds. An RTC interrupt is triggered every 1.1 seconds, and the corresponding information is printed in the interrupt function.RTC_Handler RTC_INT_PRE_COMP3
If the macro
RTC_PRECOMP3_INT
is not enabled, the RTC timer period is 0.1 seconds. An RTC interrupt is triggered every 0.1 seconds, and the corresponding information is printed in the interrupt function.RTC_Handler RTC_INT_PRE_COMP
Code Overview
This chapter will be introduced according to the following several parts:
Peripheral initialization will be introduced in chapter Initialization.
Functional implementation after initialization will be introduced in chapter Function Implementation.
Source Code Directory
Project directory:
sdk\board\evb\io_sample\RTC\Pre_comp3
Source code directory:
sdk\src\sample\io_sample\RTC\Pre_comp3
Source files are currently categorized into several groups as below.
└── Project: rtc_pre_comp3
└── 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_rtc.c
├── profile
└── app includes the ble_peripheral user application implementation
└── main.c
Initialization
When the EVB reset, the “main” function is executed. In rtc_demo
, it includes the initialization of the RTC peripheral.
int main(void)
{
extern uint32_t random_seed_value;
srand(random_seed_value);
__enable_irq();
rtc_demo();
while (1)
{
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
}
}
void rtc_demo(void)
{
/* Initialize RTC peripheral */
driver_rtc_init();
}
driver_rtc_init
is the initialization of the RTC peripheral, including the following process:
Reset the RTC peripheral.
If macro
RTC_PRECOMP3_INT
is enabled:
Set the RTC prescaler value to (3200-1), with an RTC clock frequency of 10Hz.
Set the prescaler comparison value to 320, which means the prescaler comparator time is 0.1s.
Set the comparison value of the
RTC_COMP3
comparator to 10, which means the comparator time is 1s, with a total timer time of 1.1s.Configure the prescaler comparator 3 count interrupt
RTC_INT_PRE_COMP3
.If macro
RTC_PRECOMP3_INT
is not enabled:
Set the RTC prescaler value to (3200-1), with an RTC clock frequency of 10Hz.
Set the prescaler comparison value to 320, which means the prescaler comparator time is 0.1s.
Set the prescaler comparator interrupt
RTC_INT_PRE_COMP
.Configure and enable the RTC IRQ channel. Enable interrupt signal to CPU NVIC.
Reset the RTC counter and enable the RTC timer.
void driver_rtc_init(void) { RTC_DeInit(); #if (RTC_PRECOMP3_INT) RTC_SetPrescaler(RTC_PRESCALER_VALUE); RTC_SetPreCompValue(RTC_PRECOMP_VALUE); RTC_SetCompValue(RTC_COMP3, RTC_COMP3_VALUE); RTC_INTConfig(RTC_INT_PRE_COMP3, ENABLE); #else RTC_SetPrescaler(RTC_PRESCALER_VALUE); RTC_SetPreCompValue(RTC_PRECOMP_VALUE); RTC_INTConfig(RTC_INT_PRE_COMP, ENABLE); #endif /* Config RTC interrupt */ NVIC_InitTypeDef NVIC_InitStruct; NVIC_InitStruct.NVIC_IRQChannel = RTC_IRQn; NVIC_InitStruct.NVIC_IRQChannelPriority = 3; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); RTC_NvCmd(ENABLE); /* Start RTC */ RTC_ResetCounter(); RTC_Cmd(ENABLE); }
Functional Implementation
RTC time is up, triggering RTC interrupt and entering the interrupt handler function RTC_Handler
.
If the macro
RTC_PRECOMP3_INT
is enabled, the interrupt occurs at 1.1s. In the interrupt function, read the counter value, reset the prescaler counter, set the comparison value again, and clear the interrupt flag.If the macro
RTC_PRECOMP3_INT
is not enabled, the interrupt occurs at 0.1s. In the interrupt function, reset the prescaler counter and clear the interrupt flag.void RTC_Handler(void) { DBG_DIRECT("RTC_Handler"); #if (RTC_PRECOMP3_INT) if (RTC_GetINTStatus(RTC_INT_PRE_COMP3) == SET) { DBG_DIRECT("RTC_INT_PRE_COMP3"); uint32_t counter = RTC_GetCounter(); RTC_ResetPrescalerCounter(); RTC_SetCompValue(RTC_COMP3, counter + RTC_COMP3_VALUE); RTC_ClearINTPendingBit(RTC_INT_PRE_COMP3); } #else if (RTC_GetINTStatus(RTC_INT_PRE_COMP) == SET) { DBG_DIRECT("RTC_INT_PRE_COMP"); RTC_ResetPrescalerCounter(); RTC_ClearINTPendingBit(RTC_INT_PRE_COMP); } #endif }