initial commit

This commit is contained in:
2022-10-23 23:45:43 -07:00
commit e190fa5193
6450 changed files with 8626944 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
extern crate alloc;
use alloc::string::{String, ToString};
use ufmt::{uDisplay, uWrite, uwrite, Formatter};
pub struct DumbError(String);
impl<T: ToString + 'static> From<T> for DumbError {
fn from(error: T) -> Self {
Self(error.to_string())
}
}
impl uDisplay for DumbError {
fn fmt<W>(&self, fmt: &mut Formatter<'_, W>) -> core::result::Result<(), W::Error>
where
W: uWrite + ?Sized,
{
uwrite!(fmt, "{}", self.0.as_str())
}
}
pub type Result<T> = core::result::Result<T, DumbError>;
#[alloc_error_handler]
fn oom(_: core::alloc::Layout) -> ! {
loop {}
}
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
+47
View File
@@ -0,0 +1,47 @@
use super::pac;
pub use super::pac::CLKGEN;
use super::time::Hertz;
pub const CLKGEN_FREQ_MAX_HZ: Hertz = Hertz(48_000_000);
pub const CLKGEN_CLKKEY: u32 = 71;
#[allow(unused)]
fn clk_cfg<F, R>(f: F) -> R
where
F: FnOnce() -> R,
{
cortex_m::interrupt::free(|_| {
unsafe {
(*pac::CLKGEN::ptr())
.clkkey
.write(|w| w.bits(CLKGEN_CLKKEY));
}
let r = f();
unsafe {
(*pac::CLKGEN::ptr()).clkkey.write(|w| w.bits(0x00));
}
r
})
}
pub struct ClockCtrl<'a> {
clkgen: &'a mut CLKGEN,
}
impl<'a> ClockCtrl<'a> {
pub fn new(clkgen: &'a mut CLKGEN) -> ClockCtrl {
ClockCtrl { clkgen }
}
pub fn enable_xt(&mut self) {
self.clkgen.octrl.modify(|_, w| w.stopxt().en());
}
pub fn disable_xt(&mut self) {
self.clkgen.octrl.modify(|_, w| w.stopxt().stop());
}
pub fn rtc_use_xt(&mut self) {
self.clkgen.octrl.write(|w| w.stopxt().en().osel().rtc_xt());
}
pub fn rtc_use_lfrc(&mut self) {
self.clkgen.octrl.modify(|_, w| w.osel().rtc_lfrc());
}
}
+146
View File
@@ -0,0 +1,146 @@
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;
pub use flash::FlashDelay;
use super::clock;
use super::ehal::blocking::delay::{DelayMs, DelayUs};
use super::halc;
use super::pac;
use super::pac::CLKGEN;
use super::time::Hertz;
pub struct Delay {
sysclock: Hertz,
syst: SYST,
}
pub fn sysclock(clkgen: &pac::clkgen::RegisterBlock) -> Hertz {
match clkgen.cctrl.read().coresel().variant() {
pac::clkgen::cctrl::CORESEL_A::HFRC => clock::CLKGEN_FREQ_MAX_HZ,
pac::clkgen::cctrl::CORESEL_A::HFRC_DIV2 => Hertz(clock::CLKGEN_FREQ_MAX_HZ.0 / 2),
}
}
impl Delay {
pub fn new(mut syst: SYST, clkgen: &mut CLKGEN) -> Self {
syst.set_clock_source(SystClkSource::Core);
let sysclock = sysclock(clkgen);
Delay { syst, sysclock }
}
pub fn free(self) -> SYST {
self.syst
}
}
impl DelayMs<u32> for Delay {
fn delay_ms(&mut self, ms: u32) {
self.delay_us(ms * 1_000);
}
}
impl DelayMs<u16> for Delay {
fn delay_ms(&mut self, ms: u16) {
self.delay_ms(ms as u32);
}
}
impl DelayMs<u8> for Delay {
fn delay_ms(&mut self, ms: u8) {
self.delay_ms(ms as u32);
}
}
impl DelayUs<u32> for Delay {
fn delay_us(&mut self, us: u32) {
const MAX_RVR: u32 = 0x00FF_FFFF;
let mut total_rvr = us * (self.sysclock.0 / 1_000_000);
while total_rvr != 0 {
let current_rvr = if total_rvr <= MAX_RVR {
total_rvr
} else {
MAX_RVR
};
self.syst.set_reload(current_rvr);
self.syst.clear_current();
self.syst.enable_counter();
total_rvr -= current_rvr;
while !self.syst.has_wrapped() {}
self.syst.disable_counter();
}
}
}
impl DelayUs<u16> for Delay {
fn delay_us(&mut self, us: u16) {
self.delay_us(us as u32)
}
}
impl DelayUs<u8> for Delay {
fn delay_us(&mut self, us: u8) {
self.delay_us(us as u32)
}
}
pub mod flash {
use super::*;
#[derive(Clone, Copy)]
pub struct FlashDelay;
impl FlashDelay {
pub fn new() -> FlashDelay {
FlashDelay
}
pub fn delay_us(us: u32) {
let clkgen = unsafe { &*CLKGEN::ptr() };
let sysclock = sysclock(clkgen);
let cycles = us * (sysclock.0 / 3_000_000);
unsafe {
halc::am_hal_flash_delay(cycles);
}
}
pub fn delay_cycles(cycles: u32) {
unsafe {
halc::am_hal_flash_delay(cycles);
}
}
}
impl DelayUs<u32> for FlashDelay {
fn delay_us(&mut self, us: u32) {
let clkgen = unsafe { &*CLKGEN::ptr() };
let sysclock = sysclock(clkgen);
let cycles = us * (sysclock.0 / 3_000_000);
unsafe {
halc::am_hal_flash_delay(cycles);
}
}
}
impl DelayUs<u16> for FlashDelay {
fn delay_us(&mut self, us: u16) {
self.delay_us(us as u32)
}
}
impl DelayUs<u8> for FlashDelay {
fn delay_us(&mut self, us: u8) {
self.delay_us(us as u32)
}
}
impl<T> DelayMs<T> for FlashDelay
where
T: Into<u32>,
{
fn delay_ms(&mut self, us: T) {
let us = us.into();
DelayUs::<u32>::delay_us(self, us * 1000);
}
}
}
+22
View File
@@ -0,0 +1,22 @@
use super::pac::GPIO;
pub use super::pin::*;
pub struct Pins {
_gpio: GPIO,
pub d10: P14<{ Mode::Floating }>,
pub tx0: P48<{ Mode::Floating }>,
pub rx0: P49<{ Mode::Floating }>,
pub d18: P26<{ Mode::Floating }>,
}
impl Pins {
pub fn new(gpio: GPIO) -> Pins {
Pins {
_gpio: gpio,
d10: Pin::new(),
d18: Pin::new(),
tx0: Pin::new(),
rx0: Pin::new(),
}
}
}
+25
View File
@@ -0,0 +1,25 @@
pub use artemis_thing_plus::Pins;
use super::ehal;
use super::pac;
const PAD_KEY: u32 = 0x73;
pub fn gpio_cfg<F, R>(f: F) -> R
where
F: FnOnce() -> R,
{
cortex_m::interrupt::free(|_| {
unsafe {
(*pac::GPIO::ptr()).padkey.write(|w| w.bits(PAD_KEY));
}
let r = f();
unsafe {
(*pac::GPIO::ptr()).padkey.write(|w| w.bits(0x00));
}
r
})
}
mod artemis_thing_plus;
pub mod pin;
+204
View File
@@ -0,0 +1,204 @@
use paste::paste;
use super::ehal::digital::v2::{OutputPin, ToggleableOutputPin};
use super::gpio_cfg;
use super::pac;
#[derive(PartialEq, Eq)]
pub enum DriveStrength {
D2mA,
D4mA,
D8mA,
D12mA,
}
#[derive(PartialEq, Eq)]
pub enum OutputMode {
Disable = 0,
PushPull,
OpenDrain,
TriState,
}
#[derive(PartialEq, Eq)]
pub enum InputMode {
NoneOrAuto = 0,
Enable = 1,
}
#[derive(PartialEq, Eq)]
pub enum Mode {
Floating,
Input,
Output,
AF0,
}
pub struct Pin<const PINNUM: usize, const MODE: Mode> {}
pub trait PinCfg {
unsafe fn padfncsel(&mut self, f: u8);
unsafe fn padinpen(&mut self, on: bool);
unsafe fn padpull(&mut self, on: bool);
unsafe fn padstrng(&mut self, high: bool);
unsafe fn outcfg(&mut self, c: u8);
}
macro_rules! pin {
($id:literal, $padreg:ident, $cfgreg: ident) => {
paste! {
pub type [<P $id>]<const MODE: Mode> = Pin<$id, MODE>;
impl<const MODE: Mode>PinCfg for Pin<$id, MODE> {
unsafe fn padpull(&mut self, on: bool) {
// XXX: Pad 20 differs in behavior to the rest of the pads, see p. 420.
(*pac::GPIO::ptr()).[<padreg $padreg:lower>]
.write(|p| p.[< pad $id pull >]().bit(on))
}
unsafe fn padinpen(&mut self, on: bool) {
(*pac::GPIO::ptr()).[<padreg $padreg:lower>]
.write(|p| p.[< pad $id inpen >]().bit(on))
}
unsafe fn padstrng(&mut self, high: bool) {
(*pac::GPIO::ptr()).[<padreg $padreg:lower>]
.write(|p| p.[< pad $id strng >]().bit(high))
}
unsafe fn padfncsel(&mut self, f: u8) {
(*pac::GPIO::ptr()).[<padreg $padreg:lower>]
.write(|p| p.[< pad $id fncsel >]().bits(f))
}
unsafe fn outcfg(&mut self, f: u8) {
(*pac::GPIO::ptr()).[<cfg $cfgreg:lower>]
.write(|p| p.[< gpio $id outcfg >]().bits(f))
}
}
}
};
}
impl<const P: usize> Pin<P, { Mode::Floating }> {
pub fn new() -> Self {
Self {}
}
}
impl<const P: usize, const M: Mode> Pin<P, M>
where
Pin<P, M>: PinCfg,
{
pub fn with_mode() -> Self {
Self {}.into_mode::<M>()
}
pub fn into_mode<const NEWM: Mode>(mut self) -> Pin<P, NEWM> {
gpio_cfg(|| unsafe {
self.padfncsel(3);
match NEWM {
Mode::Floating | Mode::Input => self.padinpen(true),
Mode::Output => {
self.padinpen(false);
self.outcfg(1); // push-pull
}
Mode::AF0 => {
self.padfncsel(0);
self.padinpen(false);
}
}
});
Pin {}
}
pub fn pin_num(&self) -> usize {
P
}
pub fn into_push_pull_output(self) -> Pin<P, { Mode::Output }> {
self.into_mode()
}
}
impl<const P: usize> Pin<P, { Mode::Output }>
where
Pin<P, { Mode::Output }>: PinCfg,
{
pub fn internal_pull_up(&mut self, on: bool) {
gpio_cfg(|| unsafe { self.padpull(on) })
}
}
impl<const P: usize> Pin<P, { Mode::AF0 }>
where
Pin<P, { Mode::AF0 }>: PinCfg,
{
pub fn set_drive_strength(&mut self, d: DriveStrength) {
gpio_cfg(|| unsafe {
match d {
DriveStrength::D2mA => self.padstrng(false),
DriveStrength::D4mA => self.padstrng(true),
_ => (), // XXX: is configured in altpadcfg
}
});
}
}
impl<const P: usize> OutputPin for Pin<P, { Mode::Output }>
where
Pin<P, { Mode::Output }>: PinCfg,
{
type Error = !;
fn set_low(&mut self) -> Result<(), !> {
let mask: u32 = 0b1u32 << (P % 32);
let reg = unsafe {
match P {
0..=31 => (*pac::GPIO::ptr()).wtca.as_ptr(),
_ => (*pac::GPIO::ptr()).wtcb.as_ptr(),
}
};
gpio_cfg(|| unsafe { reg.write(mask) });
Ok(())
}
fn set_high(&mut self) -> Result<(), !> {
let mask: u32 = 0b1u32 << (P % 32);
let reg = unsafe {
match P {
0..=31 => (*pac::GPIO::ptr()).wtsa.as_ptr(),
_ => (*pac::GPIO::ptr()).wtsb.as_ptr(),
}
};
gpio_cfg(|| unsafe { reg.write(mask) });
Ok(())
}
}
impl<const P: usize> ToggleableOutputPin for Pin<P, { Mode::Output }>
where
Pin<P, { Mode::Output }>: PinCfg,
{
type Error = !;
fn toggle(&mut self) -> Result<(), !> {
let mask: u32 = 0b1u32 << (P % 32);
let reg = unsafe {
match P {
0..=31 => (*pac::GPIO::ptr()).wta.as_ptr(),
_ => (*pac::GPIO::ptr()).wtb.as_ptr(),
}
};
gpio_cfg(|| unsafe {
*reg ^= mask;
});
Ok(())
}
}
pin!(14, D, B);
pin!(26, G, D);
pin!(48, M, G);
pin!(49, M, G);
+18
View File
@@ -0,0 +1,18 @@
pub extern crate ambiq_apollo3_pac2 as pac;
pub extern crate ambiq_hal_sys as halc;
pub extern crate embedded_hal as ehal;
pub mod clock;
pub mod delay;
pub mod gpio;
pub mod rtc;
pub mod time;
pub mod uart;
pub mod watchdog;
pub mod prelude {
pub use super::ehal::digital::v2::{InputPin, OutputPin, ToggleableOutputPin};
pub use super::ehal::prelude::*;
pub use super::halc;
pub use super::halc::c_types::*;
}
+198
View File
@@ -0,0 +1,198 @@
use chrono::{Datelike, Timelike};
use rtcc::DateTimeAccess;
use super::clock::ClockCtrl;
use super::pac;
use super::pac::rtc::rtcctl::RPT_A;
use super::pac::{CLKGEN, RTC};
pub struct Rtc {
rtc: RTC,
}
fn bcd_to_dec(bcd: u8) -> u8 {
(((bcd & 0xf0) >> 4) * 10) + (bcd & 0x0f)
}
fn dec_to_bcd(dec: u8) -> u8 {
((dec / 10) << 4) | (dec % 10)
}
impl Rtc {
pub fn new(rtc: RTC, clkgen: &mut CLKGEN) -> Rtc {
let mut clk = ClockCtrl::new(clkgen);
rtc.rtcctl.reset();
rtc.almup.reset();
rtc.almlow.reset();
rtc.inten.write(|w| w.alm().clear_bit());
rtc.intclr.write(|w| w.alm().set_bit());
clk.rtc_use_xt();
rtc.rtcctl.modify(|_, w| w.hr1224()._24hr());
Rtc { rtc }
}
pub fn enable(&mut self) {
self.rtc.rtcctl.modify(|_, w| w.rstop().run());
}
pub fn disable(&mut self) {
self.rtc.rtcctl.modify(|_, w| w.rstop().stop());
}
pub fn set(&self, dt: &chrono::NaiveDateTime) {
let date = dt.date();
let time = dt.time();
let year = date.year();
let yr = year % 100;
self.rtc.rtcctl.modify(|_, w| w.wrtc().en());
self.rtc.ctrlow.write(|w| unsafe {
w.ctrhr()
.bits(dec_to_bcd(time.hour() as u8))
.ctrmin()
.bits(dec_to_bcd(time.minute() as u8))
.ctrsec()
.bits(dec_to_bcd(time.second() as u8))
.ctr100()
.bits(dec_to_bcd((time.nanosecond() / 1_000_000 * 100) as u8))
});
self.rtc.ctrup.write(|w| unsafe {
w.ceb()
.dis() // TODO: support other centuries
.ctryr()
.bits(dec_to_bcd(yr as u8))
.ctrmo()
.bits(dec_to_bcd(date.month() as u8))
.ctrdate()
.bits(dec_to_bcd(date.day() as u8))
.ctrwkdy()
.bits(date.weekday() as u8)
});
self.rtc.rtcctl.modify(|_, w| w.wrtc().dis());
}
pub fn now(&self) -> chrono::NaiveDateTime {
let (upper, lower) = loop {
let lower = self.rtc.ctrlow.read();
let no_err = self.rtc.ctrup.read().cterr().is_noerr();
let upper = self.rtc.ctrup.read();
if no_err {
break (upper, lower);
}
};
let yr = bcd_to_dec(upper.ctryr().bits()) as i32;
const CE: i32 = 20;
chrono::NaiveDate::from_ymd(
CE * 100 + yr,
bcd_to_dec(upper.ctrmo().bits()).into(),
bcd_to_dec(upper.ctrdate().bits()).into(),
)
.and_hms_milli(
bcd_to_dec(lower.ctrhr().bits()).into(),
bcd_to_dec(lower.ctrmin().bits()).into(),
bcd_to_dec(lower.ctrsec().bits()).into(),
u32::from(bcd_to_dec(lower.ctr100().bits())) * 10u32,
)
}
pub fn set_alarm_repeat(&mut self, interval: AlarmRepeat) {
self.rtc.almup.reset();
self.rtc.almlow.reset();
self.rtc
.rtcctl
.modify(|_, w| w.rpt().variant(interval.into()));
match interval {
AlarmRepeat::DeciSecond => {
self.rtc.almlow.write(|w| unsafe { w.alm100().bits(0xf0) });
}
AlarmRepeat::CentiSecond => {
self.rtc.almlow.write(|w| unsafe { w.alm100().bits(0xff) });
}
_ => {}
}
}
pub fn clear_interrupts(&mut self) {
self.rtc.intclr.write(|w| w.alm().set_bit());
}
pub fn disable_alarm_repeat(&mut self) {
self.rtc.rtcctl.modify(|_, w| w.rpt().dis());
}
pub fn enable_alarm(&mut self) {
cortex_m::interrupt::free(|_| {
self.clear_interrupts();
self.rtc.inten.write(|w| w.alm().set_bit());
unsafe {
pac::NVIC::unmask(pac::Interrupt::RTC);
}
});
}
pub fn disable_alarm(&mut self) {
pac::NVIC::mask(pac::Interrupt::RTC);
self.rtc.inten.write(|w| w.alm().clear_bit());
self.clear_interrupts();
}
}
impl DateTimeAccess for Rtc {
type Error = !;
fn datetime(&mut self) -> Result<chrono::NaiveDateTime, !> {
Ok(self.now())
}
fn set_datetime(&mut self, datetime: &chrono::NaiveDateTime) -> Result<(), !> {
self.set(datetime);
Ok(())
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u8)]
pub enum AlarmRepeat {
Disabled,
Year,
Month,
Week,
Day,
Hour,
Minute,
Second,
DeciSecond,
CentiSecond,
}
impl Into<RPT_A> for AlarmRepeat {
fn into(self) -> RPT_A {
use AlarmRepeat::*;
use RPT_A::*;
match self {
Disabled => DIS,
Year => YEAR,
Month => MONTH,
Week => WEEK,
Day => DAY,
Hour => HR,
Minute => MIN,
Second => SEC,
DeciSecond => SEC,
CentiSecond => SEC,
}
}
}
+199
View File
@@ -0,0 +1,199 @@
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Bps(pub u32);
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Hertz(pub u32);
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct KiloHertz(pub u32);
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MegaHertz(pub u32);
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Seconds(pub u32);
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Milliseconds(pub u32);
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Microseconds(pub u32);
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Nanoseconds(pub u32);
pub trait U32Ext {
fn bps(self) -> Bps;
fn hz(self) -> Hertz;
fn khz(self) -> KiloHertz;
fn mhz(self) -> MegaHertz;
fn s(self) -> Seconds;
fn ms(self) -> Milliseconds;
fn us(self) -> Microseconds;
fn ns(self) -> Nanoseconds;
}
impl U32Ext for u32 {
fn bps(self) -> Bps {
Bps(self)
}
fn hz(self) -> Hertz {
Hertz(self)
}
fn khz(self) -> KiloHertz {
KiloHertz(self)
}
fn mhz(self) -> MegaHertz {
MegaHertz(self)
}
fn s(self) -> Seconds {
Seconds(self)
}
fn ms(self) -> Milliseconds {
Milliseconds(self)
}
fn us(self) -> Microseconds {
Microseconds(self)
}
fn ns(self) -> Nanoseconds {
Nanoseconds(self)
}
}
impl From<KiloHertz> for Hertz {
fn from(item: KiloHertz) -> Self {
Hertz(item.0 * 1_000)
}
}
impl From<MegaHertz> for Hertz {
fn from(item: MegaHertz) -> Self {
Hertz(item.0 * 1_000_000)
}
}
impl From<MegaHertz> for KiloHertz {
fn from(item: MegaHertz) -> Self {
KiloHertz(item.0 * 1_000)
}
}
impl From<Hertz> for KiloHertz {
fn from(item: Hertz) -> Self {
KiloHertz(item.0 / 1_000)
}
}
impl From<Hertz> for MegaHertz {
fn from(item: Hertz) -> Self {
MegaHertz(item.0 / 1_000_000)
}
}
impl From<KiloHertz> for MegaHertz {
fn from(item: KiloHertz) -> Self {
MegaHertz(item.0 / 1_000)
}
}
impl From<Seconds> for Milliseconds {
fn from(item: Seconds) -> Self {
Milliseconds(item.0 * 1_000)
}
}
impl From<Seconds> for Microseconds {
fn from(item: Seconds) -> Self {
Microseconds(item.0 * 1_000_000)
}
}
impl From<Seconds> for Nanoseconds {
fn from(item: Seconds) -> Self {
Nanoseconds(item.0 * 1_000_000_000)
}
}
impl From<Milliseconds> for Microseconds {
fn from(item: Milliseconds) -> Self {
Microseconds(item.0 * 1_000)
}
}
impl From<Microseconds> for Nanoseconds {
fn from(item: Microseconds) -> Self {
Nanoseconds(item.0 * 1_000)
}
}
impl From<Milliseconds> for Seconds {
fn from(item: Milliseconds) -> Self {
Seconds(item.0 / 1_000)
}
}
impl From<Microseconds> for Seconds {
fn from(item: Microseconds) -> Self {
Seconds(item.0 / 1_000_000)
}
}
impl From<Microseconds> for Milliseconds {
fn from(item: Microseconds) -> Self {
Milliseconds(item.0 / 1_000)
}
}
impl From<Milliseconds> for Nanoseconds {
fn from(item: Milliseconds) -> Self {
Nanoseconds(item.0 * 1_000_000)
}
}
impl From<Nanoseconds> for Hertz {
fn from(item: Nanoseconds) -> Self {
Hertz(1_000_000_000_u32 / item.0)
}
}
impl From<Microseconds> for Hertz {
fn from(item: Microseconds) -> Self {
Hertz(1_000_000_u32 / item.0)
}
}
impl From<Nanoseconds> for KiloHertz {
fn from(item: Nanoseconds) -> Self {
KiloHertz(1_000_000_u32 / item.0)
}
}
impl From<Nanoseconds> for MegaHertz {
fn from(item: Nanoseconds) -> Self {
MegaHertz(1_000_u32 / item.0)
}
}
impl From<Hertz> for Microseconds {
fn from(item: Hertz) -> Self {
Microseconds(1_000_000_u32 / item.0)
}
}
impl From<Hertz> for Nanoseconds {
fn from(item: Hertz) -> Self {
Nanoseconds(1_000_000_000u32 / item.0)
}
}
impl From<KiloHertz> for Nanoseconds {
fn from(item: KiloHertz) -> Self {
Nanoseconds(1_000_000u32 / item.0)
}
}
impl From<MegaHertz> for Nanoseconds {
fn from(item: MegaHertz) -> Self {
Nanoseconds(1_000u32 / item.0)
}
}
+124
View File
@@ -0,0 +1,124 @@
use core::ptr;
use super::ehal::serial::{Read, Write};
use super::halc;
use super::halc::c_types::*;
use super::pac;
use super::{gpio, gpio::pin::Mode};
pub struct Uart0 {
ph_uart: *mut c_void,
uart: pac::UART0,
tx: gpio::pin::P48<{ Mode::Floating }>,
rx: gpio::pin::P49<{ Mode::Floating }>,
}
unsafe impl Sync for Uart0 {}
unsafe impl Send for Uart0 {}
impl Uart0 {
pub fn new(
uart: pac::UART0,
tx: gpio::pin::P48<{ Mode::Floating }>,
rx: gpio::pin::P49<{ Mode::Floating }>,
) -> Uart0 {
let mut ph_uart = ptr::null_mut();
let uart_config = halc::am_hal_uart_config_t {
ui32BaudRate: 115200,
ui32DataBits: halc::cAM_HAL_UART_DATA_BITS_8,
ui32Parity: halc::cAM_HAL_UART_PARITY_NONE,
ui32StopBits: halc::cAM_HAL_UART_ONE_STOP_BIT,
ui32FlowControl: halc::cAM_HAL_UART_FLOW_CTRL_NONE,
ui32FifoLevels: (halc::cAM_HAL_UART_TX_FIFO_1_2 | halc::cAM_HAL_UART_RX_FIFO_1_2),
pui8TxBuffer: ptr::null_mut(),
ui32TxBufferSize: 0,
pui8RxBuffer: ptr::null_mut(),
ui32RxBufferSize: 0,
};
unsafe {
halc::am_hal_uart_initialize(0, &mut ph_uart);
halc::am_hal_uart_power_control(ph_uart, 0, false);
halc::am_hal_uart_configure(ph_uart, &uart_config);
halc::am_hal_gpio_pinconfig(tx.pin_num() as u32, halc::g_AM_BSP_GPIO_COM_UART_TX);
halc::am_hal_gpio_pinconfig(rx.pin_num() as u32, halc::g_AM_BSP_GPIO_COM_UART_RX);
}
Uart0 {
ph_uart,
uart,
tx,
rx,
}
}
}
impl Drop for Uart0 {
fn drop(&mut self) {
unsafe {
halc::am_hal_uart_power_control(self.ph_uart, 2, false);
halc::am_hal_uart_deinitialize(self.ph_uart);
halc::am_hal_gpio_pinconfig(self.tx.pin_num() as u32, halc::g_AM_HAL_GPIO_DISABLE);
halc::am_hal_gpio_pinconfig(self.rx.pin_num() as u32, halc::g_AM_HAL_GPIO_DISABLE);
self.ph_uart = ptr::null_mut();
}
}
}
impl Read<u8> for Uart0 {
type Error = ();
fn read(&mut self) -> nb::Result<u8, Self::Error> {
if self.uart.fr.read().rxfe().bit_is_set() {
Err(nb::Error::WouldBlock)
} else {
let dr = self.uart.dr.read();
if dr.oedata().is_err()
|| dr.bedata().is_err()
|| dr.pedata().is_err()
|| dr.fedata().is_err()
{
Err(nb::Error::Other(()))
} else {
Ok(dr.data().bits())
}
}
}
}
impl Write<u8> for Uart0 {
type Error = !;
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
if self.uart.fr.read().txff().bit_is_set() {
Err(nb::Error::WouldBlock)
} else {
unsafe {
self.uart.dr.write(|dr| dr.data().bits(byte));
}
Ok(())
}
}
fn flush(&mut self) -> nb::Result<(), Self::Error> {
if self.uart.fr.read().txbusy().bit_is_set() {
Err(nb::Error::WouldBlock)
} else {
Ok(())
}
}
}
impl ufmt::uWrite for Uart0 {
type Error = !;
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
for b in s.as_bytes().iter() {
nb::block!(self.write(*b))?;
}
Ok(())
}
}
+46
View File
@@ -0,0 +1,46 @@
use super::ehal::watchdog;
use super::pac::{wdt, WDT};
pub struct Watchdog {
wdt: WDT,
}
pub type Frequency = wdt::cfg::CLKSEL_A;
impl Watchdog {
pub fn from(wdt: WDT, reset: bool, reset_count: u8, freq: Frequency) -> Watchdog {
wdt.cfg.write(|w| unsafe {
w.resen()
.bit(reset)
.resval()
.bits(reset_count)
.clksel()
.variant(freq)
});
Watchdog { wdt }
}
pub fn start(&mut self) {
self.wdt.cfg.modify(|_, w| w.wdten().set_bit());
watchdog::Watchdog::feed(self);
self.wdt.rstrt.read().bits();
}
pub fn lock_and_start(&mut self) {
self.wdt
.lock
.write(|w| w.lock().variant(wdt::lock::LOCK_A::KEYVALUE));
}
pub fn halt(&mut self) {
self.wdt.cfg.modify(|_, w| w.wdten().clear_bit());
}
}
impl watchdog::Watchdog for Watchdog {
fn feed(&mut self) {
self.wdt
.rstrt
.write(|w| w.rstrt().variant(wdt::rstrt::RSTRT_A::KEYVALUE));
}
}
+254
View File
@@ -0,0 +1,254 @@
#![no_main]
#![no_std]
#![feature(adt_const_params)]
#![feature(never_type)]
#![feature(alloc_error_handler)]
extern crate alloc;
use alloc::string::{String, ToString};
use chrono::NaiveDateTime;
use ufmt::{uwrite, uwriteln};
use error::Result;
use hal::prelude::*;
mod error;
mod hal;
#[global_allocator]
static ALLOCATOR: alloc_cortex_m::CortexMHeap = alloc_cortex_m::CortexMHeap::empty();
#[cortex_m_rt::pre_init]
unsafe fn pre_init() {
(*cortex_m::peripheral::SCB::PTR).vtor.write(0x10000);
}
struct App<'a> {
command: &'a str,
func: fn(&mut State, &str) -> Result<()>,
description: &'a str,
}
static APPS: [App; 5] = [
App {
command: "help",
func: help,
description: "Help command",
},
App {
command: "free",
func: free,
description: "Show memory allocation",
},
App {
command: "reset",
func: reset,
description: "Soft reboot the device",
},
App {
command: "time",
func: time,
description: "Perform clock operations, set accepts %d/%m/%Y %H:%M:%S",
},
App {
command: "mandelbrot",
func: mandelbrot,
description: "Display a mandelbrot set",
},
];
fn help(state: &mut State, _args: &str) -> Result<()> {
for app in &APPS {
uwriteln!(state.serial, "{}: {}\r", app.command, app.description)?;
}
Ok(())
}
fn free(state: &mut State, _args: &str) -> Result<()> {
uwriteln!(
state.serial,
"memory> used: {}, free: {}\r",
ALLOCATOR.used(),
ALLOCATOR.free()
)?;
Ok(())
}
fn reset(_state: &mut State, _args: &str) -> Result<()> {
unsafe {
halc::am_hal_reset_control(
halc::am_hal_reset_control_e_AM_HAL_RESET_CONTROL_SWPOI,
core::ptr::null_mut::<c_void>(),
);
}
Ok(())
}
fn time(state: &mut State, args: &str) -> Result<()> {
match args.split_once(' ').unwrap_or((&args, "")) {
("set", time) => {
let dt = NaiveDateTime::parse_from_str(time, "%d/%m/%Y %H:%M:%S")?;
state.rtc.set(&dt);
}
_ => return Err("Command not recognized".into()),
}
Ok(())
}
fn mandelbrot(state: &mut State, args: &str) -> Result<()> {
use num_complex::Complex;
struct Ifs {
max_iter: u64,
}
trait Dds<State> {
fn cont(&self, z: State) -> bool;
fn next(&self, z: State, c: State) -> State;
}
impl Dds<Complex<f64>> for Ifs {
fn cont(&self, z: Complex<f64>) -> bool {
z.norm_sqr() <= 4.0
}
fn next(&self, z: Complex<f64>, c: Complex<f64>) -> Complex<f64> {
z * z + c
}
}
impl Ifs {
pub fn new(max_iter: u64) -> Self {
Self { max_iter }
}
pub fn iter(&self, c: Complex<f64>) -> u64 {
let mut i: u64 = 0;
let mut z = c;
while i < self.max_iter && self.cont(z) {
z = self.next(z, c);
i += 1;
}
if i < self.max_iter {
return self.max_iter - i;
}
0
}
}
fn parse_args(args: &str) -> Result<(f64, f64, i32, i32)> {
let mut args = args.split(' ');
let min = args
.next()
.ok_or("expected min")?
.parse::<f64>()
.map_err(|_| "min: expected float")?;
let max = args
.next()
.ok_or("expected max")?
.parse::<f64>()
.map_err(|_| "min: expected float")?;
let d_x = args
.next()
.ok_or("expected d_x")?
.parse::<i32>()
.map_err(|_| "d_x: expected int")?;
let d_y = args
.next()
.ok_or("expected d_y")?
.parse::<i32>()
.map_err(|_| "d_y: expected int")?;
Ok((min, max, d_x, d_y))
}
let (min, max, d_x, d_y) = parse_args(args)?;
let min = Complex::new(min, min);
let max = Complex::new(max, max);
let mandel = Ifs::new(256);
for j in 0..d_y - 1 {
for i in 0..d_x - 1 {
let x = min.re + (max.re - min.re) * (i as f64) / (d_x as f64);
let y = min.im + (max.im - min.im) * (j as f64) / (d_y as f64);
let c = Complex::new(x, y);
let m = mandel.iter(c);
let mut ch = ' ';
if (1..63).contains(&m) {
ch = '.';
}
if (64..128).contains(&m) {
ch = 'o';
}
if (128..192).contains(&m) {
ch = '*';
}
if (192..256).contains(&m) {
ch = '0';
}
uwrite!(state.serial, "{}", ch)?;
}
uwriteln!(state.serial, "\r")?;
}
Ok(())
}
struct State {
serial: hal::uart::Uart0,
rtc: hal::rtc::Rtc,
delay: hal::delay::Delay,
}
#[cortex_m_rt::entry]
fn main() -> ! {
unsafe { ALLOCATOR.init(cortex_m_rt::heap_start() as usize, (1024 * 384) - 0x100) }
let mut dp = hal::pac::Peripherals::take().unwrap();
let core = hal::pac::CorePeripherals::take().unwrap();
let pins = hal::gpio::Pins::new(dp.GPIO);
let serial = hal::uart::Uart0::new(dp.UART0, pins.tx0, pins.rx0);
let mut rtc = hal::rtc::Rtc::new(dp.RTC, &mut dp.CLKGEN);
let delay = hal::delay::Delay::new(core.SYST, &mut dp.CLKGEN);
rtc.enable();
let mut state = State { serial, rtc, delay };
let mut led = pins.d18.into_push_pull_output();
loop {
led.toggle().unwrap();
let timestamp = state.rtc.now().to_string();
uwrite!(state.serial, "{}:artemis> ", timestamp.as_str()).unwrap();
let mut line = String::new();
loop {
let char = match state.serial.read() {
Ok(word) => {
state.serial.write(word).unwrap();
char::from(word)
}
Err(_) => continue,
};
match char {
'\r' => {
uwrite!(state.serial, "\r\n").unwrap();
break;
}
'\x08' => {
line.pop();
uwrite!(state.serial, "\x20\x08").unwrap();
}
_ => line.push(char),
}
}
let (command, args) = line.split_once(' ').unwrap_or((&line, ""));
for app in &APPS {
if command == app.command {
match (app.func)(&mut state, args.trim()) {
Ok(_) => continue,
Err(e) => uwriteln!(state.serial, "{}\r", e).unwrap(),
};
}
}
}
}