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(); }