blob: 7c9f4b8e35e6a7e13f076ab34774d1a0c9aab93c [file] [log] [blame]
alexander3c798932021-03-26 21:42:19 +00001/*
2 * Copyright (c) 2021 Arm Limited. All rights reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17#ifdef __cplusplus
18extern "C"
19{
20#endif
21
22#include "irqs.h"
23#include "cmsis.h"
24
25#include <stdio.h>
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +010026#include <inttypes.h>
alexander3c798932021-03-26 21:42:19 +000027
28static uint64_t cpu_cycle_count = 0;
29
30/**
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +010031 * External references
32 */
33extern uint32_t __INITIAL_SP;
34extern uint32_t __STACK_LIMIT;
35
36#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
37 extern uint32_t __STACK_SEAL;
38#endif
39
40extern __NO_RETURN void __PROGRAM_START(void);
41
42/**
alexander3c798932021-03-26 21:42:19 +000043 * @brief Dump core registers on stdout
44 */
45static void LogCoreCPURegisters(void)
46{
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +010047 printf("CTRL : 0x%08" PRIx32 "\n", __get_CONTROL());
48 printf("IPSR : 0x%08" PRIx32 "\n", __get_IPSR());
49 printf("APSR : 0x%08" PRIx32 "\n", __get_APSR());
50 printf("xPSR : 0x%08" PRIx32 "\n", __get_xPSR());
51 printf("PSP : 0x%08" PRIx32 "\n", __get_PSP());
52 printf("MSP : 0x%08" PRIx32 "\n", __get_MSP());
53 printf("PRIMASK : 0x%08" PRIx32 "\n", __get_PRIMASK());
54 printf("BASEPRI : 0x%08" PRIx32 "\n", __get_BASEPRI());
55 printf("FAULTMSK: 0x%08" PRIx32 "\n", __get_FAULTMASK());
alexander3c798932021-03-26 21:42:19 +000056}
57
58/**
59 * @brief Default interrupt handler - an infinite loop.
60 **/
61__attribute__((noreturn)) static void DefaultHandler(void)
62{
63 LogCoreCPURegisters();
64 while (1) {
65 /* Without the following line, armclang may optimize away the
66 * infinite loop because it'd be without side effects and thus
67 * undefined behaviour. */
68 __ASM volatile("");
69 }
70}
71
72#define DEFAULT_HANDLER_CALL(type) \
73 do { \
74 printf("\n%s caught by function %s\n", \
75 type, __FUNCTION__); \
76 DefaultHandler(); \
77 } while (0)
78
79#define DEFAULT_ERROR_HANDLER_CALL() \
80 DEFAULT_HANDLER_CALL("Exception")
81
82#define DEFAULT_IRQ_HANDLER_CALL() \
83 DEFAULT_HANDLER_CALL("Interrupt")
84
85/**
86 * Dummy Exception Handlers for core interrupts.
87 *
88 * Weak definitions provided to be used if the user chooses not
89 * to override them.
90 **/
91
92/**
93 * @brief Non maskable interrupt handler.
94 **/
95 __attribute__((weak)) void NMI_Handler(void)
96{
97 DEFAULT_ERROR_HANDLER_CALL();
98}
99
100/**
101 * @brief Hardfault interrupt handler.
102 **/
103 __attribute__((weak)) void HardFault_Handler(void)
104{
105 DEFAULT_ERROR_HANDLER_CALL();
106}
107
108/**
109 * @brief Memory management interrupt handler.
110 **/
111__attribute__((weak)) void MemManage_Handler(void)
112{
113 DEFAULT_IRQ_HANDLER_CALL();
114}
115
116/**
117 * @brief Bus fault interrupt handler.
118 **/
119__attribute__((weak)) void BusFault_Handler(void)
120{
121 DEFAULT_ERROR_HANDLER_CALL();
122}
123
124/**
125 * @brief Usage fault interrupt handler.
126 **/
127__attribute__((weak)) void UsageFault_Handler(void)
128{
129 DEFAULT_ERROR_HANDLER_CALL();
130}
131
132/**
133 * @brief Secure access fault interrupt handler.
134 **/
135__attribute__((weak)) void SecureFault_Handler(void)
136{
137 DEFAULT_ERROR_HANDLER_CALL();
138}
139
140/**
141 * @brief Supervisor call interrupt handler.
142 **/
143__attribute__((weak)) void SVC_Handler(void)
144{
145 DEFAULT_IRQ_HANDLER_CALL();
146}
147
148/**
149 * @brief Debug monitor interrupt handler.
150 **/
151__attribute__((weak)) void DebugMon_Handler(void)
152{
153 DEFAULT_IRQ_HANDLER_CALL();
154}
155
156/**
157 * @brief Pending SV call interrupt handler.
158 */
159__attribute__((weak)) void PendSV_Handler(void)
160{
161 DEFAULT_IRQ_HANDLER_CALL();
162}
163
164/**
165 * @brief System tick interrupt handler.
166 **/
167void SysTick_Handler(void)
168{
169 /* Increment the cycle counter based on load value. */
170 cpu_cycle_count += SysTick->LOAD + 1;
171}
172
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100173/**
174 * Gets the current SysTick derived counter value
175 */
alexander3c798932021-03-26 21:42:19 +0000176uint64_t Get_SysTick_Cycle_Count(void)
177{
178 uint32_t systick_val;
179
180 NVIC_DisableIRQ(SysTick_IRQn);
181 systick_val = SysTick->VAL & SysTick_VAL_CURRENT_Msk;
182 NVIC_EnableIRQ(SysTick_IRQn);
183
184 return cpu_cycle_count + (SysTick->LOAD - systick_val);
185}
186
alexander3c798932021-03-26 21:42:19 +0000187/**
188 * Interrupt vector table.
189 */
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100190irq_vec_type __VECTOR_TABLE[] __VECTOR_TABLE_ATTRIBUTE = {
191 (irq_vec_type)(&__INITIAL_SP), /* Initial Stack Pointer */
192 Reset_Handler , /* 1 Initial PC, set to entry point */
alexander3c798932021-03-26 21:42:19 +0000193
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100194 NMI_Handler , /* 2 (-14) NMI Handler */
195 HardFault_Handler , /* 3 (-13) Hard Fault Handler */
196 MemManage_Handler , /* 4 (-12) MPU Fault Handler */
197 BusFault_Handler , /* 5 (-11) Bus Fault Handler */
198 UsageFault_Handler , /* 6 (-10) Usage Fault Handler */
199 SecureFault_Handler, /* 7 ( -9) Secure Fault Handler */
alexander3c798932021-03-26 21:42:19 +0000200 0 , /* 8 ( -8) Reserved */
201 0 , /* 9 ( -7) Reserved */
202 0 , /* 10 ( -6) Reserved */
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100203 SVC_Handler , /* 11 ( -5) SVCall Handler */
204 DebugMon_Handler , /* 12 ( -4) Debug Monitor Handler */
alexander3c798932021-03-26 21:42:19 +0000205 0 , /* 13 ( -3) Reserved */
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100206 PendSV_Handler , /* 14 ( -2) PendSV Handler */
207 SysTick_Handler , /* 15 ( -1) SysTick Handler */
alexander3c798932021-03-26 21:42:19 +0000208
209 /* External sources to be populated by user. */
210 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 16 */
211 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 - 32 */
212 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 32 - 48 */
213 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 48 - 64 */
214 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 64 - 80 */
215 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 96 */
216 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 96 - 112 */
217 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 112 - 128 */
218};
219
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100220/**
221 * SysTick initialisation
222 */
alexander3c798932021-03-26 21:42:19 +0000223int Init_SysTick(void)
224{
225 const uint32_t ticks_10ms = GetSystemCoreClock()/100 + 1;
226 int err = 0;
227
228 /* Reset CPU cycle count value. */
229 cpu_cycle_count = 0;
230
231 /* Changing configuration for sys tick => guard from being
232 * interrupted. */
233 NVIC_DisableIRQ(SysTick_IRQn);
234
235 /* SysTick init - this will enable interrupt too. */
236 err = SysTick_Config(ticks_10ms);
237
238 /* Enable interrupt again. */
239 NVIC_EnableIRQ(SysTick_IRQn);
240
241 return err;
242}
243
244/* Reset handler - starting point of our application. */
245__attribute__((used)) void Reset_Handler(void)
246{
247 /* Initialise system. */
248 SystemInit();
249
250 /* Configure the system tick. */
251 Init_SysTick();
252
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100253 /* cmsis supplied entry point. */
254 __PROGRAM_START();
alexander3c798932021-03-26 21:42:19 +0000255}
256
257#ifdef __cplusplus
258}
259#endif