1#![no_std]
8
9use core::fmt::Write;
10
11pub mod dcb;
12pub mod dwt;
13pub mod mpu;
14pub mod nvic;
15pub mod scb;
16pub mod support;
17pub mod syscall;
18pub mod systick;
19
20extern "C" {
22 static _szero: *const u32;
23 static _ezero: *const u32;
24 static _etext: *const u32;
25 static _srelocate: *const u32;
26 static _erelocate: *const u32;
27}
28
29pub trait CortexMVariant {
74 const GENERIC_ISR: unsafe extern "C" fn();
84
85 const SYSTICK_HANDLER: unsafe extern "C" fn();
92
93 const SVC_HANDLER: unsafe extern "C" fn();
96
97 const HARD_FAULT_HANDLER: unsafe extern "C" fn();
99
100 unsafe fn switch_to_user(
104 user_stack: *const usize,
105 process_regs: &mut [usize; 8],
106 ) -> *const usize;
107
108 unsafe fn print_cortexm_state(writer: &mut dyn Write);
112}
113
114#[cfg(any(doc, all(target_arch = "arm", target_os = "none")))]
115pub unsafe extern "C" fn unhandled_interrupt() {
116 use core::arch::asm;
117 let mut interrupt_number: u32;
118
119 asm!(
121 "
122 mrs r0, ipsr
123 ",
124 out("r0") interrupt_number,
125 options(nomem, nostack, preserves_flags),
126 );
127
128 interrupt_number &= 0x1ff;
129
130 panic!("Unhandled Interrupt. ISR {} is active.", interrupt_number);
131}
132
133#[cfg(any(doc, all(target_arch = "arm", target_os = "none")))]
140#[unsafe(naked)]
141pub unsafe extern "C" fn initialize_ram_jump_to_main() {
142 use core::arch::naked_asm;
143 naked_asm!(
144 "
145 // Start by initializing .bss memory. The Tock linker script defines
146 // `_szero` and `_ezero` to mark the .bss segment.
147 ldr r0, ={sbss} // r0 = first address of .bss
148 ldr r1, ={ebss} // r1 = first address after .bss
149
150 movs r2, #0 // r2 = 0
151
152100: // bss_init_loop
153 cmp r1, r0 // We increment r0. Check if we have reached r1
154 // (end of .bss), and stop if so.
155 beq 101f // If r0 == r1, we are done.
156 stm r0!, {{r2}} // Write a word to the address in r0, and increment r0.
157 // Since r2 contains zero, this will clear the memory
158 // pointed to by r0. Using `stm` (store multiple) with the
159 // bang allows us to also increment r0 automatically.
160 b 100b // Continue the loop.
161
162101: // bss_init_done
163
164 // Now initialize .data memory. This involves coping the values right at the
165 // end of the .text section (in flash) into the .data section (in RAM).
166 ldr r0, ={sdata} // r0 = first address of data section in RAM
167 ldr r1, ={edata} // r1 = first address after data section in RAM
168 ldr r2, ={etext} // r2 = address of stored data initial values
169
170200: // data_init_loop
171 cmp r1, r0 // We increment r0. Check if we have reached the end
172 // of the data section, and if so we are done.
173 beq 201f // r0 == r1, and we have iterated through the .data section
174 ldm r2!, {{r3}} // r3 = *(r2), r2 += 1. Load the initial value into r3,
175 // and use the bang to increment r2.
176 stm r0!, {{r3}} // *(r0) = r3, r0 += 1. Store the value to memory, and
177 // increment r0.
178 b 200b // Continue the loop.
179
180201: // data_init_done
181
182 // Now that memory has been initialized, we can jump to main() where the
183 // board initialization takes place and Rust code starts.
184 bl main
185 ",
186 sbss = sym _szero,
187 ebss = sym _ezero,
188 sdata = sym _srelocate,
189 edata = sym _erelocate,
190 etext = sym _etext,
191 );
192}
193
194pub unsafe fn print_cortexm_state(writer: &mut dyn Write) {
195 let _ccr = syscall::SCB_REGISTERS[0];
196 let cfsr = syscall::SCB_REGISTERS[1];
197 let hfsr = syscall::SCB_REGISTERS[2];
198 let mmfar = syscall::SCB_REGISTERS[3];
199 let bfar = syscall::SCB_REGISTERS[4];
200
201 let iaccviol = (cfsr & 0x01) == 0x01;
202 let daccviol = (cfsr & 0x02) == 0x02;
203 let munstkerr = (cfsr & 0x08) == 0x08;
204 let mstkerr = (cfsr & 0x10) == 0x10;
205 let mlsperr = (cfsr & 0x20) == 0x20;
206 let mmfarvalid = (cfsr & 0x80) == 0x80;
207
208 let ibuserr = ((cfsr >> 8) & 0x01) == 0x01;
209 let preciserr = ((cfsr >> 8) & 0x02) == 0x02;
210 let impreciserr = ((cfsr >> 8) & 0x04) == 0x04;
211 let unstkerr = ((cfsr >> 8) & 0x08) == 0x08;
212 let stkerr = ((cfsr >> 8) & 0x10) == 0x10;
213 let lsperr = ((cfsr >> 8) & 0x20) == 0x20;
214 let bfarvalid = ((cfsr >> 8) & 0x80) == 0x80;
215
216 let undefinstr = ((cfsr >> 16) & 0x01) == 0x01;
217 let invstate = ((cfsr >> 16) & 0x02) == 0x02;
218 let invpc = ((cfsr >> 16) & 0x04) == 0x04;
219 let nocp = ((cfsr >> 16) & 0x08) == 0x08;
220 let unaligned = ((cfsr >> 16) & 0x100) == 0x100;
221 let divbyzero = ((cfsr >> 16) & 0x200) == 0x200;
222
223 let vecttbl = (hfsr & 0x02) == 0x02;
224 let forced = (hfsr & 0x40000000) == 0x40000000;
225
226 let _ = writer.write_fmt(format_args!("\r\n---| Cortex-M Fault Status |---\r\n"));
227
228 if iaccviol {
229 let _ = writer.write_fmt(format_args!(
230 "Instruction Access Violation: {}\r\n",
231 iaccviol
232 ));
233 }
234 if daccviol {
235 let _ = writer.write_fmt(format_args!(
236 "Data Access Violation: {}\r\n",
237 daccviol
238 ));
239 }
240 if munstkerr {
241 let _ = writer.write_fmt(format_args!(
242 "Memory Management Unstacking Fault: {}\r\n",
243 munstkerr
244 ));
245 }
246 if mstkerr {
247 let _ = writer.write_fmt(format_args!(
248 "Memory Management Stacking Fault: {}\r\n",
249 mstkerr
250 ));
251 }
252 if mlsperr {
253 let _ = writer.write_fmt(format_args!(
254 "Memory Management Lazy FP Fault: {}\r\n",
255 mlsperr
256 ));
257 }
258
259 if ibuserr {
260 let _ = writer.write_fmt(format_args!(
261 "Instruction Bus Error: {}\r\n",
262 ibuserr
263 ));
264 }
265 if preciserr {
266 let _ = writer.write_fmt(format_args!(
267 "Precise Data Bus Error: {}\r\n",
268 preciserr
269 ));
270 }
271 if impreciserr {
272 let _ = writer.write_fmt(format_args!(
273 "Imprecise Data Bus Error: {}\r\n",
274 impreciserr
275 ));
276 }
277 if unstkerr {
278 let _ = writer.write_fmt(format_args!(
279 "Bus Unstacking Fault: {}\r\n",
280 unstkerr
281 ));
282 }
283 if stkerr {
284 let _ = writer.write_fmt(format_args!(
285 "Bus Stacking Fault: {}\r\n",
286 stkerr
287 ));
288 }
289 if lsperr {
290 let _ = writer.write_fmt(format_args!(
291 "Bus Lazy FP Fault: {}\r\n",
292 lsperr
293 ));
294 }
295 if undefinstr {
296 let _ = writer.write_fmt(format_args!(
297 "Undefined Instruction Usage Fault: {}\r\n",
298 undefinstr
299 ));
300 }
301 if invstate {
302 let _ = writer.write_fmt(format_args!(
303 "Invalid State Usage Fault: {}\r\n",
304 invstate
305 ));
306 }
307 if invpc {
308 let _ = writer.write_fmt(format_args!(
309 "Invalid PC Load Usage Fault: {}\r\n",
310 invpc
311 ));
312 }
313 if nocp {
314 let _ = writer.write_fmt(format_args!(
315 "No Coprocessor Usage Fault: {}\r\n",
316 nocp
317 ));
318 }
319 if unaligned {
320 let _ = writer.write_fmt(format_args!(
321 "Unaligned Access Usage Fault: {}\r\n",
322 unaligned
323 ));
324 }
325 if divbyzero {
326 let _ = writer.write_fmt(format_args!(
327 "Divide By Zero: {}\r\n",
328 divbyzero
329 ));
330 }
331
332 if vecttbl {
333 let _ = writer.write_fmt(format_args!(
334 "Bus Fault on Vector Table Read: {}\r\n",
335 vecttbl
336 ));
337 }
338 if forced {
339 let _ = writer.write_fmt(format_args!(
340 "Forced Hard Fault: {}\r\n",
341 forced
342 ));
343 }
344
345 if mmfarvalid {
346 let _ = writer.write_fmt(format_args!(
347 "Faulting Memory Address: {:#010X}\r\n",
348 mmfar
349 ));
350 }
351 if bfarvalid {
352 let _ = writer.write_fmt(format_args!(
353 "Bus Fault Address: {:#010X}\r\n",
354 bfar
355 ));
356 }
357
358 if cfsr == 0 && hfsr == 0 {
359 let _ = writer.write_fmt(format_args!("No Cortex-M faults detected.\r\n"));
360 } else {
361 let _ = writer.write_fmt(format_args!(
362 "Fault Status Register (CFSR): {:#010X}\r\n",
363 cfsr
364 ));
365 let _ = writer.write_fmt(format_args!(
366 "Hard Fault Status Register (HFSR): {:#010X}\r\n",
367 hfsr
368 ));
369 }
370}
371
372#[cfg(not(any(doc, all(target_arch = "arm", target_os = "none"))))]
380pub unsafe extern "C" fn unhandled_interrupt() {
381 unimplemented!()
382}
383
384#[cfg(not(any(doc, all(target_arch = "arm", target_os = "none"))))]
385pub unsafe extern "C" fn initialize_ram_jump_to_main() {
386 unimplemented!()
387}