402 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			402 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /********************************** (C) COPYRIGHT *******************************
 | |
|  * File Name          : CH59x_SYS.c
 | |
|  * Author             : WCH
 | |
|  * Version            : V1.2
 | |
|  * Date               : 2021/11/17
 | |
|  * Description
 | |
|  *********************************************************************************
 | |
|  * 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 "CH59x_common.h"
 | |
| 
 | |
| /*********************************************************************
 | |
|  * @fn      SetSysClock
 | |
|  *
 | |
|  * @brief   配置系统运行时钟
 | |
|  *
 | |
|  * @param   sc      - 系统时钟源选择 refer to SYS_CLKTypeDef
 | |
|  *
 | |
|  * @return  none
 | |
|  */
 | |
| __HIGH_CODE
 | |
| void SetSysClock(SYS_CLKTypeDef sc)
 | |
| {
 | |
|     uint8_t chip_type=0;
 | |
|     if(((*(uint32_t*)ROM_CFG_VERISON)&0xFF) == DEF_CHIP_ID_CH592A)
 | |
|     {
 | |
|         chip_type = 1;
 | |
|     }
 | |
|     sys_safe_access_enable();
 | |
|     R8_PLL_CONFIG &= ~(1 << 5); //
 | |
|     sys_safe_access_disable();
 | |
|     if(sc & 0x20)  // HSE div
 | |
|     {
 | |
|         sys_safe_access_enable();
 | |
|         R32_CLK_SYS_CFG = (0 << 6) | (sc & 0x1f) | RB_TX_32M_PWR_EN | RB_PLL_PWR_EN;
 | |
|         __nop();
 | |
|         __nop();
 | |
|         __nop();
 | |
|         __nop();
 | |
|         sys_safe_access_disable();
 | |
|         sys_safe_access_enable();
 | |
|         SAFEOPERATE;
 | |
|         R8_FLASH_CFG = 0X51;
 | |
|         sys_safe_access_disable();
 | |
|     }
 | |
| 
 | |
|     else if(sc & 0x40) // PLL div
 | |
|     {
 | |
|         sys_safe_access_enable();
 | |
|         R32_CLK_SYS_CFG = (1 << 6) | (sc & 0x1f) | RB_TX_32M_PWR_EN | RB_PLL_PWR_EN;
 | |
|         __nop();
 | |
|         __nop();
 | |
|         __nop();
 | |
|         __nop();
 | |
|         sys_safe_access_disable();
 | |
|         sys_safe_access_enable();
 | |
|         if(chip_type)
 | |
|         {
 | |
|             R8_FLASH_CFG = 0X53;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             R8_FLASH_CFG = 0X52;
 | |
|         }
 | |
|         sys_safe_access_disable();
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         sys_safe_access_enable();
 | |
|         R32_CLK_SYS_CFG |= RB_CLK_SYS_MOD;
 | |
|         sys_safe_access_disable();
 | |
|     }
 | |
|     //更改FLASH clk的驱动能力
 | |
|     sys_safe_access_enable();
 | |
|     R8_PLL_CONFIG |= 1 << 7;
 | |
|     sys_safe_access_disable();
 | |
| }
 | |
| 
 | |
| /*********************************************************************
 | |
|  * @fn      GetSysClock
 | |
|  *
 | |
|  * @brief   获取当前系统时钟
 | |
|  *
 | |
|  * @param   none
 | |
|  *
 | |
|  * @return  Hz
 | |
|  */
 | |
| uint32_t GetSysClock(void)
 | |
| {
 | |
|     uint16_t rev;
 | |
| 
 | |
|     rev = R32_CLK_SYS_CFG & 0xff;
 | |
|     if((rev & 0x40) == (0 << 6))
 | |
|     { // 32M进行分频
 | |
|         return (32000000 / (rev & 0x1f));
 | |
|     }
 | |
|     else if((rev & RB_CLK_SYS_MOD) == (1 << 6))
 | |
|     { // PLL进行分频
 | |
|         return (480000000 / (rev & 0x1f));
 | |
|     }
 | |
|     else
 | |
|     { // 32K做主频
 | |
|         return (32000);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*********************************************************************
 | |
|  * @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;
 | |
|     asm volatile("fence.i");
 | |
| }
 | |
| 
 | |
| /*********************************************************************
 | |
|  * @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)
 | |
| {
 | |
|     uint32_t val;
 | |
| 
 | |
|     val = SysTick->CNT;
 | |
|     return (val);
 | |
| }
 | |
| 
 | |
| /*********************************************************************
 | |
|  * @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 == 80000000)
 | |
|     i = t * 20;
 | |
| #elif(FREQ_SYS == 60000000)
 | |
|     i = t * 15;
 | |
| #elif(FREQ_SYS == 48000000)
 | |
|     i = t * 12;
 | |
| #elif(FREQ_SYS == 40000000)
 | |
|     i = t * 10;
 | |
| #elif(FREQ_SYS == 32000000)
 | |
|     i = t << 3;
 | |
| #elif(FREQ_SYS == 24000000)
 | |
|     i = t * 6;
 | |
| #elif(FREQ_SYS == 16000000)
 | |
|     i = t << 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 << 1;
 | |
| #endif
 | |
|     do
 | |
|     {
 | |
|         __nop();
 | |
|     } while(--i);
 | |
| }
 | |
| 
 | |
| /*********************************************************************
 | |
|  * @fn      mDelaymS
 | |
|  *
 | |
|  * @brief   mS 延时
 | |
|  *
 | |
|  * @param   t       - 时间参数
 | |
|  *
 | |
|  * @return  none
 | |
|  */
 | |
| __HIGH_CODE
 | |
| void mDelaymS(uint16_t t)
 | |
| {
 | |
|     uint16_t i;
 | |
| 
 | |
|     for(i = 0; i < t; i++)
 | |
|     {
 | |
|         mDelayuS(1000);
 | |
|     }
 | |
| }
 | |
| 
 | |
| #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
 | |
| 
 | |
| /*********************************************************************
 | |
|  * @fn      _sbrk
 | |
|  *
 | |
|  * @brief   Change the spatial position of data segment.
 | |
|  *
 | |
|  * @return  size: Data length
 | |
|  */
 | |
| __attribute__((used))
 | |
| void *_sbrk(ptrdiff_t incr)
 | |
| {
 | |
|     extern char _end[];
 | |
|     extern char _heap_end[];
 | |
|     static char *curbrk = _end;
 | |
| 
 | |
|     if ((curbrk + incr < _end) || (curbrk + incr > _heap_end))
 | |
|     return NULL - 1;
 | |
| 
 | |
|     curbrk += incr;
 | |
|     return curbrk - incr;
 | |
| }
 | |
| 
 | |
| 
 |