1 /* 2 * Copyright (c) 2020-2023 Arm Limited. All rights reserved. 3 * SPDX-License-Identifier: BSD-3-Clause 4 */ 5 6 #include "microsecond_timer.h" 7 #include "cmsis.h" 8 9 /* Maximum count for the SysTick */ 10 #define MAX_SYSTICK_VAL (0x00ffffff) 11 12 typedef struct _systick_us_context { 13 uint64_t overflow_count; /* Number of overflows; Forms high-order bits of 64-bit elapsed time */ 14 uint32_t core_clock_per_us; /* Number of core clocks per microsecond */ 15 } systick_us_context_t; 16 17 /* Global state for the systick microsecond timer */ 18 static systick_us_context_t s_context = { 0 }; 19 20 /* @brief SysTick interrupt handler. 21 * 22 * Increments the high-order bits of the 64-bit elapsed time every time the 24-bit SysTick 23 * counter rolls over from 0 and starts counting again from the maximum value. 24 */ SysTick_Handler(void)25void SysTick_Handler(void) 26 { 27 s_context.overflow_count += MAX_SYSTICK_VAL + 1; 28 } 29 30 /* Initializes the SysTick timer */ microsecond_timer_init(void)31void microsecond_timer_init(void) { 32 /* Precompute the number of clocks per microsecond */ 33 s_context.core_clock_per_us = SystemCoreClock / 1e6; 34 35 /* First disable SysTick */ 36 SysTick->CTRL = 0; 37 38 /* Init SysTick reload with the maximum count */ 39 SysTick->LOAD = MAX_SYSTICK_VAL; 40 SysTick->VAL = 0; /* Writing any value clears */ 41 42 /* Enable the interrupt and start counting */ 43 SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; 44 } 45 get_elapsed_us(void)46uint64_t get_elapsed_us(void) 47 { 48 uint32_t elapsed_microseconds = (MAX_SYSTICK_VAL - SysTick->VAL) / s_context.core_clock_per_us; 49 return s_context.overflow_count + elapsed_microseconds; 50 } 51 get_elapsed_ms(void)52static uint64_t get_elapsed_ms(void) 53 { 54 return get_elapsed_us() / 1000; 55 } 56 sleep_ms(uint32_t delay_ms)57void sleep_ms(uint32_t delay_ms) 58 { 59 uint64_t start_time = get_elapsed_ms(); 60 while (get_elapsed_ms() - start_time < delay_ms) { 61 } 62 } 63