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