1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 /*! \file driver_systick.c
10     \brief Encapsulates the ARM sysTick counter, which is used for benchmarking
11 */
12 
13 #include "sensor_fusion.h"
14 #include "drivers.h"
15 
16 // SysTick register definitions based on CMSIS definitions for same
17 #define SYST_CSR    SysTick->CTRL   // SysTick Control & Status Register
18 #define SYST_RVR    SysTick->LOAD   // SysTick Reload Value Register
19 #define SYST_CVR    SysTick->VAL    // SysTick Current Value Register
20 
21 // ARM-core specific function that enables the ARM systick timer on Kinetis uCs.
22 // this is purely for algorithm benchmarking and can either be deleted or re-written for use on other uCs.
23 // the systick clock frequency for each uC are defined as CORE_SYSTICK_HZ in types.h.
24 
25 // the timer is 24 bit so allows measurement of intervals up to 2^24/CORE_SYSTICK_HZ secs=0.35s for a 48MHz uC.
ARM_systick_enable(void)26 void ARM_systick_enable(void)
27 {
28     SYST_CSR = 0x5u;        // enable systick from internal clock
29     SYST_RVR = 0x00FFFFFFu; // set reload to maximum 24 bit value
30     return;
31 }
32 
33 // ARM-core specific function to store the current systick timer ticks for benchmarking
ARM_systick_start_ticks(int32 * pstart)34 void ARM_systick_start_ticks(int32 *pstart)
35 {
36     // store the 24 bit systick timer
37     *pstart = SYST_CVR & 0x00FFFFFF;
38 
39     return;
40 }
41 
42 // ARM-core specific function to compute the elapsed systick timer ticks for benchmarking
ARM_systick_elapsed_ticks(int32 start_ticks)43 int32 ARM_systick_elapsed_ticks(int32 start_ticks)
44 {
45 	int32 elapsed_ticks;
46 
47 	// subtract the stored start ticks and check for wraparound down through zero
48 	elapsed_ticks = start_ticks - (SYST_CVR & 0x00FFFFFF);
49 	if (elapsed_ticks < 0) elapsed_ticks += SYST_RVR;
50 
51 	return elapsed_ticks;
52 }
53 
ARM_systick_delay_ms(uint32 iSystemCoreClock,uint32 delay_ms)54 void ARM_systick_delay_ms(uint32 iSystemCoreClock, uint32 delay_ms)
55 {
56 	int32 istart_ticks;	// start ticks on entry
57 	int32 ielapsed_ticks;	// elapsed ticks
58 	int16 i;		// loop counter
59 
60 	// loop for requested number of ms
61 	for (i = 0; i < delay_ms; i++)
62 	{
63 		// loop until 1ms has elapsed
64 		ARM_systick_start_ticks(&istart_ticks);
65 		do
66 		{
67 			ielapsed_ticks = ARM_systick_elapsed_ticks(istart_ticks);
68 		} while (ielapsed_ticks < iSystemCoreClock / 1000);
69 	}
70 
71 	return;
72 }
73