apollo3/
lib.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Peripheral implementations for the Apollo3 MCU.
6
7#![no_std]
8
9// Peripherals
10pub mod ble;
11pub mod cachectrl;
12pub mod chip;
13pub mod clkgen;
14pub mod flashctrl;
15pub mod gpio;
16pub mod iom;
17pub mod ios;
18pub mod mcuctrl;
19pub mod nvic;
20pub mod pwrctrl;
21pub mod stimer;
22pub mod uart;
23
24use cortexm4f::{initialize_ram_jump_to_main, scb, unhandled_interrupt, CortexM4F, CortexMVariant};
25
26extern "C" {
27    // _estack is not really a function, but it makes the types work
28    // You should never actually invoke it!!
29    fn _estack();
30}
31
32#[cfg_attr(
33    all(target_arch = "arm", target_os = "none"),
34    link_section = ".vectors"
35)]
36// used Ensures that the symbol is kept until the final binary
37#[cfg_attr(all(target_arch = "arm", target_os = "none"), used)]
38pub static BASE_VECTORS: [unsafe extern "C" fn(); 16] = [
39    _estack,
40    initialize_ram_jump_to_main,
41    unhandled_interrupt,           // NMI
42    CortexM4F::HARD_FAULT_HANDLER, // Hard Fault
43    unhandled_interrupt,           // MemManage
44    unhandled_interrupt,           // BusFault
45    unhandled_interrupt,           // UsageFault
46    unhandled_interrupt,
47    unhandled_interrupt,
48    unhandled_interrupt,
49    unhandled_interrupt,
50    CortexM4F::SVC_HANDLER, // SVC
51    unhandled_interrupt,    // DebugMon
52    unhandled_interrupt,
53    unhandled_interrupt,        // PendSV
54    CortexM4F::SYSTICK_HANDLER, // SysTick
55];
56
57#[cfg_attr(
58    all(target_arch = "arm", target_os = "none"),
59    link_section = ".vectors"
60)]
61// used Ensures that the symbol is kept until the final binary
62#[cfg_attr(all(target_arch = "arm", target_os = "none"), used)]
63pub static IRQS: [unsafe extern "C" fn(); 32] = [CortexM4F::GENERIC_ISR; 32];
64
65// The Patch table.
66//
67// The patch table should pad the vector table size to a total of 64 entries
68// (16 core + 48 periph) such that code begins at offset 0x100.
69#[cfg_attr(
70    all(target_arch = "arm", target_os = "none"),
71    link_section = ".vectors"
72)]
73// used Ensures that the symbol is kept until the final binary
74#[cfg_attr(all(target_arch = "arm", target_os = "none"), used)]
75pub static PATCH: [unsafe extern "C" fn(); 16] = [unhandled_interrupt; 16];
76
77// The SVC call in this function means that we need to ensure it's inlined in
78// `main()` otherwise we end up with a clobbered stack.
79#[cfg(any(doc, all(target_arch = "arm", target_os = "none")))]
80#[inline(always)]
81pub unsafe fn init() {
82    use core::arch::asm;
83    let cache_ctrl = crate::cachectrl::CacheCtrl::new();
84    cache_ctrl.enable_cache();
85
86    // Explicitly tell the core where Tock's vector table is located. If Tock is the
87    // only thing on the chip then this is effectively a no-op. If, however, there is
88    // a bootloader present then we want to ensure that the vector table is set
89    // correctly for Tock. The bootloader _may_ set this for us, but it may not
90    // so that any errors early in the Tock boot process trap back to the bootloader.
91    // To be safe we unconditionally set the vector table.
92    scb::set_vector_table_offset(BASE_VECTORS.as_ptr() as *const ());
93
94    // Disable the FPU (it might be enalbed by a prior stage)
95    scb::disable_fpca();
96
97    // This ensures the FPU is actually disabled
98    asm!("svc 0xff", out("r0") _, out("r1") _, out("r2") _, out("r3") _, out("r12") _);
99
100    cortexm4f::nvic::disable_all();
101    cortexm4f::nvic::clear_all_pending();
102    cortexm4f::nvic::enable_all();
103}
104
105// Mock implementation for tests
106#[cfg(not(any(doc, all(target_arch = "arm", target_os = "none"))))]
107pub unsafe fn init() {
108    // Prevent unused code warning.
109    scb::disable_fpca();
110
111    unimplemented!()
112}