306 lines
7.2 KiB
C
306 lines
7.2 KiB
C
|
|
|
|
#include "Includes.h"
|
|
|
|
|
|
//#define printf(...) (0)
|
|
|
|
|
|
|
|
/**
|
|
* Copyright (c) 2022 - 2025, XinChip
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* Author :
|
|
*
|
|
*/
|
|
extern void Init_rtc(rtc_t *rtc)
|
|
{
|
|
uint32_t VAL;
|
|
|
|
if(rtc == (rtc_t*)0) return;
|
|
VAL = ((rtc->day)<<17) | ((rtc->hour)<<12) | ((rtc->minute)<<6) | (rtc->second);
|
|
__write_hw_reg32(CPR_CTLAPBCLKEN_GRCTL, 0x20002);
|
|
__write_hw_reg32(CPR_AOCLKEN_GRCTL, 0x20002);
|
|
|
|
__write_hw_reg32(RTC_ICR, 0x00);
|
|
__write_hw_reg32(RTC_CLR, VAL);
|
|
__write_hw_reg32(RTC_WLR, rtc->week);
|
|
|
|
__write_hw_reg32(RTC_RAW_LIMIT, 32000);//32768
|
|
__write_hw_reg32(RTC_SECOND_LIMIT, 60);
|
|
__write_hw_reg32(RTC_MINUTE_LIMIT, 60);
|
|
__write_hw_reg32(RTC_HOUR_LIMIT, 24);
|
|
|
|
VAL = 0x100;
|
|
if(rtc->interrupt != 0) {
|
|
|
|
VAL |= (rtc->interrupt);
|
|
NVIC_EnableIRQ(RTC_IRQn);
|
|
}
|
|
__write_hw_reg32(RTC_ICR, VAL); //- 使能RTC开始工作
|
|
|
|
|
|
}
|
|
/**
|
|
* Copyright (c) 2022 - 2025, XinChip
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* Author :
|
|
*
|
|
*/
|
|
extern void rtc_Current_VAL(rtc_t *rtc)
|
|
{
|
|
uint32_t VAL;
|
|
__read_hw_reg32(RTC_CCVR, VAL);
|
|
|
|
rtc->day = (VAL >> 17) & 0x7FFF;
|
|
rtc->hour = (VAL >> 12) & 0x1F;
|
|
rtc->minute = (VAL >> 6)& 0x3F;
|
|
rtc->second = VAL & 0x3F;
|
|
|
|
__read_hw_reg32(RTC_WVR, VAL);
|
|
rtc->week = VAL & 0x07;
|
|
}
|
|
/**
|
|
* Copyright (c) 2022 - 2025, XinChip
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* Author :
|
|
*
|
|
*/
|
|
extern void rtc_Alarm_Init(uint32_t no, rtc_t * rtc)
|
|
{
|
|
uint8_t TAB[3] = {RTC_INT_T1, RTC_INT_T2, RTC_INT_T3};
|
|
uint32_t VAL;
|
|
|
|
no = no - 1;
|
|
|
|
VAL = ((rtc->hour)<<12) | ((rtc->minute)<<6) | (rtc->second);
|
|
//VAL |= 1<<((rtc->week)+17);
|
|
VAL |= rtc->week_alarm;
|
|
__write_hw_reg32(RTC_CMR_X(no), VAL);
|
|
__read_hw_reg32(RTC_ICR, VAL);
|
|
VAL |= TAB[no];
|
|
__write_hw_reg32(RTC_ICR, VAL); //- 使能定时匹配中
|
|
NVIC_EnableIRQ(RTC_IRQn);//使能RTC中断
|
|
}
|
|
|
|
/**
|
|
* Copyright (c) 2022 - 2025, XinChip
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* Author :
|
|
*
|
|
*/
|
|
extern void Init_rtc_gpio(uint32_t num,uint32_t level)
|
|
{
|
|
uint32_t val;
|
|
__write_hw_reg32(CPR_CTLAPBCLKEN_GRCTL, 0x20002);
|
|
__write_hw_reg32(CPR_AOCLKEN_GRCTL, 0x20002);
|
|
|
|
__write_hw_reg32(PWRKEY_CTRL0, level);/*gpio0-31(1:low,0:high)*/
|
|
__write_hw_reg32(PWRKEY_CTRL1, num);/*gpio0-31(0:disable,1:enable)*/
|
|
__write_hw_reg32(PWRKEY_CTRL2, 0x80000000);/*bit31:enable inter,bit1:inter raw*/
|
|
|
|
NVIC_EnableIRQ(RTC_IRQn);
|
|
}
|
|
/**
|
|
* Copyright (c) 2022 - 2025, XinChip
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* Author :
|
|
*
|
|
*/
|
|
extern void RTC_Handler(void)
|
|
{
|
|
/*rtc pclk must be opened here after deep sleep wakeup*/
|
|
__write_hw_reg32(CPR_CTLAPBCLKEN_GRCTL, 0x20002);
|
|
|
|
uint32_t stat;
|
|
/*bit0:day , bit1:hour , bit2:min , bit3:sec , bit4:t2 , bit5:t1 , bit6:t3 intr*/
|
|
__read_hw_reg32(RTC_ISR, stat);
|
|
if(stat != 0)
|
|
{
|
|
__write_hw_reg32(RTC_EOI, stat);//clear intr
|
|
if(stat&0x1)//day intr
|
|
{
|
|
printf("rtc day intr\n");
|
|
|
|
}
|
|
if(stat&0x2)//hour intr
|
|
{
|
|
printf("rtc hour intr\n");
|
|
|
|
}
|
|
if(stat&0x4)//min intr
|
|
{
|
|
printf("rtc min intr\n");
|
|
|
|
}
|
|
if(stat&0x8)//sec intr
|
|
{
|
|
printf("rtc sec intr\n");
|
|
|
|
}
|
|
if(stat&0x70)//alarm intr
|
|
{
|
|
printf("rtc alarm t2/t1/t3 intr\n");
|
|
rtc_t rtc={0};
|
|
Init_rtc(&rtc);
|
|
rtc.second=rtc.second+2;
|
|
rtc.week_alarm=0xFE0000;
|
|
rtc_Alarm_Init(1,&rtc);
|
|
}
|
|
}
|
|
/*ao_timer intr*/
|
|
__read_hw_reg32(AO_ALL_INTR, stat);
|
|
if(stat&0x20)//ao_timer intr
|
|
{
|
|
*AO_TIMER_CTL |=0x10000;
|
|
printf("ao_timer intr\n");
|
|
|
|
}
|
|
/*rtc_gpio inter*/
|
|
__read_hw_reg32(PWRKEY_CTRL2, stat);
|
|
if(stat&0x02) /*power key gpio wakeup*/
|
|
{
|
|
printf("rtc_gpio intr\n");
|
|
//__write_hw_reg32(PWRKEY_CTRL2, 0x00000000);
|
|
//__write_hw_reg32(PWRKEY_CTRL2, 0x80000000);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*************************The following is the calibration of rc32k************************************/
|
|
|
|
static AO_TIMER_CTL_T* ao_timer_ctl = (AO_TIMER_CTL_T*)AO_TIMER_CTL;
|
|
static void LPO_RTM_SET(uint16_t val)
|
|
{
|
|
*((volatile unsigned *)0x40002084)=0x1fff4000|val; //*((volatile unsigned *)0x40002084)=0x1fff4000|0x22C0; //printf("LPO_RTM:%08x\n",*((volatile unsigned *)0x40002084));
|
|
}
|
|
|
|
/**
|
|
* Copyright (c) 2022 - 2025, XinChip
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* Author :
|
|
*
|
|
*/
|
|
static uint8_t calib_step(uint32_t _cycle_32k,uint32_t *FREQ_VAL)
|
|
{
|
|
uint32_t tsd;
|
|
ao_timer_ctl->AO_TIMER_VALUE = _cycle_32k;//32 cycle == 1ms
|
|
ao_timer_ctl->AO_TIMER_EN = 0;
|
|
ao_timer_ctl->AO_TIMER_CLR = 0; //中断使用在timer 使能之前
|
|
ao_timer_ctl->FREQ_TIMER_EN = 1;
|
|
do{
|
|
__read_hw_reg32(AO_ALL_INTR, tsd);
|
|
}while((tsd&0x20)==0);
|
|
__read_hw_reg32(FREQ_TIMER_VAL, *FREQ_VAL);//
|
|
ao_timer_ctl->AO_TIMER_CLR = 1; // rtc 必须清理中断
|
|
ao_timer_ctl->FREQ_TIMER_EN = 0;
|
|
if(*FREQ_VAL==COUNT_16M) return 0;
|
|
return ((*FREQ_VAL<COUNT_16M)? 1:2);
|
|
}
|
|
|
|
|
|
/**
|
|
* Copyright (c) 2022 - 2025, XinChip
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* Describe : init calib clk
|
|
*
|
|
*/
|
|
static volatile uint32_t mid=MID_LPO_RTM;
|
|
void calib_init(void)
|
|
{
|
|
__write_hw_reg32(CPR_CTLAPBCLKEN_GRCTL, 0x20002);
|
|
__write_hw_reg32(CPR_AOCLKEN_GRCTL, 0x20002);
|
|
LPO_RTM_SET(mid);
|
|
}
|
|
/**
|
|
* Copyright (c) 2022 - 2025, XinChip
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* Describe : "linear regression" calibration
|
|
*
|
|
*/
|
|
void rc32k_calib(uint16_t cts)
|
|
{
|
|
uint32_t tsd,frac;
|
|
while(cts--)
|
|
{
|
|
__disable_irq();
|
|
calib_step(CALIB_STEP_CYCLE_32K,&tsd);
|
|
__enable_irq();
|
|
printf("FREQ_TIMER_VAL:%d\n",tsd);
|
|
|
|
frac=(uint32_t)((((float)((16.0)*CALIB_STEP_CYCLE_32K))/tsd)*1000000);
|
|
if(frac > _32K_STAND_HZ)
|
|
{
|
|
mid=mid-((uint32_t)(((float)(frac-_32K_STAND_HZ))/GEARS_HZ));
|
|
}
|
|
else if(frac < _32K_STAND_HZ)
|
|
{
|
|
mid=mid+((uint32_t)(((float)(_32K_STAND_HZ-frac))/GEARS_HZ));
|
|
}
|
|
LPO_RTM_SET(mid);
|
|
|
|
}
|
|
printf("@@LPO_RTM_SET:0x%08x\n",mid);
|
|
|
|
|
|
}
|
|
/**********************************calibration rc32k end********************************************/
|
|
|
|
void test_rtc(void)
|
|
{
|
|
/*rc32k calib*/
|
|
calib_init();
|
|
rc32k_calib(3);
|
|
#if 0
|
|
gpio_mux_ctl(1,0);gpio_fun_inter(1,0);gpio_fun_sel(1,0);gpio_direction_input(1,1);
|
|
gpio_mux_ctl(4,0);gpio_fun_inter(4,0);gpio_fun_sel(4,0);gpio_direction_input(4,0);
|
|
Init_rtc_gpio(0x00000012,0x00000010);/*1:low,0:high*/
|
|
while(1);
|
|
#endif
|
|
#if 0
|
|
rtc_t rtc={0};
|
|
Init_rtc(&rtc);
|
|
rtc.second=rtc.second+5; //设定闹钟时间5S后
|
|
rtc.week_alarm=0xFE0000; //设置闹钟星期几有效,周一到周日都有效
|
|
rtc_Alarm_Init(1,&rtc); //设置闹钟--5s后唤醒
|
|
while(1);
|
|
#endif
|
|
#if 1
|
|
rtc_t rtc={
|
|
.day = 16,
|
|
.hour = 10,
|
|
.minute= 14,
|
|
.second= 00,
|
|
.week = 5,
|
|
.interrupt = RTC_INT_SEC
|
|
};
|
|
Init_rtc(&rtc);
|
|
while(1)
|
|
{
|
|
for(int i=0;i<0x455000;i++);
|
|
rtc_Current_VAL(&rtc);
|
|
printf("%d-%d %d:%d:%d\n",rtc.day,rtc.week,rtc.hour,rtc.minute,rtc.second);
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
|