blob: c6f54b112eb1b39a7362ee376b632c46da3f0da0 [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>
26
27static uint64_t cpu_cycle_count = 0;
28
29/**
30 * @brief Dump core registers on stdout
31 */
32static void LogCoreCPURegisters(void)
33{
34 printf("CTRL : 0x%08x\n", __get_CONTROL());
35 printf("IPSR : 0x%08x\n", __get_IPSR());
36 printf("APSR : 0x%08x\n", __get_APSR());
37 printf("xPSR : 0x%08x\n", __get_xPSR());
38 printf("PSP : 0x%08x\n", __get_PSP());
39 printf("MSP : 0x%08x\n", __get_MSP());
40 printf("PRIMASK : 0x%08x\n", __get_PRIMASK());
41 printf("BASEPRI : 0x%08x\n", __get_BASEPRI());
42 printf("FAULTMSK: 0x%08x\n", __get_FAULTMASK());
43 printf("PC : 0x%08x\n", __current_pc());
44}
45
46/**
47 * @brief Default interrupt handler - an infinite loop.
48 **/
49__attribute__((noreturn)) static void DefaultHandler(void)
50{
51 LogCoreCPURegisters();
52 while (1) {
53 /* Without the following line, armclang may optimize away the
54 * infinite loop because it'd be without side effects and thus
55 * undefined behaviour. */
56 __ASM volatile("");
57 }
58}
59
60#define DEFAULT_HANDLER_CALL(type) \
61 do { \
62 printf("\n%s caught by function %s\n", \
63 type, __FUNCTION__); \
64 DefaultHandler(); \
65 } while (0)
66
67#define DEFAULT_ERROR_HANDLER_CALL() \
68 DEFAULT_HANDLER_CALL("Exception")
69
70#define DEFAULT_IRQ_HANDLER_CALL() \
71 DEFAULT_HANDLER_CALL("Interrupt")
72
73/**
74 * Dummy Exception Handlers for core interrupts.
75 *
76 * Weak definitions provided to be used if the user chooses not
77 * to override them.
78 **/
79
80/**
81 * @brief Non maskable interrupt handler.
82 **/
83 __attribute__((weak)) void NMI_Handler(void)
84{
85 DEFAULT_ERROR_HANDLER_CALL();
86}
87
88/**
89 * @brief Hardfault interrupt handler.
90 **/
91 __attribute__((weak)) void HardFault_Handler(void)
92{
93 DEFAULT_ERROR_HANDLER_CALL();
94}
95
96/**
97 * @brief Memory management interrupt handler.
98 **/
99__attribute__((weak)) void MemManage_Handler(void)
100{
101 DEFAULT_IRQ_HANDLER_CALL();
102}
103
104/**
105 * @brief Bus fault interrupt handler.
106 **/
107__attribute__((weak)) void BusFault_Handler(void)
108{
109 DEFAULT_ERROR_HANDLER_CALL();
110}
111
112/**
113 * @brief Usage fault interrupt handler.
114 **/
115__attribute__((weak)) void UsageFault_Handler(void)
116{
117 DEFAULT_ERROR_HANDLER_CALL();
118}
119
120/**
121 * @brief Secure access fault interrupt handler.
122 **/
123__attribute__((weak)) void SecureFault_Handler(void)
124{
125 DEFAULT_ERROR_HANDLER_CALL();
126}
127
128/**
129 * @brief Supervisor call interrupt handler.
130 **/
131__attribute__((weak)) void SVC_Handler(void)
132{
133 DEFAULT_IRQ_HANDLER_CALL();
134}
135
136/**
137 * @brief Debug monitor interrupt handler.
138 **/
139__attribute__((weak)) void DebugMon_Handler(void)
140{
141 DEFAULT_IRQ_HANDLER_CALL();
142}
143
144/**
145 * @brief Pending SV call interrupt handler.
146 */
147__attribute__((weak)) void PendSV_Handler(void)
148{
149 DEFAULT_IRQ_HANDLER_CALL();
150}
151
152/**
153 * @brief System tick interrupt handler.
154 **/
155void SysTick_Handler(void)
156{
157 /* Increment the cycle counter based on load value. */
158 cpu_cycle_count += SysTick->LOAD + 1;
159}
160
161uint64_t Get_SysTick_Cycle_Count(void)
162{
163 uint32_t systick_val;
164
165 NVIC_DisableIRQ(SysTick_IRQn);
166 systick_val = SysTick->VAL & SysTick_VAL_CURRENT_Msk;
167 NVIC_EnableIRQ(SysTick_IRQn);
168
169 return cpu_cycle_count + (SysTick->LOAD - systick_val);
170}
171
172
173/**
174 * These symbols are provided by the ARM lib - needs the stack and heap
175 * regions in the scatter file.
176 */
177extern void Image$$ARM_LIB_STACK$$ZI$$Base();
178extern void Image$$ARM_LIB_STACK$$ZI$$Limit();
179extern void Image$$ARM_LIB_HEAP$$ZI$$Base();
180extern void Image$$ARM_LIB_HEAP$$ZI$$Limit();
181extern __attribute__((noreturn)) void __main();
182
183__attribute__((naked, used)) void __user_setup_stackheap()
184{
185 __ASM volatile("LDR r0, =Image$$ARM_LIB_HEAP$$ZI$$Base");
186 __ASM volatile("LDR r1, =Image$$ARM_LIB_STACK$$ZI$$Limit");
187 __ASM volatile("LDR r2, =Image$$ARM_LIB_HEAP$$ZI$$Limit");
188 __ASM volatile("LDR r3, =Image$$ARM_LIB_STACK$$ZI$$Base");
189 __ASM volatile("bx lr");
190}
191
192/**
193 * Interrupt vector table.
194 */
195irq_vec_type __Vectors[] __attribute__((section("RESET"), used)) = {
196 &Image$$ARM_LIB_STACK$$ZI$$Limit, /* 0 Initial SP */
197 &Reset_Handler , /* 1 Initial PC, set to entry point */
198
199 &NMI_Handler , /* 2 (-14) NMI Handler */
200 &HardFault_Handler , /* 3 (-13) Hard Fault Handler */
201 &MemManage_Handler , /* 4 (-12) MPU Fault Handler */
202 &BusFault_Handler , /* 5 (-11) Bus Fault Handler */
203 &UsageFault_Handler , /* 6 (-10) Usage Fault Handler */
204 &SecureFault_Handler, /* 7 ( -9) Secure Fault Handler */
205 0 , /* 8 ( -8) Reserved */
206 0 , /* 9 ( -7) Reserved */
207 0 , /* 10 ( -6) Reserved */
208 &SVC_Handler , /* 11 ( -5) SVCall Handler */
209 &DebugMon_Handler , /* 12 ( -4) Debug Monitor Handler */
210 0 , /* 13 ( -3) Reserved */
211 &PendSV_Handler , /* 14 ( -2) PendSV Handler */
212 &SysTick_Handler , /* 15 ( -1) SysTick Handler */
213
214 /* External sources to be populated by user. */
215 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 16 */
216 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 - 32 */
217 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 32 - 48 */
218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 48 - 64 */
219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 64 - 80 */
220 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 96 */
221 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 96 - 112 */
222 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 112 - 128 */
223};
224
225int Init_SysTick(void)
226{
227 const uint32_t ticks_10ms = GetSystemCoreClock()/100 + 1;
228 int err = 0;
229
230 /* Reset CPU cycle count value. */
231 cpu_cycle_count = 0;
232
233 /* Changing configuration for sys tick => guard from being
234 * interrupted. */
235 NVIC_DisableIRQ(SysTick_IRQn);
236
237 /* SysTick init - this will enable interrupt too. */
238 err = SysTick_Config(ticks_10ms);
239
240 /* Enable interrupt again. */
241 NVIC_EnableIRQ(SysTick_IRQn);
242
243 return err;
244}
245
246/* Reset handler - starting point of our application. */
247__attribute__((used)) void Reset_Handler(void)
248{
249 /* Initialise system. */
250 SystemInit();
251
252 /* Configure the system tick. */
253 Init_SysTick();
254
255 /* libcxx supplied entry point. */
256 __main();
257}
258
259#ifdef __cplusplus
260}
261#endif