-
Notifications
You must be signed in to change notification settings - Fork 2k
/
cortexm_init.c
135 lines (115 loc) · 3.97 KB
/
cortexm_init.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
* Copyright (C) 2015 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_cortexm_common
* @{
*
* @file
* @brief Cortex-M specific configuration and initialization options
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include "cpu.h"
/**
* Interrupt vector base address, defined by the linker
*/
extern const void *_isr_vectors;
#if defined(CPU_CORTEXM_INIT_SUBFUNCTIONS)
#define CORTEXM_STATIC_INLINE /*empty*/
#else
#define CORTEXM_STATIC_INLINE static inline
#endif
CORTEXM_STATIC_INLINE void cortexm_init_isr_priorities(void)
{
#if CPU_CORTEXM_PRIORITY_GROUPING != 0
/* If defined, initialise priority subgrouping, see cpu_conf_common.h */
NVIC_SetPriorityGrouping(CPU_CORTEXM_PRIORITY_GROUPING);
#endif
/* initialize the interrupt priorities */
/* set pendSV interrupt to its own priority */
NVIC_SetPriority(PendSV_IRQn, CPU_CORTEXM_PENDSV_IRQ_PRIO);
/* set SVC interrupt to same priority as the rest */
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32L0) || \
defined(CPU_FAM_STM32L1) || defined(CPU_FAM_STM32G0)
NVIC_SetPriority(SVC_IRQn, CPU_DEFAULT_IRQ_PRIO);
#else
NVIC_SetPriority(SVCall_IRQn, CPU_DEFAULT_IRQ_PRIO);
#endif
/* initialize all vendor specific interrupts with the same value */
for (unsigned i = 0; i < CPU_IRQ_NUMOF; i++) {
NVIC_SetPriority((IRQn_Type) i, CPU_DEFAULT_IRQ_PRIO);
}
}
CORTEXM_STATIC_INLINE void cortexm_init_misc(void)
{
/* enable wake up on events for __WFE CPU sleep */
SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
/* for Cortex-M3 r1p0 and up the STKALIGN option was added, but not automatically
* enabled until revision r2p0. For 64bit function arguments to work properly this
* needs to be enabled.
*/
#ifdef SCB_CCR_STKALIGN_Msk
SCB->CCR |= SCB_CCR_STKALIGN_Msk;
#endif
}
void cortexm_init(void)
{
/* configure the vector table location to internal flash */
#if defined(CPU_CORE_CORTEX_M3) || defined(CPU_CORE_CORTEX_M33) || \
defined(CPU_CORE_CORTEX_M4) || defined(CPU_CORE_CORTEX_M4F) || \
defined(CPU_CORE_CORTEX_M7) || \
(defined(CPU_CORE_CORTEX_M0PLUS) || defined(CPU_CORE_CORTEX_M23) \
&& (__VTOR_PRESENT == 1))
SCB->VTOR = (uint32_t)&_isr_vectors;
#endif
cortexm_init_isr_priorities();
cortexm_init_misc();
}
bool cpu_check_address(volatile const char *address)
{
#if defined(CPU_CORE_CORTEX_M3) || defined(CPU_CORE_CORTEX_M33) || \
defined(CPU_CORE_CORTEX_M4) || defined(CPU_CORE_CORTEX_M4F) || \
defined(CPU_CORE_CORTEX_M7)
static const uint32_t BFARVALID_MASK = (0x80 << SCB_CFSR_BUSFAULTSR_Pos);
bool is_valid = true;
/* Clear BFARVALID flag */
SCB->CFSR |= BFARVALID_MASK;
/* Ignore BusFault by enabling BFHFNMIGN and disabling interrupts */
uint32_t mask = __get_FAULTMASK();
__disable_fault_irq();
SCB->CCR |= SCB_CCR_BFHFNMIGN_Msk;
*address;
/* Check BFARVALID flag */
if ((SCB->CFSR & BFARVALID_MASK) != 0) {
/* Bus Fault occurred reading the address */
is_valid = false;
}
/* Re-enable BusFault by clearing BFHFNMIGN */
SCB->CCR &= ~SCB_CCR_BFHFNMIGN_Msk;
__set_FAULTMASK(mask);
return is_valid;
#else
/* Cortex-M0 doesn't have BusFault so we need to catch HardFault */
(void)address;
bool result;
__asm__ volatile (
"movs r5, #1 \n" /* R5 will be set to 0 by HardFault handler */
/* to indicate HardFault has occurred */
"ldr r1, =0xDEADF00D \n" /* set magic number */
"ldr r2, =0xCAFEBABE \n" /* 2nd magic to be sure */
"ldrb r3, %1 \n" /* probe address */
"mov %0, r5 \n" /* store result */
: "=r"(result)
: "m"(*address)
: "r1", "r2", "r3", "r5", "cc"
);
return result;
#endif
}