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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
#![crate_name = "sam4l"]
#![crate_type = "rlib"]
#![feature(repr_align, attr_literals, const_cell_new)]
#![feature(const_atomic_usize_new, const_ptr_null_mut, integer_atomics, try_from)]
#![feature(asm, core_intrinsics, concat_idents, const_fn)]
#![no_std]
extern crate cortexm4;
#[allow(unused_imports)]
#[macro_use(debug, static_init, register_bitfields, register_bitmasks)]
extern crate kernel;
#[macro_use]
mod helpers;
pub mod chip;
pub mod ast;
pub mod bpm;
pub mod bscif;
pub mod dma;
pub mod i2c;
pub mod spi;
pub mod nvic;
pub mod pm;
pub mod gpio;
pub mod usart;
pub mod scif;
pub mod adc;
pub mod flashcalw;
pub mod wdt;
pub mod trng;
pub mod crccu;
pub mod dac;
pub mod aes;
pub mod usbc;
use cortexm4::{generic_isr, systick_handler, SVC_Handler};
unsafe extern "C" fn unhandled_interrupt() {
let mut interrupt_number: u32;
asm!(
"mrs r0, ipsr "
: "={r0}"(interrupt_number)
:
: "r0"
:
);
interrupt_number = interrupt_number & 0x1ff;
panic!("Unhandled Interrupt. ISR {} is active.", interrupt_number);
}
extern "C" {
fn _estack();
fn reset_handler();
static mut _szero: u32;
static mut _ezero: u32;
static mut _etext: u32;
static mut _srelocate: u32;
static mut _erelocate: u32;
}
#[link_section=".vectors"]
#[cfg_attr(rustfmt, rustfmt_skip)]
#[no_mangle]
pub static BASE_VECTORS: [unsafe extern fn(); 16] = [
_estack, reset_handler,
unhandled_interrupt,
hard_fault_handler,
unhandled_interrupt,
unhandled_interrupt,
unhandled_interrupt,
unhandled_interrupt, unhandled_interrupt, unhandled_interrupt,
unhandled_interrupt,
SVC_Handler,
unhandled_interrupt,
unhandled_interrupt,
unhandled_interrupt,
systick_handler
];
#[link_section = ".vectors"]
#[no_mangle]
pub static IRQS: [unsafe extern "C" fn(); 80] = [generic_isr; 80];
pub unsafe fn init() {
let mut pdest = &mut _srelocate as *mut u32;
let pend = &mut _erelocate as *mut u32;
let mut psrc = &_etext as *const u32;
if psrc != pdest {
while (pdest as *const u32) < pend {
*pdest = *psrc;
pdest = pdest.offset(1);
psrc = psrc.offset(1);
}
}
let pzero = &_ezero as *const u32;
pdest = &mut _szero as *mut u32;
while (pdest as *const u32) < pzero {
*pdest = 0;
pdest = pdest.offset(1);
}
cortexm4::nvic::disable_all();
cortexm4::nvic::clear_all_pending();
cortexm4::nvic::enable_all();
}
unsafe extern "C" fn hard_fault_handler() {
use core::intrinsics::offset;
let faulting_stack: *mut u32;
let kernel_stack: bool;
asm!(
"mov r1, 0 \n\
tst lr, #4 \n\
itte eq \n\
mrseq r0, msp \n\
addeq r1, 1 \n\
mrsne r0, psp "
: "={r0}"(faulting_stack), "={r1}"(kernel_stack)
:
: "r0", "r1"
:
);
if kernel_stack {
let stacked_r0: u32 = *offset(faulting_stack, 0);
let stacked_r1: u32 = *offset(faulting_stack, 1);
let stacked_r2: u32 = *offset(faulting_stack, 2);
let stacked_r3: u32 = *offset(faulting_stack, 3);
let stacked_r12: u32 = *offset(faulting_stack, 4);
let stacked_lr: u32 = *offset(faulting_stack, 5);
let stacked_pc: u32 = *offset(faulting_stack, 6);
let stacked_xpsr: u32 = *offset(faulting_stack, 7);
let mode_str = "Kernel";
let shcsr: u32 = core::ptr::read_volatile(0xE000ED24 as *const u32);
let cfsr: u32 = core::ptr::read_volatile(0xE000ED28 as *const u32);
let hfsr: u32 = core::ptr::read_volatile(0xE000ED2C as *const u32);
let mmfar: u32 = core::ptr::read_volatile(0xE000ED34 as *const u32);
let bfar: u32 = core::ptr::read_volatile(0xE000ED38 as *const u32);
let iaccviol = (cfsr & 0x01) == 0x01;
let daccviol = (cfsr & 0x02) == 0x02;
let munstkerr = (cfsr & 0x08) == 0x08;
let mstkerr = (cfsr & 0x10) == 0x10;
let mlsperr = (cfsr & 0x20) == 0x20;
let mmfarvalid = (cfsr & 0x80) == 0x80;
let ibuserr = ((cfsr >> 8) & 0x01) == 0x01;
let preciserr = ((cfsr >> 8) & 0x02) == 0x02;
let impreciserr = ((cfsr >> 8) & 0x04) == 0x04;
let unstkerr = ((cfsr >> 8) & 0x08) == 0x08;
let stkerr = ((cfsr >> 8) & 0x10) == 0x10;
let lsperr = ((cfsr >> 8) & 0x20) == 0x20;
let bfarvalid = ((cfsr >> 8) & 0x80) == 0x80;
let undefinstr = ((cfsr >> 16) & 0x01) == 0x01;
let invstate = ((cfsr >> 16) & 0x02) == 0x02;
let invpc = ((cfsr >> 16) & 0x04) == 0x04;
let nocp = ((cfsr >> 16) & 0x08) == 0x08;
let unaligned = ((cfsr >> 16) & 0x100) == 0x100;
let divbysero = ((cfsr >> 16) & 0x200) == 0x200;
let vecttbl = (hfsr & 0x02) == 0x02;
let forced = (hfsr & 0x40000000) == 0x40000000;
let ici_it = (((stacked_xpsr >> 25) & 0x3) << 6) | ((stacked_xpsr >> 10) & 0x3f);
let thumb_bit = ((stacked_xpsr >> 24) & 0x1) == 1;
let exception_number = (stacked_xpsr & 0x1ff) as usize;
panic!(
"{} HardFault.\n\
\tKernel version {}\n\
\tr0 0x{:x}\n\
\tr1 0x{:x}\n\
\tr2 0x{:x}\n\
\tr3 0x{:x}\n\
\tr12 0x{:x}\n\
\tlr 0x{:x}\n\
\tpc 0x{:x}\n\
\tprs 0x{:x} [ N {} Z {} C {} V {} Q {} GE {}{}{}{} ; ICI.IT {} T {} ; Exc {}-{} ]\n\
\tsp 0x{:x}\n\
\ttop of stack 0x{:x}\n\
\tbottom of stack 0x{:x}\n\
\tSHCSR 0x{:x}\n\
\tCFSR 0x{:x}\n\
\tHSFR 0x{:x}\n\
\tInstruction Access Violation: {}\n\
\tData Access Violation: {}\n\
\tMemory Management Unstacking Fault: {}\n\
\tMemory Management Stacking Fault: {}\n\
\tMemory Management Lazy FP Fault: {}\n\
\tInstruction Bus Error: {}\n\
\tPrecise Data Bus Error: {}\n\
\tImprecise Data Bus Error: {}\n\
\tBus Unstacking Fault: {}\n\
\tBus Stacking Fault: {}\n\
\tBus Lazy FP Fault: {}\n\
\tUndefined Instruction Usage Fault: {}\n\
\tInvalid State Usage Fault: {}\n\
\tInvalid PC Load Usage Fault: {}\n\
\tNo Coprocessor Usage Fault: {}\n\
\tUnaligned Access Usage Fault: {}\n\
\tDivide By Zero: {}\n\
\tBus Fault on Vector Table Read: {}\n\
\tForced Hard Fault: {}\n\
\tFaulting Memory Address: (valid: {}) {:#010X}\n\
\tBus Fault Address: (valid: {}) {:#010X}\n\
",
mode_str,
env!("TOCK_KERNEL_VERSION"),
stacked_r0,
stacked_r1,
stacked_r2,
stacked_r3,
stacked_r12,
stacked_lr,
stacked_pc,
stacked_xpsr,
(stacked_xpsr >> 31) & 0x1,
(stacked_xpsr >> 30) & 0x1,
(stacked_xpsr >> 29) & 0x1,
(stacked_xpsr >> 28) & 0x1,
(stacked_xpsr >> 27) & 0x1,
(stacked_xpsr >> 19) & 0x1,
(stacked_xpsr >> 18) & 0x1,
(stacked_xpsr >> 17) & 0x1,
(stacked_xpsr >> 16) & 0x1,
ici_it,
thumb_bit,
exception_number,
kernel::process::ipsr_isr_number_to_str(exception_number),
faulting_stack as u32,
(_estack as *const ()) as u32,
(&_ezero as *const u32) as u32,
shcsr,
cfsr,
hfsr,
iaccviol,
daccviol,
munstkerr,
mstkerr,
mlsperr,
ibuserr,
preciserr,
impreciserr,
unstkerr,
stkerr,
lsperr,
undefinstr,
invstate,
invpc,
nocp,
unaligned,
divbysero,
vecttbl,
forced,
mmfarvalid,
mmfar,
bfarvalid,
bfar
);
} else {
asm!(
"ldr r0, =SYSCALL_FIRED
mov r1, #1
str r1, [r0, #0]
ldr r0, =APP_FAULT
str r1, [r0, #0]
/* Read the SCB registers. */
ldr r0, =SCB_REGISTERS
ldr r1, =0xE000ED14
ldr r2, [r1, #0] /* CCR */
str r2, [r0, #0]
ldr r2, [r1, #20] /* CFSR */
str r2, [r0, #4]
ldr r2, [r1, #24] /* HFSR */
str r2, [r0, #8]
ldr r2, [r1, #32] /* MMFAR */
str r2, [r0, #12]
ldr r2, [r1, #36] /* BFAR */
str r2, [r0, #16]
/* Set thread mode to privileged */
mov r0, #0
msr CONTROL, r0
movw LR, #0xFFF9
movt LR, #0xFFFF"
);
}
}