Files
hpw421/component/boot2/bsp/bsp_calib_rc32k.c
2026-07-03 18:08:25 +08:00

305 lines
7.4 KiB
C

#include "Includes.h"
#if 1
//#define printf(...) (0)
typedef struct
{
uint32_t AO_TIMER_VALUE:16;
uint32_t AO_TIMER_CLR:1;
uint32_t AO_TIMER_EN:1;
uint32_t FREQ_TIMER_EN:1;
uint32_t RESERVED:13;
}AO_TIMER_CTL_T;
static AO_TIMER_CTL_T* ao_timer_ctl = (AO_TIMER_CTL_T*)AO_TIMER_CTL;
/*
3fff 3044 --50K
2fff 4132 --39K
1fff 5229 --31K
0fff 6326 --25K
*/
#define MAX_LPO_RTM 0x3fff
#define MIN_LPO_RTM 0x0
#define MID_LPO_RTM 0x1fff
#define RANGE_LPO_RTM 0x400
#define GEARS_HZ 1.56
#define _32K_STAND_HZ 32000
#define CALIB_STEP_CYCLE_32K 32 //#define CALIB_STEP_CYCLE_32K 10
#define COUNT_16M 16000 //#define COUNT_16M 5000
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)
{
//config clk
__write_hw_reg32(CPR_CTLAPBCLKEN_GRCTL, 0x00020002);
__write_hw_reg32(CPR_AOCLKEN_GRCTL,0x00020002);
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);
}
#else
//////////////////////////校准三次 每次校准用的时间如下//////////////////////////
//低电压下
//*((volatile unsigned *)(0x40002400 + 0x20)) =0x44;
//*((volatile unsigned *)(0x40002400 + 0x48)) =0x01;
//@@LPO_RTM_SET:0x00002704 32 //1ms校准一次
//@@LPO_RTM_SET:0x00002709 32*5 //5ms校准一次
//@@LPO_RTM_SET:0x0000270b 320*2 //20ms校准一次
//@@LPO_RTM_SET:0x00002708 320*4 //40ms校准一次
//@@LPO_RTM_SET:0x00002706 320*6 //60ms校准一次
//@@LPO_RTM_SET:0x0000270a 320*8 //80ms校准一次
//@@LPO_RTM_SET:0x00002706 3200 //100ms校准一次
//@@LPO_RTM_SET:0x00002705 3200*2 //200ms校准一次
//@@LPO_RTM_SET:0x00002708 3200*3 //300ms校准一次
//@@LPO_RTM_SET:0x00002705 3200*4 //400ms校准一次
//@@LPO_RTM_SET:0x00002705 3200*5 //400ms校准一次
//@@LPO_RTM_SET:0x0000270a 3200*6 //600ms校准一次
//@@LPO_RTM_SET:0x00002708 3200*7 //700ms校准一次
//@@LPO_RTM_SET:0x00002708 3200*8 //800ms校准一次
//@@LPO_RTM_SET:0x00002707 3200*9 //900ms校准一次
//正常电压下:
//@@LPO_RTM_SET:0x000026db 32 //1ms校准一次
//@@LPO_RTM_SET:0x000026da 32*5 //5ms校准一次
//@@LPO_RTM_SET:0x000026dc 320*2 //20ms校准一次
//@@LPO_RTM_SET:0x000026da 320*4 //40ms校准一次
//@@LPO_RTM_SET:0x000026e0 320*6 //60ms校准一次
//@@LPO_RTM_SET:0x000026dc 320*8 //80ms校准一次
//@@LPO_RTM_SET:0x000026dc 3200 //100ms校准一次
//@@LPO_RTM_SET:0x000026dc 3200*2 //200ms校准一次
//@@LPO_RTM_SET:0x000026df 3200*3 //300ms校准一次
//@@LPO_RTM_SET:0x000026dd 3200*4 //400ms校准一次
//@@LPO_RTM_SET:0x000026db 3200*5 //400ms校准一次
//@@LPO_RTM_SET:0x000026db 3200*6 //600ms校准一次
//@@LPO_RTM_SET:0x000026de 3200*7 //700ms校准一次
//@@LPO_RTM_SET:0x000026dd 3200*8 //800ms校准一次
//@@LPO_RTM_SET:0x000026e0 3200*9 //900ms校准一次
//#define printf(...) (0)
typedef struct
{
uint32_t AO_TIMER_VALUE:16;
uint32_t AO_TIMER_CLR:1;
uint32_t AO_TIMER_EN:1;
uint32_t FREQ_TIMER_EN:1;
uint32_t RESERVED:13;
}AO_TIMER_CTL_T;
static AO_TIMER_CTL_T* ao_timer_ctl = (AO_TIMER_CTL_T*)AO_TIMER_CTL;
/*
3fff 3044 --50K
2fff 4132 --39K
1fff 5229 --31K
0fff 6326 --25K
*/
#define MAX_LPO_RTM 0x3fff
#define MIN_LPO_RTM 0x0
#define MID_LPO_RTM 0x1fff
#define RANGE_LPO_RTM 0x400
#define GEARS_HZ 1.56
#define _32K_STAND_HZ 32000
//#define CALIB_STEP_CYCLE_32K 32 //#define CALIB_STEP_CYCLE_32K 10
//#define COUNT_16M 16000 //#define COUNT_16M 5000
#define TMP_VAL 1
#define CALIB_STEP_CYCLE_32K 32*TMP_VAL //#define CALIB_STEP_CYCLE_32K 10
#define COUNT_16M 16000*TMP_VAL //#define COUNT_16M 5000
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);
//if(*FREQ_TIMER_VAL>=16777210) printf("***********\n");
}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)
{
//config clk
__write_hw_reg32(CPR_CTLAPBCLKEN_GRCTL, 0x00020002);
__write_hw_reg32(CPR_AOCLKEN_GRCTL,0x00020002);
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);
}
#endif
#if 0
void test_main(void)
{
printf("TEST CALIB\n");
Init_gpio();
// *((volatile unsigned *)(0x40002400 + 0x20)) =0x44;
// *((volatile unsigned *)(0x40002400 + 0x48)) =0x01;
gpio_output_high(26);
gpio_output_low(26);
//3.19ms
calib_init();
rc32k_calib(3);
gpio_output_high(26);
gpio_output_low(26);
xc_ao_timer_calib_test();
}
#endif
//cmp