#![no_std]
#![allow(static_mut_refs)]
pub extern crate lpc55_pac as raw;
pub mod prelude;
pub mod macros;
pub mod time;
pub mod traits;
pub mod typestates;
use core::ptr::copy_nonoverlapping;
pub use typestates::init_state::Enabled;
pub mod peripherals;
pub use peripherals::{
adc::Adc, anactrl::Anactrl, casper::Casper, ctimer::Ctimers, dma::Dma, flash::Flash,
flexcomm::Flexcomm, gint::Gint, gpio::Gpio, hashcrypt::Hashcrypt, inputmux::InputMux,
iocon::Iocon, pfr::Pfr, pint::Pint, pmc::Pmc, prince::Prince, puf::Puf, rng::Rng, rtc::Rtc,
syscon::Syscon, usbfs::Usbfs, usbhs::Usbhs, utick::Utick,
};
pub mod drivers;
pub use drivers::{ClockRequirements, FlashGordon, I2cMaster, Pin, Pins, SpiMaster, UsbBus};
pub fn new() -> Peripherals {
take().unwrap()
}
pub fn take() -> Option<Peripherals> {
Some(Peripherals::from((
raw::Peripherals::take()?, raw::CorePeripherals::take()?, )))
}
#[allow(non_snake_case)]
pub struct Peripherals {
pub adc: Adc,
pub anactrl: Anactrl,
pub casper: Casper,
pub ctimer: Ctimers,
pub dma: Dma,
pub flash: Flash,
pub flexcomm: Flexcomm,
pub gint: Gint,
pub gpio: Gpio,
pub hashcrypt: Hashcrypt,
pub inputmux: InputMux,
pub iocon: Iocon,
pub pint: Pint,
pub pfr: Pfr,
pub pmc: Pmc,
pub prince: Prince,
pub puf: Puf,
pub rng: Rng,
pub rtc: Rtc,
pub syscon: Syscon,
pub usbfs: Usbfs,
pub usbhs: Usbhs,
pub utick: Utick,
pub CRC_ENGINE: raw::CRC_ENGINE,
pub FLASH_CMPA: raw::FLASH_CMPA,
pub FLASH_CFPA0: raw::FLASH_CFPA0,
pub SCT0: raw::SCT0,
pub SAU: raw::SAU,
pub AHB_SECURE_CTRL: raw::AHB_SECURE_CTRL,
pub CPUID: raw::CPUID,
pub DCB: raw::DCB,
pub DWT: raw::DWT,
pub MPU: raw::MPU,
pub NVIC: raw::NVIC,
pub SCB: raw::SCB,
pub wwdt: raw::WWDT,
pub SYST: raw::SYST,
}
impl From<(raw::Peripherals, raw::CorePeripherals)> for Peripherals {
fn from(raw: (raw::Peripherals, raw::CorePeripherals)) -> Self {
let cp = raw.1;
let p = raw.0;
Peripherals {
adc: Adc::from(p.ADC0),
anactrl: Anactrl::from(p.ANACTRL),
casper: Casper::from(p.CASPER),
ctimer: (
peripherals::ctimer::Ctimer0::from(p.CTIMER0),
peripherals::ctimer::Ctimer1::from(p.CTIMER1),
peripherals::ctimer::Ctimer2::from(p.CTIMER2),
peripherals::ctimer::Ctimer3::from(p.CTIMER3),
peripherals::ctimer::Ctimer4::from(p.CTIMER4),
),
dma: Dma::from(p.DMA0),
flash: Flash::from(p.FLASH),
flexcomm: (
peripherals::flexcomm::Flexcomm0::from((
p.FLEXCOMM0,
p.I2C0,
p.I2S0,
p.SPI0,
p.USART0,
)),
peripherals::flexcomm::Flexcomm1::from((
p.FLEXCOMM1,
p.I2C1,
p.I2S1,
p.SPI1,
p.USART1,
)),
peripherals::flexcomm::Flexcomm2::from((
p.FLEXCOMM2,
p.I2C2,
p.I2S2,
p.SPI2,
p.USART2,
)),
peripherals::flexcomm::Flexcomm3::from((
p.FLEXCOMM3,
p.I2C3,
p.I2S3,
p.SPI3,
p.USART3,
)),
peripherals::flexcomm::Flexcomm4::from((
p.FLEXCOMM4,
p.I2C4,
p.I2S4,
p.SPI4,
p.USART4,
)),
peripherals::flexcomm::Flexcomm5::from((
p.FLEXCOMM5,
p.I2C5,
p.I2S5,
p.SPI5,
p.USART5,
)),
peripherals::flexcomm::Flexcomm6::from((
p.FLEXCOMM6,
p.I2C6,
p.I2S6,
p.SPI6,
p.USART6,
)),
peripherals::flexcomm::Flexcomm7::from((
p.FLEXCOMM7,
p.I2C7,
p.I2S7,
p.SPI7,
p.USART7,
)),
peripherals::flexcomm::Flexcomm8::from((p.FLEXCOMM8, p.SPI8)),
),
gint: Gint::from((p.GINT0, p.GINT1)),
gpio: Gpio::from(p.GPIO),
hashcrypt: Hashcrypt::from(p.HASHCRYPT),
inputmux: InputMux::from(p.INPUTMUX),
iocon: Iocon::from(p.IOCON),
pint: Pint::from(p.PINT),
pfr: Pfr::new(),
pmc: Pmc::from(p.PMC),
prince: Prince::from(p.PRINCE),
puf: Puf::from(p.PUF),
rng: Rng::from(p.RNG),
rtc: Rtc::from(p.RTC),
syscon: Syscon::from(p.SYSCON),
usbfs: Usbfs::from((p.USB0, p.USBFSH)),
usbhs: Usbhs::from((p.USBPHY, p.USB1, p.USBHSH)),
utick: Utick::from(p.UTICK0),
AHB_SECURE_CTRL: p.AHB_SECURE_CTRL,
CRC_ENGINE: p.CRC_ENGINE,
FLASH_CMPA: p.FLASH_CMPA,
FLASH_CFPA0: p.FLASH_CFPA0,
SAU: p.SAU,
SCT0: p.SCT0,
wwdt: p.WWDT,
CPUID: cp.CPUID,
DCB: cp.DCB,
DWT: cp.DWT,
MPU: cp.MPU,
NVIC: cp.NVIC,
SCB: cp.SCB,
SYST: cp.SYST,
}
}
}
impl Peripherals {
pub fn take() -> Option<Self> {
Some(Self::from((
raw::Peripherals::take()?,
raw::CorePeripherals::take()?,
)))
}
pub unsafe fn steal() -> Self {
Self::from((raw::Peripherals::steal(), raw::CorePeripherals::steal()))
}
}
pub fn enable_cycle_counter() {
unsafe { &mut raw::CorePeripherals::steal().DWT }.enable_cycle_counter();
}
pub fn get_cycle_count() -> u32 {
raw::DWT::cycle_count()
}
pub fn count_cycles<Output>(f: impl FnOnce() -> Output) -> (u32, Output) {
let before = get_cycle_count();
let outcome = f();
let after = get_cycle_count();
(after - before, outcome)
}
pub fn wait_at_least(delay_usecs: u32) {
enable_cycle_counter();
let max_cpu_speed = 150_000_000; let period = max_cpu_speed / 1_000_000;
let current = get_cycle_count() as u64;
let mut target = current + period as u64 * delay_usecs as u64;
if target > 0xFFFF_FFFF {
target -= 0xFFFF_FFFF;
while target < get_cycle_count() as u64 {
continue;
}
}
while target > get_cycle_count() as u64 {
continue;
}
}
pub fn chip_revision() -> &'static str {
const DIEID: *const u8 = 0x5000_0FFC as _;
let rev_id: u8 = 0xFu8 & unsafe { core::ptr::read_volatile(DIEID) };
match rev_id {
0 => "0A",
1 => "1B",
_ => "unknown",
}
}
pub fn uuid() -> [u8; 16] {
const UUID: *const u8 = 0x0009_FC70 as _;
let mut uuid: [u8; 16] = [0; 16];
unsafe {
copy_nonoverlapping(UUID, uuid.as_mut_ptr(), 16);
}
uuid
}
pub fn boot_to_bootrom() -> ! {
cortex_m::interrupt::disable();
let core_peripherals = unsafe { cortex_m::peripheral::Peripherals::steal() };
unsafe {
core_peripherals.NVIC.icer[0].write(0xFFFF_FFFFu32);
core_peripherals.NVIC.icer[1].write(0xFFFF_FFFFu32);
cortex_m::interrupt::enable();
}
let mut syscon = unsafe { Syscon::reset_all_noncritical_peripherals() };
let iocon = unsafe { Iocon::steal() }.enabled(&mut syscon).release();
iocon
.pio0_5
.modify(|_, w| w.invert().set_bit().digimode().digital());
unsafe { cortex_m::asm::bootload(0x03000000 as *const u32) }
}