fr8008怎么实现 SysTick ?



  • fr8008怎么实现 SysTick ?



  • 如下

    
    /*
     * INCLUDE FILES
     ****************************************************************************************
     */
    #include <stdio.h>
    #include <string.h>
    
    #include "gap_api.h"
    #include "gatt_api.h"
    #include "ble_stack.h"
    #include "app_config.h"
    
    #include "jump_table.h"
    #include "co_log.h"
    
    #include "plf.h"
    #include "driver_system.h"
    #include "driver_pmu.h"
    #include "driver_uart.h"
    
    #include "ble_simple_peripheral.h"
    #include "simple_gatt_service.h"
    
    #undef LOG_LOCAL_LEVEL
    #define LOG_LOCAL_LEVEL        (LOG_LEVEL_INFO)
    const char *app_tag = "project";
    
    #define SYSTEM_STACK_SIZE           0x800
    
    void patch_init(void);
    void disable_ch_sel_2(void);
    void conn_req_rssi_filter(int8_t rssi_value);
    
    void systick_init(void);
    void systick_delay_ms(uint32_t ms);
    void systick_delay_us(uint32_t us);
    uint32_t systick_get_ms(void);
    
    /*
     * LOCAL VARIABLES
     */
    static volatile uint32_t g_systick_ms = 0;
    
    __attribute__((section("stack_section"))) static uint32_t system_stack[SYSTEM_STACK_SIZE/sizeof(uint32_t)];
    
    const struct jump_table_version_t _jump_table_version __attribute__((section("jump_table_3"))) = 
    {
        .stack_top_address = &system_stack[SYSTEM_STACK_SIZE/sizeof(uint32_t)],
        .firmware_version = 0x00000000,
    };
    
    const struct jump_table_image_t _jump_table_image __attribute__((section("jump_table_1"))) =
    {
        .image_type = IMAGE_TYPE_APP,
        .image_size = 0x20000,      
    };
    
    /*********************************************************************
     * @fn      SysTick_Handler
     *
     * @brief   1ms tick. Overrides the WEAK handler in boot_vectors.
     */
    void SysTick_Handler(void)
    {
        g_systick_ms++;
    }
    
    /*********************************************************************
     * @fn      systick_init
     *
     * @brief   Start SysTick at 1ms. Must be called after system_set_clock().
     */
    void systick_init(void)
    {
        uint32_t ticks = system_get_clock() / 1000;
    
        if ((ticks == 0) || ((ticks - 1) > SysTick_LOAD_RELOAD_Msk)) {
            return;
        }
    
        SysTick_Config(ticks);
    }
    
    /*********************************************************************
     * @fn      systick_get_ms
     *
     * @brief   Milliseconds since systick_init. Does not advance in sleep.
     */
    uint32_t systick_get_ms(void)
    {
        return g_systick_ms;
    }
    
    /*********************************************************************
     * @fn      systick_delay_ms
     *
     * @brief   Blocking delay. Do not call with interrupts disabled.
     */
    void systick_delay_ms(uint32_t ms)
    {
        uint32_t start = g_systick_ms;
    
        while ((uint32_t)(g_systick_ms - start) < ms) {
        }
    }
    
    /*********************************************************************
     * @fn      systick_delay_us
     *
     * @brief   Blocking us delay. Temporarily uses SysTick as a one-shot,
     *          then restores the 1ms tick.
     */
    void systick_delay_us(uint32_t us)
    {
        uint32_t clk = system_get_clock();
        uint32_t ticks_per_us;
        uint32_t max_us;
    
        if ((us == 0) || (clk < 1000000)) {
            return;
        }
    
        ticks_per_us = clk / 1000000;
        max_us = SysTick_LOAD_RELOAD_Msk / ticks_per_us;
    
        while (us) {
            uint32_t chunk = (us > max_us) ? max_us : us;
    
            SysTick->CTRL = 0;
            SysTick->LOAD = ticks_per_us * chunk - 1;
            SysTick->VAL  = 0;
            SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
    
            while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0) {
            }
    
            us -= chunk;
        }
    
        systick_init();
    }
    
    /*********************************************************************
     * @fn      user_entry_before_sleep_imp
     *
     * @brief   Before system goes to sleep mode, user_entry_before_sleep_imp()
     *          will be called, MCU peripherals can be configured properly before 
     *          system goes to sleep, for example, some MCU peripherals need to be
     *          used during the system is in sleep mode. 
     *
     * @param   None. 
     *       
     *
     * @return  None.
     */
    __attribute__((section("ram_code"))) void user_entry_before_sleep_imp(void)
    {
        /* SysTick uses CPU clock and would wake the core every 1ms */
        SysTick->CTRL = 0;
    
        pmu_calibration_stop();
    
        uart_putc_noint_no_wait(UART0, 's');
        co_delay_100us(1);
    
    	pmu_set_pin_to_PMU(GPIO_PORT_A, (1<<GPIO_BIT_1));
    	pmu_set_pin_to_PMU(GPIO_PORT_A, (1<<GPIO_BIT_0)|(1<<GPIO_BIT_4));
    	pmu_set_pin_dir(GPIO_PORT_A, (1<<GPIO_BIT_0)|(1<<GPIO_BIT_4),GPIO_DIR_IN);
    	pmu_set_pin_pull(GPIO_PORT_A, (1<<GPIO_BIT_0)|(1<<GPIO_BIT_4),GPIO_PULL_NONE);
        pmu_oscap_set(0);
    }
    
    /*********************************************************************
     * @fn      user_entry_after_sleep_imp
     *
     * @brief   After system wakes up from sleep mode, user_entry_after_sleep_imp()
     *          will be called, MCU peripherals need to be initialized again, 
     *          this can be done in user_entry_after_sleep_imp(). MCU peripherals
     *          status will not be kept during the sleep. 
     *
     * @param   None. 
     *       
     *
     * @return  None.
     */
    __attribute__((section("ram_code"))) void user_entry_after_sleep_imp(void)
    {
        
        pmu_set_pin_to_CPU(GPIO_PORT_A, (1<<GPIO_BIT_0));
        
        system_set_port_mux(GPIO_PORT_A, GPIO_BIT_0, PORTA0_FUNC_UART0_RXD);
        system_set_port_mux(GPIO_PORT_A, GPIO_BIT_1, PORTA1_FUNC_UART0_TXD);
        uart_init(UART0, 1152);
        fr_uart_enableIrq(UART0, Uart_irq_erbfi);
    
        /* RC calibration start. Ensure the accuracy of sleep wake time */
        pmu_calibration_start(PMU_CALI_SEL_RCLFOSC, LP_RC_CALIB_CNT);
    
        uart_putc_noint_no_wait(UART0, 'w');
        co_delay_100us(1);
    
        NVIC_EnableIRQ(PMU_IRQn);
    
        systick_init();
    }
    
    __attribute__((section("ram_code"))) void main_loop(void)
    {
        while(1)
        {
            if(ble_stack_schedule_allow())
            {
                /*user code should be add here*/
                
                /* schedule internal stack event */
                ble_stack_schedule();
            }
            
            GLOBAL_INT_DISABLE();
            switch(ble_stack_sleep_check())
            {
                case 2:
                {
                    ble_stack_enter_sleep();
                }
                break;
                default:
                    break;
            }
            GLOBAL_INT_RESTORE();
            
            ble_stack_schedule_backward();
        }
    }
    
    /*********************************************************************
     * @fn      proj_init
     *
     * @brief   Main entrancy of user application. This function is called after BLE stack
     *          is initialized, and all the application code will be executed from here.
     *          In that case, application layer initializtion can be startd here. 
     *
     * @param   None. 
     *       
     *
     * @return  None.
     */
    void proj_init(void)
    {
        LOG_INFO(app_tag, "BLE Peripheral\r\n");
    	co_printf("%s\r\n",__func__);
        systick_delay_ms(500);
    	co_printf("%s\r\n",__TIME__);
    	
        // Application layer initialization, can included bond manager init, 
        // advertising parameters init, scanning parameter init, GATT service adding, etc.    
        simple_peripheral_init();
    }