#include "drv_clk.h"
#include "drv_misc.h"
#include "kit_debug.h"

#define AIRCR_VECTKEY_MASK          ((uint32_t)0x05FA0000)
#define NVIC_PriorityGroup_0        ((uint32_t)0x700)
#define GPIO_REMAP_EN_SWO_DIS_JTAG  ((uint32_t)0x02000000)

/***********************************************************
 *HSI是高速内部时钟,RC振荡器,频率为8MHz。 
 *HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 
 *LSI是低速内部时钟,RC振荡器,频率为40kHz。 
 *LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 
 *PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍

 *FCLK,提供给CPU内核的时钟信号,CPU的主频就是指这个信号; 
 *HCLK,提供给高速总线AHB的时钟信号; 
 *PCLK,提供给低速总线APB的时钟信号;
 *SYSCLK,系统时钟,最大72MHz

 *HSE(8M)->PLLXTPRE(*1)->PLLSRC(HSE)->PLLMUL(*9)->SW(PLL)
 *互联型 HSE(8M)->PREDIV1SCR(HSE)->PLLSRC(/1)->PLLMUL(*9) -> SW (PLL)

***********************************************************/
void drv_clk_init(void)
{
//    uint16_t dly = 500;
//#ifndef STM32F10X_CL
//    RCC->CFGR &= (uint32_t)0xF8FF0000;
//#else
//    RCC->CFGR &= (uint32_t)0xF0FF0000;
//#endif
//    SCB->VTOR = APP_START_ADDR;
//    /* Enable HSE */    
//    RCC->CR |= ((uint32_t)RCC_CR_HSEON);
//    
//    while((RCC->CR & RCC_CR_HSERDY) == 0)
//    {
//        if(dly-- < 1)
//            KIT_ASSERT_RES(0, kKit_Ret_Error);
//    }

//    /* Enable Prefetch Buffer */
//    FLASH->ACR |= FLASH_ACR_PRFTBE;

//    /* Flash 2 wait state */
//    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
//    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    
//    /* HCLK = SYSCLK */
//    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;     
//    /* PCLK2 = HCLK */
//    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;   
//    /* PCLK1 = HCLK */
//    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
//    /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
//    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
//#ifdef STM32F10X_CL    
//    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLMULL9);
//#else
//    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
//#endif    
//    /* Enable PLL */
//    RCC->CR |= RCC_CR_PLLON;

//    dly = 0xFFFF;
//    /* Wait till PLL is ready */
//    while((RCC->CR & RCC_CR_PLLRDY) == 0)
//    {
//         if(dly-- < 1)
//            KIT_ASSERT_RES(0, kKit_Ret_Error);
//    }
//    
//    /* Select PLL as system clock source */
//    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
//    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

//    dly = 0xFFFF;
//    /* Wait till PLL is used as system clock source */
//    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
//    {
//         if(dly-- < 1)
//            KIT_ASSERT_RES(0, kKit_Ret_Error);
//    }
//    //关闭抢占优先级
//    SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup_0;
//    //打开复用时钟
//    RCC->APB2ENR |= RCC_APB2Periph_AFIO;
//    //PB3 PB4作为普通IO
//    AFIO->MAPR |= GPIO_REMAP_EN_SWO_DIS_JTAG; 
}


kit_ret_e drv_clk_set_status(BspClkType clk, uint32_t dev)
{
    kit_ret_e res = kKit_Ret_Ok;
    
    
    return res;
}

NoArgFuncCall systick_int_call;
kit_ret_e drv_clk_set_system_tick(uint8_t priority, uint16_t period, NoArgFuncCall call)
{
    uint32_t  tick;
    kit_ret_e res;

    KIT_ASSERT_PARAM((call != NULL) && (CLOCK_SYS_FREQ / 1000 * period) < SysTick_LOAD_RELOAD_Msk);
    tick = CLOCK_SYS_FREQ / 1000 * period; 
    if ((call != NULL) && (tick < SysTick_LOAD_RELOAD_Msk))
    {
        systick_int_call = call;
        SysTick->LOAD  = (tick & SysTick_LOAD_RELOAD_Msk) - 1;  /* set reload register */
        drv_misc_set_nvic(SysTick_IRQn, priority);              /* set Priority for Cortex-M0 System Interrupts */
        SysTick->VAL   = 0;                                     /* Load the SysTick Counter Value */
        SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                         SysTick_CTRL_TICKINT_Msk   |
                         SysTick_CTRL_ENABLE_Msk;               /* Enable SysTick IRQ and SysTick Timer */
        
        res = kKit_Ret_Ok;
    }
    else
    {
        res = kKit_Ret_ParamErr;
    }
                                                           
    return res;
}

void SysTick_Handler(void)
{
    KIT_ASSERT_PARAM(systick_int_call != NULL);
    
    systick_int_call();
}