1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 /**
10  * @file  systick_utils.c
11  * @brief Encapsulates the ARM sysTick counter, which is used for computing delays.
12  *         ARM-core specific function that enables the ARM systick timer on Kinetis uCs.
13  *         the timer is 24 bit so allows measurement of intervals up to 2^24/CORE_SYSTICK_HZ secs=0.35s for a 48MHz uC.
14 */
15 
16 #include "issdk_hal.h"
17 
18 // SysTick register definitions based on CMSIS definitions.
19 #define SYST_CSR SysTick->CTRL // SysTick Control & Status Register
20 #define SYST_RVR SysTick->LOAD // SysTick Reload Value Register
21 #define SYST_CVR SysTick->VAL  // SysTick Current Value Register
22 
23 uint32_t g_ovf_stamp;
24 volatile uint32_t g_ovf_counter = 0;
25 
26 #ifndef SDK_OS_FREE_RTOS
27 // SDK specific SysTick Interrupt Handler
SysTick_Handler(void)28 void SysTick_Handler(void)
29 {
30     g_ovf_counter += 1;
31 }
32 #endif
33 
34 // ARM-core specific function to enable systicks.
BOARD_SystickEnable(void)35 void BOARD_SystickEnable(void)
36 {
37     SYST_CSR = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk |
38                SysTick_CTRL_ENABLE_Msk; // Enable systick from internal clock with Interrupts.
39     SYST_RVR = 0x00FFFFFFu;             // Set reload to maximum 24 bit value.
40     return;
41 }
42 
43 // ARM-core specific function to store the current systick timer ticks.
BOARD_SystickStart(int32_t * pStart)44 void BOARD_SystickStart(int32_t *pStart)
45 {
46     // Store the 24 bit systick timer.
47     g_ovf_stamp = g_ovf_counter;
48     *pStart = SYST_CVR & 0x00FFFFFF;
49 }
50 
51 // ARM-core specific function to compute the elapsed systick timer ticks.
BOARD_SystickElapsedTicks(int32_t * pStart)52 int32_t BOARD_SystickElapsedTicks(int32_t *pStart)
53 {
54     int32_t elapsed;
55 
56     // Subtract the stored start ticks and check for wraparound down through zero.
57     elapsed = *pStart - (SYST_CVR & 0x00FFFFFF);
58     elapsed += SYST_RVR * (g_ovf_counter - g_ovf_stamp);
59 
60     return elapsed;
61 }
62 
63 // ARM-core specific function to compute the elapsed time in micro seconds.
BOARD_SystickElapsedTime_us(int32_t * pStart)64 uint32_t BOARD_SystickElapsedTime_us(int32_t *pStart)
65 {
66     uint32_t time_us, elapsed;
67     uint32_t systemCoreClock;
68 
69     elapsed = BOARD_SystickElapsedTicks(pStart);
70     systemCoreClock = CLOCK_GetFreq(kCLOCK_CoreSysClk);
71 
72     time_us = COUNT_TO_USEC(elapsed, systemCoreClock);
73 
74     // Update the 24 bit systick timer.
75     BOARD_SystickStart(pStart);
76 
77     return time_us;
78 }
79 
80 // ARM-core specific function to insert delays in milli seconds.
BOARD_DELAY_ms(uint32_t delay_ms)81 void BOARD_DELAY_ms(uint32_t delay_ms)
82 {
83     int32_t start, elapsed;
84     uint32_t systemCoreClock = CLOCK_GetFreq(kCLOCK_CoreSysClk);
85 
86     BOARD_SystickStart(&start);
87     do // Loop for requested number of ms.
88     {
89         elapsed = BOARD_SystickElapsedTicks(&start);
90     } while(COUNT_TO_MSEC(elapsed, systemCoreClock) < delay_ms);
91 }
92