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