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