| | |
| | | /* |
| | | * Copyright (c) 2019-2023 Beijing Hanwei Innovation Technology Ltd. Co. and |
| | | * Copyright (c) 2019-2025 Beijing Hanwei Innovation Technology Ltd. Co. and |
| | | * its subsidiaries and affiliates (collectly called MKSEMI). |
| | | * |
| | | * All rights reserved. |
| | |
| | | #include "mk_sleep_timer.h" |
| | | #include "mk_reset.h" |
| | | // #include "board.h" |
| | | |
| | | #if defined(__ARMCC_VERSION) |
| | | |
| | | #elif defined(__ICCARM__) |
| | | |
| | | #elif defined(__GNUC__) |
| | | |
| | | #include <sys/stat.h> |
| | | #include <unistd.h> |
| | | |
| | | __WEAK int _close(int file); |
| | | __WEAK int _lseek(int file, int ptr, int dir); |
| | | __WEAK int _read(int file, char *ptr, int len); |
| | | __WEAK int _write(int file, char *ptr, int len); |
| | | |
| | | int _close(int file) |
| | | { |
| | | return -1; // Always fail |
| | | } |
| | | |
| | | int _lseek(int file, int ptr, int dir) |
| | | { |
| | | return 0; // Always succeed (no seeking in embedded systems) |
| | | } |
| | | |
| | | int _read(int file, char *ptr, int len) |
| | | { |
| | | return 0; // No data to read |
| | | } |
| | | |
| | | int _write(int file, char *ptr, int len) |
| | | { |
| | | return len; // Pretend to write all bytes |
| | | } |
| | | #endif |
| | | |
| | | uint32_t mk_chip_id(void) |
| | | { |
| | |
| | | |
| | | void bor_close(void) |
| | | { |
| | | // disable BOD |
| | | // disable BOR |
| | | SYSCON->BOD_BOR &= ~SYSCON_BOR_EN_MSK; |
| | | } |
| | | |
| | | /* SYS Timer */ |
| | | |
| | | uint32_t sys_timer_freq = 0; |
| | | |
| | | void sys_timer_open(void) |
| | | { |
| | | // DIV = 1 (max: ~68.8s, resolution: ~16ns) |
| | | // DIV = 16 (max: ~1101.2s, resolution: ~256ns) |
| | | // DIV = 256 (max: ~17620.3s resolution: ~65us) |
| | | struct DUAL_TIMER_CFG_T sys_timer_cfg = { |
| | | .type = DUAL_TIMER_TYPE_FREERUNNING, |
| | | .prescale = DUAL_TIMER_PRESCALE_DIV1, |
| | | .prescale = SYS_TIMER_DIV == 1 ? DUAL_TIMER_PRESCALE_DIV1 : (SYS_TIMER_DIV == 16 ? DUAL_TIMER_PRESCALE_DIV16 : DUAL_TIMER_PRESCALE_DIV256), |
| | | .width = DUAL_TIMER_SIZE_32BIT, |
| | | .int_en = false, |
| | | .load = 0xffffffff, |
| | |
| | | |
| | | dual_timer_open(DUAL_TIMER_ID0, &sys_timer_cfg); |
| | | dual_timer_start(DUAL_TIMER_ID0, sys_timer_cfg.load); |
| | | uint16_t div = sys_timer_cfg.prescale == DUAL_TIMER_PRESCALE_DIV1 ? 1 : sys_timer_cfg.prescale == DUAL_TIMER_PRESCALE_DIV16 ? 16 : 256; |
| | | sys_timer_freq = clock_get_frequency(CLOCK_APB_CLK) / div; |
| | | } |
| | | |
| | | void sys_timer_close(void) |
| | |
| | | dual_timer_close(DUAL_TIMER_ID0); |
| | | } |
| | | |
| | | #if defined(__ICCARM__) |
| | | #pragma default_function_attributes = __ramfunc |
| | | #endif |
| | | uint32_t sys_timer_get(void) |
| | | { |
| | | return -dual_timer_get(DUAL_TIMER_ID0); |
| | | } |
| | | #if defined(__ICCARM__) |
| | | #pragma default_function_attributes = |
| | | #endif |
| | | |
| | | // max: 68829 us (DIV = 1) |
| | | void sys_timer_delay_us(uint32_t time_us) |
| | |
| | | NVIC_SetPriority(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ |
| | | SysTick->VAL = 0; /* A write of any value clears the field to 0 */ |
| | | SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ |
| | | // Store SysTick counter |
| | | sys_tick_env.load = ticks; |
| | | } |
| | | |
| | | uint32_t sys_tick_us(void) |
| | |
| | | val = load; |
| | | } |
| | | |
| | | uint32_t tick_us = (count * 328 + (load - val)) * 30; |
| | | uint32_t tick_us = (count * 328 + (load - val)) * 61 / 2; |
| | | |
| | | int_unlock(lock); |
| | | |
| | |
| | | return sys_tick_env.count; |
| | | } |
| | | |
| | | void sys_tick_callback_set(void (*callback)(void)) |
| | | void sys_tick_callback_set(void (*callback)(uint32_t elapsed_ticks)) |
| | | { |
| | | sys_tick_env.callback = callback; |
| | | } |
| | | |
| | | #if 0 |
| | | uint32_t sys_tick_elapse_ms(void) |
| | | { |
| | | uint32_t lock = int_lock(); |
| | |
| | | return elapse_ms; |
| | | } |
| | | |
| | | uint32_t sys_tick_elapse_ticks(void) |
| | | { |
| | | uint32_t lock = int_lock(); |
| | | |
| | | uint32_t load = SysTick->LOAD + 1; |
| | | uint32_t val = SysTick->VAL; |
| | | |
| | | uint32_t flag_pending = REG_READ(0xE000ED04) & (1 << 26); |
| | | if (flag_pending) |
| | | { |
| | | val = 0; |
| | | } |
| | | else if (val == 0) |
| | | { |
| | | val = load; |
| | | } |
| | | |
| | | int_unlock(lock); |
| | | |
| | | return load - val; |
| | | } |
| | | |
| | | static uint32_t used_cnt; |
| | | void sys_tick_pause(void) |
| | | { |
| | | // Stop SysTick |
| | |
| | | val = load; |
| | | } |
| | | |
| | | // Store SysTick counter |
| | | sys_tick_env.load = load; |
| | | // SysTick->VAL cannot be set |
| | | sys_tick_env.elapse += (load - val); |
| | | used_cnt = load - val; |
| | | } |
| | | |
| | | void sys_tick_resume(void) |
| | | { |
| | | sys_tick_start(sys_tick_env.load); |
| | | |
| | | uint32_t slp_cnt = high_xtal_off_time(); |
| | | uint32_t slp_cnt = xtal_38m4_off_time(); |
| | | uint32_t cnt = slp_cnt / sys_tick_env.load; |
| | | sys_tick_env.elapse += (slp_cnt - cnt * sys_tick_env.load); |
| | | while (sys_tick_env.elapse >= sys_tick_env.load) |
| | |
| | | } |
| | | |
| | | sys_tick_env.count += cnt; |
| | | if ((sys_tick_env.callback != NULL) && (cnt)) |
| | | slp_cnt += used_cnt; |
| | | if ((sys_tick_env.callback != NULL) && (slp_cnt)) |
| | | { |
| | | sys_tick_env.callback(); |
| | | sys_tick_env.callback(slp_cnt); |
| | | } |
| | | } |
| | | #endif |
| | | |
| | | void SysTick_Handler(void) |
| | | { |
| | |
| | | sys_tick_env.count++; |
| | | if (sys_tick_env.callback != NULL) |
| | | { |
| | | sys_tick_env.callback(); |
| | | sys_tick_env.callback(sys_tick_env.load); |
| | | } |
| | | // board_led_off(BOARD_LED_2); |
| | | } |
| | | |
| | | void sys_reset(uint32_t error) |
| | | { |
| | | //LOG_INFO(TRACE_MODULE_DRIVER, "system reboot%x", error); |
| | | LOG_INFO(TRACE_MODULE_DRIVER, "system reboot%x", error); |
| | | |
| | | delay_us(10000); |
| | | |
| | |
| | | uint32_t i=1000*nTimer; |
| | | delay_US(i); |
| | | } |
| | | |
| | | void delay_us(uint32_t cnt) |
| | | { |
| | | #define SYSTEM_CLOCK_MHZ 62.4 |
| | |
| | | "bhi loop%=\n" |
| | | "pop {r4,r5}\n" |
| | | "exit%=:\n" |
| | | : |
| | | : [mult_hi] "i"(SYSTEM_CLOCK_MULT_HI), [mult_lo] "i"(SYSTEM_CLOCK_MULT_LO), [shift] "i"(SYSTEM_CLOCK_LSLS_BITS), [adjust] "i"(AAPCS_PREP_CYCLES), |
| | | [decr] "i"(DELAY_LOOP_CYCLES)); |
| | | : |
| | | : [mult_hi] "i"(SYSTEM_CLOCK_MULT_HI), [mult_lo] "i"(SYSTEM_CLOCK_MULT_LO), [shift] "i"(SYSTEM_CLOCK_LSLS_BITS), [adjust] "i"(AAPCS_PREP_CYCLES), |
| | | [decr] "i"(DELAY_LOOP_CYCLES)); |
| | | |
| | | #if defined(__GNUC__) && !defined(__ARMCC_VERSION) |
| | | __asm volatile(".syntax divided\n"); |
| | | #endif |
| | | } |
| | | |
| | | |
| | | uint8_t count_bits(uint32_t value) |
| | | { |
| | | uint8_t count = 0; |