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