/********************************** (C) COPYRIGHT ******************************* * File Name : CH58x_SYS.c * Author : WCH * Version : V1.2 * Date : 2021/11/17 * Description : source file(ch585/ch584) ********************************************************************************* * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. * Attention: This software (modified or not) and binary are used for * microcontroller manufactured by Nanjing Qinheng Microelectronics. *******************************************************************************/ #include "CH58x_common.h" #include "bsp_uart.h" volatile MachineMode_Call_func gs_machine_mode_func; extern uint32_t _vector_base[]; /********************************************************************* * @fn SetSysClock * * @brief 配置系统运行时钟 * * @param sc - 系统时钟源选择 refer to SYS_CLKTypeDef * * @return none */ __HIGH_CODE void SetSysClock(SYS_CLKTypeDef sc) { uint16_t clk_sys_cfg; uint8_t i; uint8_t x32M_c; R32_SAFE_MODE_CTRL |= RB_XROM_312M_SEL; R8_SAFE_MODE_CTRL &= ~RB_SAFE_AUTO_EN; sys_safe_access_enable(); if(sc == RB_CLK_SYS_MOD) // 32KHz { R16_CLK_SYS_CFG |= RB_CLK_SYS_MOD; } else { if(sc & RB_OSC32M_SEL) { if(!(R8_HFCK_PWR_CTRL & RB_CLK_XT32M_PON)) { x32M_c = R8_XT32M_TUNE; R8_XT32M_TUNE |= 0x03; R8_HFCK_PWR_CTRL |= RB_CLK_XT32M_PON; clk_sys_cfg = R16_CLK_SYS_CFG; R16_CLK_SYS_CFG |= 0xC0; for(i=0; i<9; i++) { __nop(); } R16_CLK_SYS_CFG = clk_sys_cfg; R8_XT32M_TUNE = x32M_c; } } else { R8_HFCK_PWR_CTRL |= RB_CLK_RC16M_PON; } if(sc & RB_XROM_SCLK_SEL) // PLL div { R8_HFCK_PWR_CTRL |= RB_CLK_PLL_PON; if((sc&0x1F) == 0 ) { R8_FLASH_SCK = R8_FLASH_SCK|(1<<4); R8_FLASH_CFG = 0X07; } else if((sc&0x1F) < 10) { R8_FLASH_SCK = R8_FLASH_SCK & (~(1<<4)); R8_FLASH_CFG = 0X02; } else if((sc&0x1F) < 16) { R8_FLASH_SCK = R8_FLASH_SCK & (~(1<<4)); R8_FLASH_CFG = 0X03; } else { R8_FLASH_SCK = R8_FLASH_SCK|(1<<4); R8_FLASH_CFG = 0X03; } } else { if((sc&0x1F) < 8 ) { R8_FLASH_SCK = R8_FLASH_SCK & (~(1<<4)); R8_FLASH_CFG = 0X51; } else { R8_FLASH_SCK = R8_FLASH_SCK & (~(1<<4)); R8_FLASH_CFG = 0X57; } } R16_CLK_SYS_CFG = sc|0xC0; R16_CLK_SYS_CFG = sc; if(sc & RB_OSC32M_SEL) { if((!((R8_GLOB_CFG_INFO & RB_CFG_DEBUG_EN)|(R8_GLOB_CFG_INFO & RB_CFG_ROM_READ ))) && (R8_SAFE_DEBUG_CTRL & RB_DEBUG_DIS)) { R8_HFCK_PWR_CTRL &= ~RB_CLK_RC16M_PON; } } else { R8_HFCK_PWR_CTRL &= ~RB_CLK_XT32M_PON; } } R8_SAFE_MODE_CTRL |= RB_SAFE_AUTO_EN; sys_safe_access_disable(); } /********************************************************************* * @fn highcode_init * * @brief 搬运highcode代码 * * @param none * * @return none */ __attribute__((section(".highcode_init"))) void highcode_init(void) { R32_SAFE_MODE_CTRL |= RB_XROM_312M_SEL; R8_SAFE_MODE_CTRL &= ~RB_SAFE_AUTO_EN; sys_safe_access_enable(); R32_MISC_CTRL |= 5; // R8_PLL_CONFIG &= ~(1 << 5); // R8_HFCK_PWR_CTRL |= RB_CLK_RC16M_PON | RB_CLK_PLL_PON; R16_CLK_SYS_CFG = CLK_SOURCE_HSI_PLL_62_4MHz; R8_FLASH_CFG = 0X02; R8_XT32M_TUNE = (R8_XT32M_TUNE&(~0x03))|0x01; R8_SAFE_MODE_CTRL |= RB_SAFE_AUTO_EN; sys_safe_access_disable(); } /********************************************************************* * @fn MachineMode_Call_IRQ * * @brief 机械模式调用函数使用的中断 * * @param none * * @return none */ __HIGH_CODE __INTERRUPT void MachineMode_Call_IRQ(void) { if(gs_machine_mode_func != NULL) { gs_machine_mode_func(); gs_machine_mode_func = NULL; } } /********************************************************************* * @fn MachineMode_Call * * @brief 注册机械模式执行函数,并在机械模式下调用 * * @param func - 用于在机械模式下执行的函数 * * @return none */ __HIGH_CODE void MachineMode_Call(MachineMode_Call_func func) { uint8_t i; uint32_t sw_vtf, sw_irqtable; uint32_t irqv; /* 这里关闭所有中断 */ irqv = (PFIC->ISR[0] >> 8) | (PFIC->ISR[1] << 24); PFIC->IRER[0] = 0xffffffff; PFIC->IRER[1] = 0xffffffff; /* 如果用户使用了SW中断的免表中断,则需要取消此函数所有注释 */ // for(i = 0; i < 4; i++) // { // if(PFIC->VTFIDR[i] == SWI_IRQn) // { // /* 找到了用户自己使用的SW中断,关闭它 */ // sw_vtf = PFIC->VTFADDR[i]; // PFIC->VTFADDR[i] = (sw_vtf & 0xFFFFFFFE); // break; // } // } sw_irqtable = _vector_base[SWI_IRQn]; _vector_base[SWI_IRQn] = (uint32_t)MachineMode_Call_IRQ; gs_machine_mode_func = func; /* 只打开SWI_IRQn */ PFIC_EnableIRQ(SWI_IRQn); /* 进入SWI_IRQn中断处理函数 */ PFIC_SetPendingIRQ(SWI_IRQn); /* 等待处理结束 */ while(gs_machine_mode_func != NULL); PFIC_DisableIRQ(SWI_IRQn); // if(i != 4) // { // /* 恢复原本的SW免表中断 */ // PFIC->VTFADDR[i] = sw_vtf; // } /* 这里恢复原来的中断使能配置 */ PFIC->IENR[0] = (irqv << 8); PFIC->IENR[1] = (irqv >> 24); } /********************************************************************* * @fn SetPI_func * * @brief 用于机械模式调用的使能预取指令函数 * * @param none * * @return none */void SetPI_func() { write_csr(0xbc0, 0x25); } /********************************************************************* * @fn SYS_EnablePI * * @brief 使能预取指令功能 * * @param none * * @return null */ void SYS_EnablePI() { MachineMode_Call(SetPI_func); } /********************************************************************* * @fn GetSysClock * * @brief 获取当前系统时钟 * * @param none * * @return Hz */ uint32_t GetSysClock(void) { if((R16_CLK_SYS_CFG & RB_CLK_SYS_MOD) == RB_CLK_SYS_MOD) { // 32K做主频 return (CAB_LSIFQ); } else if(R16_CLK_SYS_CFG & RB_XROM_SCLK_SEL) { if(!(R16_CLK_SYS_CFG & 0x1f)) { return ((R16_CLK_SYS_CFG & RB_OSC32M_SEL)?32000000:16000000); } else { // PLL进行分频 return (312000000 / (R16_CLK_SYS_CFG & 0x1f)); } } else if(R16_CLK_SYS_CFG & RB_OSC32M_SEL) { // 32M进行分频 return (32000000 / (R16_CLK_SYS_CFG & 0x1f)); } else { // 16M进行分频 return (16000000 / (R16_CLK_SYS_CFG & 0x1f)); } } /********************************************************************* * @fn SYS_GetInfoSta * * @brief 获取当前系统信息状态 * * @param i - refer to SYS_InfoStaTypeDef * * @return 是否开启 */ uint8_t SYS_GetInfoSta(SYS_InfoStaTypeDef i) { if(i == STA_SAFEACC_ACT) { return (R8_SAFE_ACCESS_SIG & RB_SAFE_ACC_ACT); } else { return (R8_GLOB_CFG_INFO & (1 << i)); } } /********************************************************************* * @fn SYS_ResetExecute * * @brief 执行系统软件复位 * * @param none * * @return none */ __HIGH_CODE void SYS_ResetExecute(void) { FLASH_ROM_SW_RESET(); sys_safe_access_enable(); R8_RST_WDOG_CTRL |= RB_SOFTWARE_RESET; sys_safe_access_disable(); } /********************************************************************* * @fn SYS_DisableAllIrq * * @brief 关闭所有中断,并保留当前中断值 * * @param pirqv - 当前保留中断值 * * @return none */ void SYS_DisableAllIrq(uint32_t *pirqv) { *pirqv = (PFIC->ISR[0] >> 8) | (PFIC->ISR[1] << 24); PFIC->IRER[0] = 0xffffffff; PFIC->IRER[1] = 0xffffffff; } /********************************************************************* * @fn SYS_RecoverIrq * * @brief 恢复之前关闭的中断值 * * @param irq_status - 当前保留中断值 * * @return none */ void SYS_RecoverIrq(uint32_t irq_status) { PFIC->IENR[0] = (irq_status << 8); PFIC->IENR[1] = (irq_status >> 24); } /********************************************************************* * @fn SYS_GetSysTickCnt * * @brief 获取当前系统(SYSTICK)计数值 * * @param none * * @return 当前计数值 */ uint32_t SYS_GetSysTickCnt(void) { return SysTick->CNTL; } /********************************************************************* * @fn WWDG_ITCfg * * @brief 看门狗定时器溢出中断使能 * * @param s - 溢出是否中断 * * @return none */ void WWDG_ITCfg(FunctionalState s) { uint8_t ctrl = R8_RST_WDOG_CTRL; if(s == DISABLE) { ctrl &= ~RB_WDOG_INT_EN; } else { ctrl |= RB_WDOG_INT_EN; } sys_safe_access_enable(); R8_RST_WDOG_CTRL = ctrl; sys_safe_access_disable(); } /********************************************************************* * @fn WWDG_ResetCfg * * @brief 看门狗定时器复位功能 * * @param s - 溢出是否复位 * * @return none */ void WWDG_ResetCfg(FunctionalState s) { uint8_t ctrl = R8_RST_WDOG_CTRL; if(s == DISABLE) { ctrl &= ~RB_WDOG_RST_EN; } else { ctrl |= RB_WDOG_RST_EN; } sys_safe_access_enable(); R8_RST_WDOG_CTRL = ctrl; sys_safe_access_disable(); } /********************************************************************* * @fn WWDG_ClearFlag * * @brief 清除看门狗中断标志,重新加载计数值也可清除 * * @param none * * @return none */ void WWDG_ClearFlag(void) { sys_safe_access_enable(); R8_RST_WDOG_CTRL |= RB_WDOG_INT_FLAG; sys_safe_access_disable(); } /********************************************************************* * @fn HardFault_Handler * * @brief 硬件错误中断,进入后执行复位,复位类型为上电复位 * * @param none * * @return none */ __INTERRUPT __HIGH_CODE __attribute__((weak)) void HardFault_Handler(void) { FLASH_ROM_SW_RESET(); sys_safe_access_enable(); R16_INT32K_TUNE = 0xFFFF; sys_safe_access_disable(); sys_safe_access_enable(); R8_RST_WDOG_CTRL |= RB_SOFTWARE_RESET; sys_safe_access_disable(); while(1); } /********************************************************************* * @fn mDelayuS * * @brief uS 延时 * * @param t - 时间参数 * * @return none */ __HIGH_CODE void mDelayuS(uint16_t t) { uint32_t i; #if(FREQ_SYS == 78000000) i = t * 13; #elif(FREQ_SYS == 62400000) i = ((uint32_t)t * 78) / 5; #elif(FREQ_SYS == 52000000) i = t * 13; #elif(FREQ_SYS == 39000000) i = (t * 13)>>1; #elif(FREQ_SYS == 26000000) i = (t * 13)>>1; #elif(FREQ_SYS == 24000000) i = t * 6; #elif(FREQ_SYS == 19500000) i = (t * 13)>>2; #elif(FREQ_SYS == 32000000) i = t << 3; #elif(FREQ_SYS == 16000000) i = t << 2; #elif(FREQ_SYS == 13000000) i = (t * 13)>>2; #elif(FREQ_SYS == 8000000) i = t << 1; #elif(FREQ_SYS == 4000000) i = t; #elif(FREQ_SYS == 2000000) i = t >> 1; #elif(FREQ_SYS == 1000000) i = t >> 2; #else i = t; #endif #if((FREQ_SYS == 78000000)||\ (FREQ_SYS == 39000000)||\ (FREQ_SYS == 19500000)) while(--i) { __nop(); }; #else do { __nop(); }while(--i); #endif } /********************************************************************* * @fn mDelaymS * * @brief mS 延时 * * @param t - 时间参数 * * @return none */ __HIGH_CODE void mDelaymS(uint16_t t) { do { mDelayuS(1000); }while(--t); } //#ifdef DEBUG //int _write(int fd, char *buf, int size) //{ // int i; // for(i = 0; i < size; i++) // { //#if DEBUG == Debug_UART0 // while(R8_UART0_TFC == UART_FIFO_SIZE); /* 等待数据发送 */ // R8_UART0_THR = *buf++; /* 发送数据 */ //#elif DEBUG == Debug_UART1 // while(R8_UART1_TFC == UART_FIFO_SIZE); /* 等待数据发送 */ // R8_UART1_THR = *buf++; /* 发送数据 */ //#elif DEBUG == Debug_UART2 // while(R8_UART2_TFC == UART_FIFO_SIZE); /* 等待数据发送 */ // R8_UART2_THR = *buf++; /* 发送数据 */ //#elif DEBUG == Debug_UART3 // while(R8_UART3_TFC == UART_FIFO_SIZE); /* 等待数据发送 */ // R8_UART3_THR = *buf++; /* 发送数据 */ //#endif // } // return size; //} //#endif int _write(int fd, char *buf, int size) { // BSP_Uart3_Send_Data(buf, size); return size; } /********************************************************************* * @fn _sbrk * * @brief Change the spatial position of data segment. * * @return size: Data length */ __attribute__((used)) void *_sbrk(ptrdiff_t incr) { extern char _end[]; static char *curbrk = _end; if ((curbrk + incr < _end) || ((uint32_t)curbrk + incr > (__get_SP() - 64))) return NULL - 1; curbrk += incr; return curbrk - incr; }