mcu_ab568x/app/platform/bsp/bsp_sys.c
2025-05-30 18:03:10 +08:00

724 lines
19 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "include.h"
#include "app_variable.h"
#ifdef TJD_COMPASS_INCLUDE_MMC5603
#include "MMC5603.h"
#endif/*TJD_COMPASS_INCLUDE_MMC5603*/
#include "watch.h"
xcfg_cb_t xcfg_cb;
sys_cb_t sys_cb AT(.buf.bsp.sys_cb);
volatile int micl2gnd_flag;
volatile u32 ticks_50ms;
uint8_t cfg_spiflash_speed_up_en = SPIFLASH_SPEED_UP_EN; //SPI FLASH提速。部份FLASH不支持提速
extern u32 __max_flash_size, __bank_size;
extern u32 __comm_start, __comm_end, __comm_size, __sram_size;
extern u32 __bss_start, __bss_end, __bss_size;
#if SECURITY_PAY_EN
extern u32 __alipay_start, __alipay_end, __alipay_size;
#endif
void sd_detect(void);
void tbox_uart_isr(void);
#if USER_KEY_QDEC_EN
void bsp_qdec_process(void);
#endif
static u8 heap_func[HEAP_FUNC_SIZE] AT(.heap.func);
#if PWRKEY_2_HW_PWRON
//软开机模拟硬开关松开PWRKEY就关机。
AT(.com_text.detect)
void pwrkey_2_hw_pwroff_detect(void)
{
static int off_cnt = 0;
if (!PWRKEY_2_HW_PWRON) {
return;
}
if (IS_PWRKEY_PRESS()) {
off_cnt = 0;
} else {
if (off_cnt < 10) {
off_cnt++;
} else if (off_cnt == 10) {
//pwrkey已松开需要关机
off_cnt = 20;
sys_cb.pwrdwn_hw_flag = 1;
sys_cb.poweron_flag = 0;
}
}
}
#endif // PWRKEY_2_HW_PWRON
extern u16 dnr_voice_maxpow(void);
extern bool dac_sclk_is_enable(void);
AT(.bcom_text.dac)
uint16_t max_pow_up(void)
{
if(sys_cb.incall_flag & INCALL_FLAG_SCO)
return 0x10;
return 0x18;
}
AT(.bcom_text.dac)
uint16_t max_pow_down(void)
{
if(sys_cb.incall_flag & INCALL_FLAG_SCO)
return 0x02;
return 0x10;
}
AT(.bcom_text.dac)
void dac_dnr_ex_process(void)
{
static u8 voice_power_count = 0, silence_pow_cont = 0;
static u8 loud_is_open = 0xff;
u16 max_pow;
if (!dac_sclk_is_enable()) {
return;
}
max_pow = dnr_voice_maxpow();
if(max_pow > max_pow_up()){
voice_power_count++;
silence_pow_cont = 0;
if(voice_power_count >= 2){
voice_power_count = 2;
if(loud_is_open != 0){
loud_is_open = 0;
loudspeaker_unmute();
}
}
}else if(max_pow < max_pow_down()){
silence_pow_cont++;
voice_power_count = 0;
if(silence_pow_cont >= 10){
silence_pow_cont = 10;
if(loud_is_open != 1){
loud_is_open = 1;
loudspeaker_mute();
}
}
}
}
//timer tick interrupt(1ms)
AT(.com_text.timer)
void usr_tmr1ms_isr(void)
{
#if USER_KEY_QDEC_EN
bsp_qdec_process();
#endif
#if LED_DISP_EN
port_2led_scan();
#endif // LED_DISP_EN
/* 1ms tick stopwatch timer */
sys_cb.timer_tick++;
sys_cb.stopwatch_tick++;
bsp_saradc_tmr1ms_process();
plugin_tmr1ms_isr();
}
//timer tick interrupt(5ms)
AT(.com_text.timer)
void usr_tmr5ms_isr(void)
{
tmr5ms_cnt++;
//5ms timer process
dac_fade_process();
bsp_key_scan();
#if PWRKEY_2_HW_PWRON
pwrkey_2_hw_pwroff_detect();
#endif
plugin_tmr5ms_isr();
//20ms timer process
if ((tmr5ms_cnt % 4) == 0) {
dac_dnr_ex_process();
#if DAC_DNR_EN
dac_dnr_process();
#endif // DAC_DNR_EN
}
//50ms timer process
if ((tmr5ms_cnt % 10) == 0) {
co_timer_pro(2);
ticks_50ms++;
#if LED_DISP_EN
led_scan();
#endif
}
//100ms timer process
if ((tmr5ms_cnt % 20) == 0) {
lowpwr_tout_ticks();
}
//500ms timer process
if ((tmr5ms_cnt % 100) == 0) {
msg_enqueue(MSG_SYS_500MS);
sys_cb.cm_times++;
}
//1s timer process
if ((tmr5ms_cnt % 200) == 0) {
msg_enqueue(MSG_SYS_1S);
tmr5ms_cnt = 0;
sys_cb.lpwr_warning_cnt++;
if (sys_cb.lpwr_cnt > 0) {
// printf("sys_cb.lpwr_cnt%d\n", sys_cb.lpwr_cnt);
sys_cb.lpwr_cnt++;
}
}
}
AT(.com_text.bsp.sys)
void bsp_loudspeaker_mute(void)
{
LOUDSPEAKER_MUTE();
sys_cb.loudspeaker_mute = 1;
}
AT(.com_text.bsp.sys)
void bsp_loudspeaker_unmute(void)
{
sys_cb.loudspeaker_mute = 0;
LOUDSPEAKER_UNMUTE();
}
AT(.text.bsp.sys)
void bsp_sys_mute(void)
{
if (!sys_cb.mute) {
sys_cb.mute = 1;
dac_fade_out();
bsp_loudspeaker_mute();
#if DAC_DNR_EN
dac_dnr_set_sta(0);
#endif
}
}
AT(.text.bsp.sys)
void bsp_sys_unmute(void)
{
if (sys_cb.mute) {
sys_cb.mute = 0;
bsp_loudspeaker_unmute();
dac_fade_in();
#if DAC_DNR_EN
dac_dnr_set_sta(sys_cb.dnr_sta);
#endif
}
}
AT(.text.bsp.sys)
void bsp_clr_mute_sta(void)
{
if (sys_cb.mute) {
sys_cb.mute = 0;
#if DAC_DNR_EN
dac_dnr_set_sta(sys_cb.dnr_sta);
#endif
}
}
AT(.com_text.bsp.sys)
bool bsp_get_mute_sta(void)
{
if (get_mp3_res_sta()) {
return 0;
}
return sys_cb.mute;
}
////PWRKEY 引脚通过开关80K上拉/10K下拉, 来实现输出高低电平, 注意高电平为1.8V
//AT(.com_text.bsp.sys)
//void powerkey_out_set(bool high) //里面调用到的函数都在公共区.
//{
// if (high) {
// RTCCON1 &= ~(BIT(1)| BIT(2) | BIT(3)) ; //bit1: 10K PD DISABLE //bit2,bit3 = 00, PU IS 80K
// RTCCON1 |= BIT(4) ; //PU ENABLE,
// } else {
// RTCCON1 &= ~BIT(4) ; //PU DISABLE
// RTCCON1 |= BIT(1) ; //10K PD ENABLE
// if (!(RTCCON11 & BIT(4))){ //PD enable protect bit.
// RTCCON11 |= BIT(4);
// }
// }
//}
AT(.text.bsp.sys.init)
bool rtc_init(void)
{
u32 temp;
sys_cb.rtc_first_pwron = 0;
// printf("RTCCON0: %x, RTCCNT: %x\n", RTCCON0, RTCCNT);
temp = RTCCON0;
temp |= BIT(9) | BIT(8); //rtc clk sel x26m div
temp &= ~BIT(6); //enable clk32k_rtc
temp &= ~BIT(2); //disable osc_32k out
RTCCON0 = temp;
RTCCON2 = 16249; //26m / 16 / 100 - 1
if (temp & BIT(7)) {
temp &= ~BIT(7); //clear first poweron flag
RTCCON0 = temp;
sys_cb.rtc_first_pwron = 1;
rtc_clock_init();
// printf("rtc 1st pwrup\n");
return false;
}
return true;
}
//UART0打印信息输出GPIO选择UART0默认G1(PA7)
void uart0_mapping_sel(void)
{
//等待uart0发送完成
if(UART0CON & BIT(0)) {
while (!(UART0CON & BIT(8)));
}
GPIOBPU &= ~(BIT(2) | BIT(3) | BIT(4));
FUNCMCON0 = (0xf << 12) | (0xf << 8); //clear uart0 mapping
#if (UART0_PRINTF_SEL == PRINTF_PB3)
GPIOBDE |= BIT(3);
GPIOBPU |= BIT(3);
GPIOBDIR |= BIT(3);
GPIOBFEN |= BIT(3);
FUNCMCON0 = URX0MAP_TX | UTX0MAP_PB3; //RX0 Map To TX0, TX0 Map to G1
#elif (UART0_PRINTF_SEL == PRINTF_PA1)
GPIOBDE |= BIT(1);
GPIOAPU |= BIT(1);
GPIOADIR |= BIT(1);
GPIOAFEN |= BIT(1);
GPIOADRV |= BIT(1);
FUNCMCON0 = URX0MAP_TX | UTX0MAP_PA1; //RX0 Map To TX0, TX0 Map to G2
#elif (UART0_PRINTF_SEL == PRINTF_PA3)
GPIOBDE |= BIT(3);
GPIOAPU |= BIT(3);
GPIOADIR |= BIT(3);
GPIOAFEN |= BIT(3);
GPIOADRV |= BIT(3);
FUNCMCON0 = URX0MAP_TX | UTX0MAP_PA3; //RX0 Map To TX0, TX0 Map to G3
#elif (UART0_PRINTF_SEL == PRINTF_PE3)
GPIOEDE |= BIT(3);
GPIOEPU |= BIT(3);
GPIOEDIR |= BIT(3);
GPIOEFEN |= BIT(3);
FUNCMCON0 = URX0MAP_TX | UTX0MAP_PE3; //RX0 Map To TX0, TX0 Map to G4
#elif (UART0_PRINTF_SEL == PRINTF_PE5)
GPIOEDE |= BIT(5);
GPIOEPU |= BIT(5);
GPIOEDIR |= BIT(5);
GPIOEFEN |= BIT(5);
FUNCMCON0 = URX0MAP_TX | UTX0MAP_PE5; //RX0 Map To TX0, TX0 Map to G5
#elif (UART0_PRINTF_SEL == PRINTF_PE7)
GPIOEDE |= BIT(7);
GPIOEPU |= BIT(7);
GPIOEDIR |= BIT(7);
GPIOEFEN |= BIT(7);
FUNCMCON0 = URX0MAP_TX | UTX0MAP_PE7; //RX0 Map To TX0, TX0 Map to G6
#elif (UART0_PRINTF_SEL == PRINTF_PF5)
GPIOFDE |= BIT(5);
GPIOFPU |= BIT(5);
GPIOFDIR |= BIT(5);
GPIOFFEN |= BIT(5);
FUNCMCON0 = URX0MAP_TX | UTX0MAP_PF5; //RX0 Map To TX0, TX0 Map to G7
#elif (UART0_PRINTF_SEL == PRINTF_VUSB)
FUNCMCON0 = URX0MAP_TX | UTX0MAP_VUSB; //RX0 Map To TX0, TX0 Map to G8
#endif
}
AT(.rodata.vol)
const u8 maxvol_tbl[2] = {16, 32};
//开user timer前初始化的内容
AT(.text.bsp.sys.init)
static void bsp_var_init(void)
{
memset(&sys_cb, 0, sizeof(sys_cb));
func_heap_init(heap_func, HEAP_FUNC_SIZE);
sys_cb.loudspeaker_mute = 1;
sys_cb.ms_ticks = tick_get();
xcfg_cb.vol_max = maxvol_tbl[xcfg_cb.vol_max];
sys_cb.hfp2sys_mul = (xcfg_cb.vol_max + 2) / 16;
if (SYS_INIT_VOLUME > xcfg_cb.vol_max) {
SYS_INIT_VOLUME = xcfg_cb.vol_max;
}
if (WARNING_VOLUME > xcfg_cb.vol_max) {
WARNING_VOLUME = xcfg_cb.vol_max;
}
#if (WORK_MODE == MODE_BQB_RF)
xcfg_cb.sys_sleep_time = 0;
#endif
sys_cb.flag_pwroff = false;
SysVariable.sleep_time= -1L;
SysVariable.pwroff_time = -1L;
SysVariable.guioff_delay = SysVariable.sleep_time;
// if (xcfg_cb.sys_sleep_time != 0) {
// SysVariable.sleep_time= (u32)xcfg_cb.sys_sleep_time * 10; //100ms为单位
// }
// if (xcfg_cb.sys_off_time != 0) {
// SysVariable.pwroff_time = (u32)xcfg_cb.sys_off_time * 10; //100ms为单位
// }
SysVariable.sleep_delay = -1L;
// SysVariable.pwroff_delay = -1L;
sys_cb.sleep_en = 0;
sys_cb.lpwr_warning_times = LPWR_WARING_TIMES;
if ((!xcfg_cb.ft_osc_cap_en) || (xcfg_cb.osci_cap == 0 && xcfg_cb.osco_cap == 0)) { //没有过产测时使用自定义OSC电容
xcfg_cb.osci_cap = xcfg_cb.uosci_cap;
xcfg_cb.osco_cap = xcfg_cb.uosco_cap;
}
port_var_init();
key_var_init();
plugin_var_init();
msg_queue_init();
saradc_var_init();
sdadc_var_init();
dac_cb_init((DAC_CH_SEL & 0x0f) | ((u8)DAC_LDOH_SEL << 4) | (0x100 * DAC_FAST_SETUP_EN) | (0x200 * DACVDD_BYPASS_EN));
}
//获取系统控制位
u8 bsp_sys_get_ctlbit(uint n)
{
if (n >= SYS_CTL_TOTAL_BITS) {
halt(HALT_BSP_SYS_CTLBITS);
}
int by = n / 8;
int bi = n % 8;
return ((sys_cb.ctl_bits[by] >> bi) & 1);
}
//设置系统控制位
void bsp_sys_set_ctlbit(uint n, u8 v)
{
if (n >= SYS_CTL_TOTAL_BITS) {
halt(HALT_BSP_SYS_CTLBITS);
}
int by = n / 8;
int bi = n % 8;
sys_cb.ctl_bits[by] = (sys_cb.ctl_bits[by] & ~BIT(bi)) | (v << bi);
}
//反转系统控制位
void bsp_sys_reverse_ctlbit(uint n)
{
if (n >= SYS_CTL_TOTAL_BITS) {
halt(HALT_BSP_SYS_CTLBITS);
}
int by = n / 8;
int bi = n % 8;
sys_cb.ctl_bits[by] ^= BIT(bi);
}
AT(.text.bsp.sys.init)
static void bsp_io_init(void)
{
GPIOADE = BIT(7); //UART
GPIOBDE = 0;
GPIOEDE = 0;
GPIOFDE = 0;
GPIOGDE = 0x3F; //MCP FLASH
uart0_mapping_sel(); //调试UART IO选择或关闭
LOUDSPEAKER_MUTE_INIT();
AMPLIFIER_SEL_INIT();
}
void bsp_get_xosc_xcfg(u8 *osci_cap, u8 *osco_cap, u8 *both_cap)
{
*osci_cap = xcfg_cb.osci_cap;
*osco_cap = xcfg_cb.osco_cap;
*both_cap = xcfg_cb.osc_both_cap;
}
AT(.text.bsp.sys.init)
void bsp_update_init(void)
{
/// config
memset(&xcfg_cb, 0, sizeof(xcfg_cb));
if (!xcfg_init(&xcfg_cb, sizeof(xcfg_cb))) { //获取配置参数
// printf("xcfg init error\n");
}
// printf("TBOX OTA Update Finish!\n");
}
/*
AT(.com_rodata.isr)
const char str_t3[] = "T3 ";
AT(.com_text.isr) FIQ
void timer3_isr(void)
{
if (TMR3CON & BIT(16)) {
TMR3CPND = BIT(16); //Clear Pending
}
printk(str_t3);
}
void timer3_init(void)
{
TMR3CON = BIT(7); //Timer overflow interrupt enable
TMR3CNT = 0;
TMR3PR = 1000000 / 2 - 1; //500ms, select xosc26_div 1M clk
TMR3CON |= BIT(2) | BIT(0); //Timer works in Counter Mode
sys_irq_init(IRQ_TMR3_VECTOR, 1, timer3_isr);
}
*/
void rtc_printf(void)
{
tm_t rtc_tm = time_to_tm(RTCCNT); //更新时间结构体
// printf("time: %d.%02d.%02d %02d:%02d:%02d\n", (rtc_tm.year+0), rtc_tm.mon, rtc_tm.day,rtc_tm.hour, rtc_tm.min, rtc_tm.sec);
}
void rtc_pwd_calibration(void)
{
param_init(sys_cb.rtc_first_pwron);
u32 rtccon9 = RTCCON9;
if((rtccon9 & 1) == 1){ //1000s起来一次校准rc rtc
RTCCON9 = 0xfff; //Clr pending
if (cm_read8(PARAM_RTC_CAL_VALID) == 1) {
sniff_rc_init();
rtc_calibration_read(PARAM_RTC_CAL_ADDR);
rtc_sleep_process();
rtc_calibration_write(PARAM_RTC_CAL_ADDR);
cm_write8(PARAM_RTC_CAL_VALID, 1);
cm_sync();
rtc_printf();
}
sfunc_pwrdown(1);
return;
}
//RTCCON9 = 0xfff; //Clr pending
}
void print_comm_info(void)
{
if (RTCCON9 & 1) {
return;
}
printf("-------------------flash info----------------------\n");
printf("flash total = %d KB, used = %d KB, remain = %d KB\n", (u32)&__max_flash_size/1024, (u32)&__bank_size/1024, ((u32)&__max_flash_size - (u32)&__bank_size)/1024);
printf("--------------------------------------------------\n");
printf("-------------------sram info----------------------\n");
printf("sram total = 0x%X, used = 0x%X, remain = 0x%X\n", (u32)&__sram_size, (u32)&__comm_size+(u32)&__bss_size, (u32)&__sram_size - (u32)&__comm_size-(u32)&__bss_size);
printf("comm: 0x%X ~ 0x%X size: 0x%X\n", (u32)&__comm_start, (u32)&__comm_end, (u32)&__comm_size);
printf("bss : 0x%X ~ 0x%X size: 0x%X\n", (u32)&__bss_start, (u32)&__bss_end, (u32)&__bss_size);
#if SECURITY_PAY_EN
printf("pay : 0x%X ~ 0x%X size: 0x%X\n", (u32)&__alipay_start, (u32)&__alipay_end, (u32)&__alipay_size);
#endif
printf("--------------------------------------------------\n");
}
/**
* @author: Ronaldolinzequan
*
* @explain: 该函数放置于(xcfg_init)之后,用于烧录管理配置工具检索
* 将一些重要易修改参数值赋值于xcfg_cb成员变量
* 保证OTA后在不擦除原厂CM区的情况下对xcfg_cb进行及时修改。
*
* 如须增加其余参数在(watch_set_make.py)脚本增加对应KEY值
* 编译后会自动获取最新数据并生成对应参数宏
*/
AT(.text.bsp.sys.init)
static void xcfg_user_data_init(void)
{
/* 充电截止电流 */
xcfg_cb.charge_stop_curr = USER_CHARGE_STOP_CURR;
/* 恒流充电电流 */
xcfg_cb.charge_constant_curr = USER_CHARGE_CONSTANT_CURR;
/* 涓流充电电流 */
xcfg_cb.charge_trickle_curr = USER_CHARGE_TRICKLE_CURR;
/* BT 蓝牙名 */
memset(xcfg_cb.bt_name, 0, sizeof(xcfg_cb.bt_name));
memcpy(xcfg_cb.bt_name, USER_BT_NAME, sizeof(USER_BT_NAME));
/* LE 蓝牙名 */
memset(xcfg_cb.le_name, 0, sizeof(xcfg_cb.le_name));
memcpy(xcfg_cb.le_name, USER_LE_NAME, sizeof(USER_LE_NAME));
}
AT(.text.bsp.sys.init)
void bsp_sys_init(void)
{
/// config
memset(&xcfg_cb, 0, sizeof(xcfg_cb));
if (!xcfg_init(&xcfg_cb, sizeof(xcfg_cb))) { //获取配置参数
// printf("xcfg init error\n");
}
xcfg_user_data_init();
print_comm_info();
// io init
bsp_io_init();
// var init
bsp_var_init();
#if USE_APP_TYPE
app_platform_init();
#endif
rtc_pwd_calibration();
// power init
pmu_init(BUCK_MODE_EN*xcfg_cb.buck_mode_en);
// clock init
adpll_init(DAC_OUT_SPR);
sys_clk_set(SYS_CLK_SEL);
// peripheral init
rtc_init();
param_init(sys_cb.rtc_first_pwron);
//晶振配置
xosc_init();
xosc_driver_init();
plugin_init();
if (POWKEY_10S_RESET) {
RTCCON10 = BIT(10); //clear 10s pending
RTCCON12 &= ~0x0f; //10S Reset Enable
} else {
RTCCON12 = (RTCCON12 & ~0xf) | 0x0a; //10S Reset Disable
}
#if CHARGE_EN
if (xcfg_cb.charge_en) {
bsp_charge_init();
}
#endif // CHARGE_EN
key_init();
/// enable user timer for display & dac
sys_set_tmr_enable(1, 1);
bt_init();
#if BT_BACKSTAGE_EN
func_bt_init();
#endif
dac_init();
// printf("SysVariable.vol = %d\n",SysVariable.vol);
bsp_change_volume(SysVariable.vol);
#if WARNING_POWER_ON
mp3_res_play(RES_BUF_POWERON_MP3, RES_LEN_POWERON_MP3);
#endif // WARNING_POWER_ON
#if BT_BACKSTAGE_MUSIC_EN
bt_audio_enable();
#if DAC_DNR_EN
dac_dnr_set_sta(1);
sys_cb.dnr_sta = 1;
#endif
#endif
#if EQ_DBG_IN_UART || EQ_DBG_IN_SPP
eq_dbg_init();
#endif // EQ_DBG_IN_UART
mic_bias_trim_w4_done();
bsp_i2c_init();
/* GUI相关初始化 */
gui_init();
/* 需放在IIC初始化之后未使用外设时注意关闭 */
bsp_sensor_pe2_pwr_pg_on();
/* 步数传感器初始化 */
bsp_sensor_step_init();
#if SENSOR_STEP_SEL != SENSOR_STEP_NULL
bsp_sensor_step_set_pedo(SysVariable.curSportRecord.pedo); // 设置计步值
#endif
/* 心率传感器初始化 */
bsp_sensor_hr_init();
bsp_sensor_hr_stop();
#ifdef TJD_COMPASS_INCLUDE_MMC5603
MMC5603_chip_init();
#endif /*TJD_COMPASS_INCLUDE_MMC5603*/
bsp_vbat_percent_init(); //放最后电压稍微稳定点
SysVariable.bt_state_set = false;
//bsp_internal_sensor_init();
#ifdef TJD_SETTING_AUDIO_SWITCH
if(SysVariable.bt_a2dp_profile_state)
bt_a2dp_profile_en();
else
bt_a2dp_profile_dis();
if(SysVariable.bt_hfp_profile_state)
bt_hfp_profile_en();
else
bt_hfp_profile_dis();
#endif
}
AT(.com_rodata)
const char func_msg_enqueue[] = "my_msg_enqueue[%d,%d,%d,%d]\n";
AT(.com_text.ctp)
void my_msg_enqueue(u16 msg)
{
// printf(func_msg_enqueue, SysVariable.password_cnt, SysVariable.password_need, SysVariable.password_allow_push, func_cb.sta);
if (!sys_cb.password_show &&
SysVariable.password_cnt == 4 &&
SysVariable.password_need &&
func_cb.sta != FUN_POWER_ON_LOGO &&
func_cb.sta != FUNC_PASSWORD_SUB_DISP)
{
sys_cb.password_show = true;
return;
}
msg_enqueue(msg);
}
// #define XO26MCON SFR_RW (SFR3_BASE + 0x29*4)
void xosc_driver_init(void)
{
// printf("=====xosc_driver_init\n");
XO26MCON = (XO26MCON & ~(31<<0)) | ((20)<<0);
}