pub use tm4c_hal::sysctl::*;
use crate::{
bb,
time::{Hertz, U32Ext},
};
use cortex_m::asm::nop;
pub struct Sysctl {
pub power_control: PowerControl,
pub clock_setup: ClockSetup,
}
pub struct PowerControl {
_0: (),
}
pub struct ClockSetup {
pub oscillator: Oscillator,
_0: (),
}
#[derive(Clone, Copy)]
pub enum Oscillator {
Main(CrystalFrequency, SystemClock),
PrecisionInternal(SystemClock),
PrecisionInternalDiv4(Divider),
LowFrequencyInternal(Divider),
}
#[derive(Clone, Copy)]
pub enum SystemClock {
UseOscillator(Divider),
UsePll(PllOutputFrequency),
}
#[derive(Clone, Copy)]
pub enum CrystalFrequency {
_4mhz,
_4_09mhz,
_4_91mhz,
_5mhz,
_5_12mhz,
_6mhz,
_6_14mhz,
_7_37mhz,
_8mhz,
_8_19mhz,
_10mhz,
_12mhz,
_12_2mhz,
_13_5mhz,
_14_3mhz,
_16mhz,
_16_3mhz,
_18mhz,
_20mhz,
_24mhz,
_25mhz,
}
impl Into<Hertz> for CrystalFrequency {
fn into(self) -> Hertz {
Hertz(match self {
CrystalFrequency::_4mhz => 4_000_000,
CrystalFrequency::_4_09mhz => 4_090_000,
CrystalFrequency::_4_91mhz => 4_910_000,
CrystalFrequency::_5mhz => 5_000_000,
CrystalFrequency::_5_12mhz => 5_120_000,
CrystalFrequency::_6mhz => 6_000_000,
CrystalFrequency::_6_14mhz => 6_140_000,
CrystalFrequency::_7_37mhz => 7_370_000,
CrystalFrequency::_8mhz => 8_000_000,
CrystalFrequency::_8_19mhz => 8_190_000,
CrystalFrequency::_10mhz => 10_000_000,
CrystalFrequency::_12mhz => 12_000_000,
CrystalFrequency::_12_2mhz => 12_200_000,
CrystalFrequency::_13_5mhz => 13_500_000,
CrystalFrequency::_14_3mhz => 14_300_000,
CrystalFrequency::_16mhz => 16_000_000,
CrystalFrequency::_16_3mhz => 16_300_000,
CrystalFrequency::_18mhz => 18_000_000,
CrystalFrequency::_20mhz => 20_000_000,
CrystalFrequency::_24mhz => 24_000_000,
CrystalFrequency::_25mhz => 25_000_000,
})
}
}
#[derive(Clone, Copy)]
pub enum PllOutputFrequency {
_80_00mhz = 0,
_66_67mhz = 2,
_50_00mhz = 3,
_40_00mhz = 4,
_33_33mhz = 5,
_28_57mhz = 6,
_25mhz = 7,
_22_22mhz = 8,
_20mhz = 9,
_18_18mhz = 10,
_16_67mhz = 11,
_15_38mhz = 12,
_14_29mhz = 13,
_13_33mhz = 14,
_12_5mhz = 15,
}
impl Into<Hertz> for PllOutputFrequency {
fn into(self) -> Hertz {
Hertz(match self {
PllOutputFrequency::_80_00mhz => 80_000_000,
PllOutputFrequency::_66_67mhz => 66_670_000,
PllOutputFrequency::_50_00mhz => 50_000_000,
PllOutputFrequency::_40_00mhz => 40_000_000,
PllOutputFrequency::_33_33mhz => 33_330_000,
PllOutputFrequency::_28_57mhz => 28_570_000,
PllOutputFrequency::_25mhz => 25_000_000,
PllOutputFrequency::_22_22mhz => 22_220_000,
PllOutputFrequency::_20mhz => 20_000_000,
PllOutputFrequency::_18_18mhz => 18_180_000,
PllOutputFrequency::_16_67mhz => 16_670_000,
PllOutputFrequency::_15_38mhz => 15_380_000,
PllOutputFrequency::_14_29mhz => 14_290_000,
PllOutputFrequency::_13_33mhz => 13_330_000,
PllOutputFrequency::_12_5mhz => 12_500_000,
})
}
}
#[derive(Clone, Copy)]
pub enum Divider {
_1 = 1,
_2 = 2,
_3 = 3,
_4 = 4,
_5 = 5,
_6 = 6,
_7 = 7,
_8 = 8,
_9 = 9,
_10 = 10,
_11 = 11,
_12 = 12,
_13 = 13,
_14 = 14,
_15 = 15,
_16 = 16,
}
#[derive(Copy, Clone)]
pub enum Domain {
Watchdog1,
Watchdog0,
Timer5,
Timer4,
Timer3,
Timer2,
Timer1,
Timer0,
GpioF,
GpioE,
GpioD,
GpioC,
GpioB,
GpioA,
MicroDma,
Hibernation,
Uart7,
Uart6,
Uart5,
Uart4,
Uart3,
Uart2,
Uart1,
Uart0,
Ssi3,
Ssi2,
Ssi1,
Ssi0,
I2c3,
I2c2,
I2c1,
I2c0,
Usb,
Can,
Adc1,
Adc0,
AnalogComparator,
Eeprom,
WideTimer5,
WideTimer4,
WideTimer3,
WideTimer2,
WideTimer1,
WideTimer0,
Pwm0,
Pwm1,
}
pub fn reset(_lock: &PowerControl, pd: Domain) {
let p = unsafe { &*tm4c123x::SYSCTL::ptr() };
match pd {
Domain::Watchdog1 => unsafe {
bb::toggle_bit(&p.srwd, 1);
bb::spin_bit(&p.prwd, 1);
},
Domain::Watchdog0 => unsafe {
bb::toggle_bit(&p.srwd, 0);
bb::spin_bit(&p.prwd, 0);
},
Domain::Timer5 => unsafe {
bb::toggle_bit(&p.srtimer, 5);
bb::spin_bit(&p.prtimer, 5);
},
Domain::Timer4 => unsafe {
bb::toggle_bit(&p.srtimer, 4);
bb::spin_bit(&p.prtimer, 4);
},
Domain::Timer3 => unsafe {
bb::toggle_bit(&p.srtimer, 3);
bb::spin_bit(&p.prtimer, 3);
},
Domain::Timer2 => unsafe {
bb::toggle_bit(&p.srtimer, 2);
bb::spin_bit(&p.prtimer, 2);
},
Domain::Timer1 => unsafe {
bb::toggle_bit(&p.srtimer, 1);
bb::spin_bit(&p.prtimer, 1);
},
Domain::Timer0 => unsafe {
bb::toggle_bit(&p.srtimer, 0);
bb::spin_bit(&p.prtimer, 0);
},
Domain::GpioF => unsafe {
bb::toggle_bit(&p.srgpio, 5);
bb::spin_bit(&p.prgpio, 5);
},
Domain::GpioE => unsafe {
bb::toggle_bit(&p.srgpio, 4);
bb::spin_bit(&p.prgpio, 4);
},
Domain::GpioD => unsafe {
bb::toggle_bit(&p.srgpio, 3);
bb::spin_bit(&p.prgpio, 3);
},
Domain::GpioC => unsafe {
bb::toggle_bit(&p.srgpio, 2);
bb::spin_bit(&p.prgpio, 2);
},
Domain::GpioB => unsafe {
bb::toggle_bit(&p.srgpio, 1);
bb::spin_bit(&p.prgpio, 1);
},
Domain::GpioA => unsafe {
bb::toggle_bit(&p.srgpio, 0);
bb::spin_bit(&p.prgpio, 0);
},
Domain::MicroDma => unsafe {
bb::toggle_bit(&p.srdma, 0);
bb::spin_bit(&p.prdma, 0);
},
Domain::Hibernation => unsafe {
bb::toggle_bit(&p.srhib, 0);
bb::spin_bit(&p.prhib, 0);
},
Domain::Uart7 => unsafe {
bb::toggle_bit(&p.sruart, 7);
bb::spin_bit(&p.pruart, 7);
},
Domain::Uart6 => unsafe {
bb::toggle_bit(&p.sruart, 6);
bb::spin_bit(&p.pruart, 6);
},
Domain::Uart5 => unsafe {
bb::toggle_bit(&p.sruart, 5);
bb::spin_bit(&p.pruart, 5);
},
Domain::Uart4 => unsafe {
bb::toggle_bit(&p.sruart, 4);
bb::spin_bit(&p.pruart, 4);
},
Domain::Uart3 => unsafe {
bb::toggle_bit(&p.sruart, 3);
bb::spin_bit(&p.pruart, 3);
},
Domain::Uart2 => unsafe {
bb::toggle_bit(&p.sruart, 2);
bb::spin_bit(&p.pruart, 2);
},
Domain::Uart1 => unsafe {
bb::toggle_bit(&p.sruart, 1);
bb::spin_bit(&p.pruart, 1);
},
Domain::Uart0 => unsafe {
bb::toggle_bit(&p.sruart, 0);
bb::spin_bit(&p.pruart, 0);
},
Domain::Ssi3 => unsafe {
bb::toggle_bit(&p.srssi, 3);
bb::spin_bit(&p.prssi, 3);
},
Domain::Ssi2 => unsafe {
bb::toggle_bit(&p.srssi, 2);
bb::spin_bit(&p.prssi, 2);
},
Domain::Ssi1 => unsafe {
bb::toggle_bit(&p.srssi, 1);
bb::spin_bit(&p.prssi, 1);
},
Domain::Ssi0 => unsafe {
bb::toggle_bit(&p.srssi, 0);
bb::spin_bit(&p.prssi, 0);
},
Domain::I2c3 => unsafe {
bb::toggle_bit(&p.sri2c, 3);
bb::spin_bit(&p.pri2c, 3);
},
Domain::I2c2 => unsafe {
bb::toggle_bit(&p.sri2c, 2);
bb::spin_bit(&p.pri2c, 2);
},
Domain::I2c1 => unsafe {
bb::toggle_bit(&p.sri2c, 1);
bb::spin_bit(&p.pri2c, 1);
},
Domain::I2c0 => unsafe {
bb::toggle_bit(&p.sri2c, 0);
bb::spin_bit(&p.pri2c, 0);
},
Domain::Usb => unsafe {
bb::toggle_bit(&p.srusb, 0);
bb::spin_bit(&p.prusb, 0);
},
Domain::Can => unsafe {
bb::toggle_bit(&p.srcan, 0);
bb::spin_bit(&p.prcan, 0);
},
Domain::Adc1 => unsafe {
bb::toggle_bit(&p.sradc, 1);
bb::spin_bit(&p.pradc, 1);
},
Domain::Adc0 => unsafe {
bb::toggle_bit(&p.sradc, 0);
bb::spin_bit(&p.pradc, 0);
},
Domain::AnalogComparator => unsafe {
bb::toggle_bit(&p.sracmp, 0);
bb::spin_bit(&p.pracmp, 0);
},
Domain::Eeprom => unsafe {
bb::toggle_bit(&p.sreeprom, 0);
bb::spin_bit(&p.preeprom, 0);
},
Domain::WideTimer5 => unsafe {
bb::toggle_bit(&p.srwtimer, 5);
bb::spin_bit(&p.prwtimer, 5);
},
Domain::WideTimer4 => unsafe {
bb::toggle_bit(&p.srwtimer, 4);
bb::spin_bit(&p.prwtimer, 4);
},
Domain::WideTimer3 => unsafe {
bb::toggle_bit(&p.srwtimer, 3);
bb::spin_bit(&p.prwtimer, 3);
},
Domain::WideTimer2 => unsafe {
bb::toggle_bit(&p.srwtimer, 2);
bb::spin_bit(&p.prwtimer, 2);
},
Domain::WideTimer1 => unsafe {
bb::toggle_bit(&p.srwtimer, 1);
bb::spin_bit(&p.prwtimer, 1);
},
Domain::WideTimer0 => unsafe {
bb::toggle_bit(&p.srwtimer, 0);
bb::spin_bit(&p.prwtimer, 0);
},
Domain::Pwm0 => unsafe {
bb::toggle_bit(&p.srpwm, 0);
bb::spin_bit(&p.prpwm, 0);
},
Domain::Pwm1 => unsafe {
bb::toggle_bit(&p.srpwm, 1);
bb::spin_bit(&p.prpwm, 1);
},
}
}
pub fn control_power(_lock: &PowerControl, pd: Domain, run_mode: RunMode, state: PowerState) {
let on = match state {
PowerState::On => true,
PowerState::Off => false,
};
match run_mode {
RunMode::Run => control_run_power(pd, on),
RunMode::Sleep => control_sleep_power(pd, on),
RunMode::DeepSleep => control_deep_sleep_power(pd, on),
}
nop();
nop();
nop();
}
fn control_run_power(pd: Domain, on: bool) {
let p = unsafe { &*tm4c123x::SYSCTL::ptr() };
match pd {
Domain::Watchdog1 => unsafe { bb::change_bit(&p.rcgcwd, 1, on) },
Domain::Watchdog0 => unsafe { bb::change_bit(&p.rcgcwd, 0, on) },
Domain::Timer5 => unsafe { bb::change_bit(&p.rcgctimer, 5, on) },
Domain::Timer4 => unsafe { bb::change_bit(&p.rcgctimer, 4, on) },
Domain::Timer3 => unsafe { bb::change_bit(&p.rcgctimer, 3, on) },
Domain::Timer2 => unsafe { bb::change_bit(&p.rcgctimer, 2, on) },
Domain::Timer1 => unsafe { bb::change_bit(&p.rcgctimer, 1, on) },
Domain::Timer0 => unsafe { bb::change_bit(&p.rcgctimer, 0, on) },
Domain::GpioF => unsafe { bb::change_bit(&p.rcgcgpio, 5, on) },
Domain::GpioE => unsafe { bb::change_bit(&p.rcgcgpio, 4, on) },
Domain::GpioD => unsafe { bb::change_bit(&p.rcgcgpio, 3, on) },
Domain::GpioC => unsafe { bb::change_bit(&p.rcgcgpio, 2, on) },
Domain::GpioB => unsafe { bb::change_bit(&p.rcgcgpio, 1, on) },
Domain::GpioA => unsafe { bb::change_bit(&p.rcgcgpio, 0, on) },
Domain::MicroDma => unsafe { bb::change_bit(&p.rcgcdma, 0, on) },
Domain::Hibernation => unsafe { bb::change_bit(&p.rcgchib, 0, on) },
Domain::Uart7 => unsafe { bb::change_bit(&p.rcgcuart, 7, on) },
Domain::Uart6 => unsafe { bb::change_bit(&p.rcgcuart, 6, on) },
Domain::Uart5 => unsafe { bb::change_bit(&p.rcgcuart, 5, on) },
Domain::Uart4 => unsafe { bb::change_bit(&p.rcgcuart, 4, on) },
Domain::Uart3 => unsafe { bb::change_bit(&p.rcgcuart, 3, on) },
Domain::Uart2 => unsafe { bb::change_bit(&p.rcgcuart, 2, on) },
Domain::Uart1 => unsafe { bb::change_bit(&p.rcgcuart, 1, on) },
Domain::Uart0 => unsafe { bb::change_bit(&p.rcgcuart, 0, on) },
Domain::Ssi3 => unsafe { bb::change_bit(&p.rcgcssi, 3, on) },
Domain::Ssi2 => unsafe { bb::change_bit(&p.rcgcssi, 2, on) },
Domain::Ssi1 => unsafe { bb::change_bit(&p.rcgcssi, 1, on) },
Domain::Ssi0 => unsafe { bb::change_bit(&p.rcgcssi, 0, on) },
Domain::I2c3 => unsafe { bb::change_bit(&p.rcgci2c, 3, on) },
Domain::I2c2 => unsafe { bb::change_bit(&p.rcgci2c, 2, on) },
Domain::I2c1 => unsafe { bb::change_bit(&p.rcgci2c, 1, on) },
Domain::I2c0 => unsafe { bb::change_bit(&p.rcgci2c, 0, on) },
Domain::Usb => unsafe { bb::change_bit(&p.rcgcusb, 0, on) },
Domain::Can => unsafe { bb::change_bit(&p.rcgccan, 0, on) },
Domain::Adc1 => unsafe { bb::change_bit(&p.rcgcadc, 1, on) },
Domain::Adc0 => unsafe { bb::change_bit(&p.rcgcadc, 0, on) },
Domain::AnalogComparator => unsafe { bb::change_bit(&p.rcgcacmp, 0, on) },
Domain::Eeprom => unsafe { bb::change_bit(&p.rcgceeprom, 0, on) },
Domain::WideTimer5 => unsafe { bb::change_bit(&p.rcgcwtimer, 5, on) },
Domain::WideTimer4 => unsafe { bb::change_bit(&p.rcgcwtimer, 4, on) },
Domain::WideTimer3 => unsafe { bb::change_bit(&p.rcgcwtimer, 3, on) },
Domain::WideTimer2 => unsafe { bb::change_bit(&p.rcgcwtimer, 2, on) },
Domain::WideTimer1 => unsafe { bb::change_bit(&p.rcgcwtimer, 1, on) },
Domain::WideTimer0 => unsafe { bb::change_bit(&p.rcgcwtimer, 0, on) },
Domain::Pwm0 => unsafe { bb::change_bit(&p.rcgcpwm, 0, on) },
Domain::Pwm1 => unsafe { bb::change_bit(&p.rcgcpwm, 1, on) },
}
}
fn control_sleep_power(pd: Domain, on: bool) {
let p = unsafe { &*tm4c123x::SYSCTL::ptr() };
match pd {
Domain::Watchdog1 => unsafe { bb::change_bit(&p.scgcwd, 1, on) },
Domain::Watchdog0 => unsafe { bb::change_bit(&p.scgcwd, 0, on) },
Domain::Timer5 => unsafe { bb::change_bit(&p.scgctimer, 5, on) },
Domain::Timer4 => unsafe { bb::change_bit(&p.scgctimer, 4, on) },
Domain::Timer3 => unsafe { bb::change_bit(&p.scgctimer, 3, on) },
Domain::Timer2 => unsafe { bb::change_bit(&p.scgctimer, 2, on) },
Domain::Timer1 => unsafe { bb::change_bit(&p.scgctimer, 1, on) },
Domain::Timer0 => unsafe { bb::change_bit(&p.scgctimer, 0, on) },
Domain::GpioF => unsafe { bb::change_bit(&p.scgcgpio, 5, on) },
Domain::GpioE => unsafe { bb::change_bit(&p.scgcgpio, 4, on) },
Domain::GpioD => unsafe { bb::change_bit(&p.scgcgpio, 3, on) },
Domain::GpioC => unsafe { bb::change_bit(&p.scgcgpio, 2, on) },
Domain::GpioB => unsafe { bb::change_bit(&p.scgcgpio, 1, on) },
Domain::GpioA => unsafe { bb::change_bit(&p.scgcgpio, 0, on) },
Domain::MicroDma => unsafe { bb::change_bit(&p.scgcdma, 0, on) },
Domain::Hibernation => unsafe { bb::change_bit(&p.scgchib, 0, on) },
Domain::Uart7 => unsafe { bb::change_bit(&p.scgcuart, 7, on) },
Domain::Uart6 => unsafe { bb::change_bit(&p.scgcuart, 6, on) },
Domain::Uart5 => unsafe { bb::change_bit(&p.scgcuart, 5, on) },
Domain::Uart4 => unsafe { bb::change_bit(&p.scgcuart, 4, on) },
Domain::Uart3 => unsafe { bb::change_bit(&p.scgcuart, 3, on) },
Domain::Uart2 => unsafe { bb::change_bit(&p.scgcuart, 2, on) },
Domain::Uart1 => unsafe { bb::change_bit(&p.scgcuart, 1, on) },
Domain::Uart0 => unsafe { bb::change_bit(&p.scgcuart, 0, on) },
Domain::Ssi3 => unsafe { bb::change_bit(&p.scgcssi, 3, on) },
Domain::Ssi2 => unsafe { bb::change_bit(&p.scgcssi, 2, on) },
Domain::Ssi1 => unsafe { bb::change_bit(&p.scgcssi, 1, on) },
Domain::Ssi0 => unsafe { bb::change_bit(&p.scgcssi, 0, on) },
Domain::I2c3 => unsafe { bb::change_bit(&p.scgci2c, 3, on) },
Domain::I2c2 => unsafe { bb::change_bit(&p.scgci2c, 2, on) },
Domain::I2c1 => unsafe { bb::change_bit(&p.scgci2c, 1, on) },
Domain::I2c0 => unsafe { bb::change_bit(&p.scgci2c, 0, on) },
Domain::Usb => unsafe { bb::change_bit(&p.scgcusb, 0, on) },
Domain::Can => unsafe { bb::change_bit(&p.scgccan, 0, on) },
Domain::Adc1 => unsafe { bb::change_bit(&p.scgcadc, 1, on) },
Domain::Adc0 => unsafe { bb::change_bit(&p.scgcadc, 0, on) },
Domain::AnalogComparator => unsafe { bb::change_bit(&p.scgcacmp, 0, on) },
Domain::Eeprom => unsafe { bb::change_bit(&p.scgceeprom, 0, on) },
Domain::WideTimer5 => unsafe { bb::change_bit(&p.scgcwtimer, 5, on) },
Domain::WideTimer4 => unsafe { bb::change_bit(&p.scgcwtimer, 4, on) },
Domain::WideTimer3 => unsafe { bb::change_bit(&p.scgcwtimer, 3, on) },
Domain::WideTimer2 => unsafe { bb::change_bit(&p.scgcwtimer, 2, on) },
Domain::WideTimer1 => unsafe { bb::change_bit(&p.scgcwtimer, 1, on) },
Domain::WideTimer0 => unsafe { bb::change_bit(&p.scgcwtimer, 0, on) },
Domain::Pwm0 => unsafe { bb::change_bit(&p.scgcpwm, 0, on) },
Domain::Pwm1 => unsafe { bb::change_bit(&p.scgcpwm, 1, on) },
}
}
fn control_deep_sleep_power(pd: Domain, on: bool) {
let p = unsafe { &*tm4c123x::SYSCTL::ptr() };
match pd {
Domain::Watchdog1 => unsafe { bb::change_bit(&p.dcgcwd, 1, on) },
Domain::Watchdog0 => unsafe { bb::change_bit(&p.dcgcwd, 0, on) },
Domain::Timer5 => unsafe { bb::change_bit(&p.dcgctimer, 5, on) },
Domain::Timer4 => unsafe { bb::change_bit(&p.dcgctimer, 4, on) },
Domain::Timer3 => unsafe { bb::change_bit(&p.dcgctimer, 3, on) },
Domain::Timer2 => unsafe { bb::change_bit(&p.dcgctimer, 2, on) },
Domain::Timer1 => unsafe { bb::change_bit(&p.dcgctimer, 1, on) },
Domain::Timer0 => unsafe { bb::change_bit(&p.dcgctimer, 0, on) },
Domain::GpioF => unsafe { bb::change_bit(&p.dcgcgpio, 5, on) },
Domain::GpioE => unsafe { bb::change_bit(&p.dcgcgpio, 4, on) },
Domain::GpioD => unsafe { bb::change_bit(&p.dcgcgpio, 3, on) },
Domain::GpioC => unsafe { bb::change_bit(&p.dcgcgpio, 2, on) },
Domain::GpioB => unsafe { bb::change_bit(&p.dcgcgpio, 1, on) },
Domain::GpioA => unsafe { bb::change_bit(&p.dcgcgpio, 0, on) },
Domain::MicroDma => unsafe { bb::change_bit(&p.dcgcdma, 0, on) },
Domain::Hibernation => unsafe { bb::change_bit(&p.dcgchib, 0, on) },
Domain::Uart7 => unsafe { bb::change_bit(&p.dcgcuart, 7, on) },
Domain::Uart6 => unsafe { bb::change_bit(&p.dcgcuart, 6, on) },
Domain::Uart5 => unsafe { bb::change_bit(&p.dcgcuart, 5, on) },
Domain::Uart4 => unsafe { bb::change_bit(&p.dcgcuart, 4, on) },
Domain::Uart3 => unsafe { bb::change_bit(&p.dcgcuart, 3, on) },
Domain::Uart2 => unsafe { bb::change_bit(&p.dcgcuart, 2, on) },
Domain::Uart1 => unsafe { bb::change_bit(&p.dcgcuart, 1, on) },
Domain::Uart0 => unsafe { bb::change_bit(&p.dcgcuart, 0, on) },
Domain::Ssi3 => unsafe { bb::change_bit(&p.dcgcssi, 3, on) },
Domain::Ssi2 => unsafe { bb::change_bit(&p.dcgcssi, 2, on) },
Domain::Ssi1 => unsafe { bb::change_bit(&p.dcgcssi, 1, on) },
Domain::Ssi0 => unsafe { bb::change_bit(&p.dcgcssi, 0, on) },
Domain::I2c3 => unsafe { bb::change_bit(&p.dcgci2c, 3, on) },
Domain::I2c2 => unsafe { bb::change_bit(&p.dcgci2c, 2, on) },
Domain::I2c1 => unsafe { bb::change_bit(&p.dcgci2c, 1, on) },
Domain::I2c0 => unsafe { bb::change_bit(&p.dcgci2c, 0, on) },
Domain::Usb => unsafe { bb::change_bit(&p.dcgcusb, 0, on) },
Domain::Can => unsafe { bb::change_bit(&p.dcgccan, 0, on) },
Domain::Adc1 => unsafe { bb::change_bit(&p.dcgcadc, 1, on) },
Domain::Adc0 => unsafe { bb::change_bit(&p.dcgcadc, 0, on) },
Domain::AnalogComparator => unsafe { bb::change_bit(&p.dcgcacmp, 0, on) },
Domain::Eeprom => unsafe { bb::change_bit(&p.dcgceeprom, 0, on) },
Domain::WideTimer5 => unsafe { bb::change_bit(&p.dcgcwtimer, 5, on) },
Domain::WideTimer4 => unsafe { bb::change_bit(&p.dcgcwtimer, 4, on) },
Domain::WideTimer3 => unsafe { bb::change_bit(&p.dcgcwtimer, 3, on) },
Domain::WideTimer2 => unsafe { bb::change_bit(&p.dcgcwtimer, 2, on) },
Domain::WideTimer1 => unsafe { bb::change_bit(&p.dcgcwtimer, 1, on) },
Domain::WideTimer0 => unsafe { bb::change_bit(&p.dcgcwtimer, 0, on) },
Domain::Pwm0 => unsafe { bb::change_bit(&p.dcgcpwm, 0, on) },
Domain::Pwm1 => unsafe { bb::change_bit(&p.dcgcpwm, 1, on) },
}
}
pub trait SysctlExt {
fn constrain(self) -> Sysctl;
}
impl SysctlExt for tm4c123x::SYSCTL {
fn constrain(self) -> Sysctl {
Sysctl {
power_control: PowerControl { _0: () },
clock_setup: ClockSetup {
oscillator: Oscillator::PrecisionInternal(SystemClock::UseOscillator(Divider::_1)),
_0: (),
},
}
}
}
impl ClockSetup {
pub fn freeze(self) -> Clocks {
let p = unsafe { &*tm4c123x::SYSCTL::ptr() };
let mut osc = 0u32;
let mut sysclk = 0u32;
match self.oscillator {
Oscillator::Main(crystal_frequency, system_clock) => {
p.rcc.write(|w| {
w.bypass().set_bit();
w.oscsrc().main();
w.moscdis().clear_bit();
unsafe {
w.sysdiv().bits(0x00);
}
osc = match crystal_frequency {
CrystalFrequency::_4mhz => {
w.xtal()._4mhz();
4_000_000
}
CrystalFrequency::_4_09mhz => {
w.xtal()._4_09mhz();
4_090_000
}
CrystalFrequency::_4_91mhz => {
w.xtal()._4_91mhz();
4_910_000
}
CrystalFrequency::_5mhz => {
w.xtal()._5mhz();
5_000_000
}
CrystalFrequency::_5_12mhz => {
w.xtal()._5_12mhz();
5_120_000
}
CrystalFrequency::_6mhz => {
w.xtal()._6mhz();
6_000_000
}
CrystalFrequency::_6_14mhz => {
w.xtal()._6_14mhz();
6_140_000
}
CrystalFrequency::_7_37mhz => {
w.xtal()._7_37mhz();
7_370_000
}
CrystalFrequency::_8mhz => {
w.xtal()._8mhz();
8_000_000
}
CrystalFrequency::_8_19mhz => {
w.xtal()._8_19mhz();
8_190_000
}
CrystalFrequency::_10mhz => {
w.xtal()._10mhz();
10_000_000
}
CrystalFrequency::_12mhz => {
w.xtal()._12mhz();
12_000_000
}
CrystalFrequency::_12_2mhz => {
w.xtal()._12_2mhz();
12_200_000
}
CrystalFrequency::_13_5mhz => {
w.xtal()._13_5mhz();
13_500_000
}
CrystalFrequency::_14_3mhz => {
w.xtal()._14_3mhz();
14_300_000
}
CrystalFrequency::_16mhz => {
w.xtal()._16mhz();
16_000_000
}
CrystalFrequency::_16_3mhz => {
w.xtal()._16_3mhz();
16_300_000
}
CrystalFrequency::_18mhz => {
w.xtal()._18mhz();
18_000_000
}
CrystalFrequency::_20mhz => {
w.xtal()._20mhz();
20_000_000
}
CrystalFrequency::_24mhz => {
w.xtal()._24mhz();
24_000_000
}
CrystalFrequency::_25mhz => {
w.xtal()._25mhz();
25_000_000
}
};
if let SystemClock::UseOscillator(div) = system_clock {
w.usesysdiv().set_bit();
unsafe {
w.sysdiv().bits(div as u8 - 1);
}
sysclk = osc / (div as u32);
} else {
w.usesysdiv().clear_bit();
unsafe {
w.sysdiv().bits(0);
}
sysclk = osc;
}
w
});
}
Oscillator::PrecisionInternal(system_clock) => {
osc = 16_000_000;
p.rcc.write(|w| {
w.bypass().set_bit();
w.oscsrc().int();
w.moscdis().set_bit();
if let SystemClock::UseOscillator(div) = system_clock {
w.usesysdiv().set_bit();
unsafe {
w.sysdiv().bits(div as u8 - 1);
}
sysclk = osc / (div as u32);
} else {
w.usesysdiv().clear_bit();
unsafe {
w.sysdiv().bits(0);
}
sysclk = osc;
}
w
});
}
Oscillator::PrecisionInternalDiv4(div) => {
osc = 4_000_000;
p.rcc.write(|w| {
w.bypass().set_bit();
w.oscsrc().int4();
w.moscdis().set_bit();
w.usesysdiv().set_bit();
unsafe {
w.sysdiv().bits(div as u8 - 1);
}
sysclk = osc / (div as u32);
w
});
}
Oscillator::LowFrequencyInternal(div) => {
osc = 30_000;
p.rcc.write(|w| {
w.bypass().set_bit();
w.oscsrc()._30();
w.moscdis().set_bit();
w.usesysdiv().set_bit();
unsafe {
w.sysdiv().bits(div as u8 - 1);
}
sysclk = osc / (div as u32);
w
});
}
}
match self.oscillator {
Oscillator::PrecisionInternal(SystemClock::UsePll(f))
| Oscillator::Main(_, SystemClock::UsePll(f)) => {
p.misc.write(|w| w.plllmis().set_bit());
p.rcc.modify(|_, w| w.pwrdn().clear_bit());
while p.pllstat.read().lock().bit_is_clear() {
nop();
}
match f {
PllOutputFrequency::_80_00mhz => {
p.rcc2.write(|w| {
w.usercc2().set_bit();
w.div400().set_bit();
w.sysdiv2lsb().clear_bit();
unsafe { w.sysdiv2().bits(2) };
w.bypass2().clear_bit();
w
});
sysclk = 400_000_000u32 / 5;
}
_ => {
p.rcc.modify(|_, w| {
unsafe { w.sysdiv().bits(f as u8) };
w.usesysdiv().set_bit();
w.bypass().clear_bit();
w
});
sysclk = 400_000_000u32 / (2 * ((f as u32) + 1));
}
}
}
_ => {}
}
Clocks {
osc: osc.hz(),
sysclk: sysclk.hz(),
}
}
}
impl PowerControl {}
pub mod chip_id {
pub use tm4c_hal::sysctl::chip_id::*;
pub fn get() -> Result<ChipId, Error> {
let p = unsafe { &*tm4c123x::SYSCTL::ptr() };
let did0 = p.did0.read();
if did0.ver().bits() != 0x01 {
return Err(Error::UnknownDid0Ver(did0.ver().bits()));
}
let device_class = match did0.class().bits() {
0x05 => DeviceClass::StellarisBlizzard,
0x0a => DeviceClass::Snowflake,
_ => DeviceClass::Unknown,
};
let major = did0.maj().bits();
let minor = did0.min().bits();
let did1 = p.did1.read();
if did1.ver().bits() != 0x01 {
return Err(Error::UnknownDid1Ver(did1.ver().bits()));
}
let part_no = match did1.prtno().bits() {
0x04 => PartNo::Lm4f120h5qr,
0xA1 => PartNo::Tm4c123gh6pm,
e => PartNo::Unknown(e),
};
let pin_count = match did1.pincnt().bits() {
0 => PinCount::_28,
1 => PinCount::_48,
2 => PinCount::_100,
3 => PinCount::_64,
4 => PinCount::_144,
5 => PinCount::_157,
6 => PinCount::_168,
_ => PinCount::Unknown,
};
let temp_range = match did1.temp().bits() {
0 => TempRange::Commercial,
1 => TempRange::Industrial,
2 => TempRange::Extended,
3 => TempRange::IndustrialOrExtended,
_ => TempRange::Unknown,
};
let package = match did1.pkg().bits() {
0 => Package::Soic,
1 => Package::Lqfp,
2 => Package::Bga,
_ => Package::Unknown,
};
let rohs_compliant = did1.rohs().bit_is_set();
let qualification = match did1.qual().bits() {
0 => Qualification::EngineeringSample,
1 => Qualification::PilotProduction,
2 => Qualification::FullyQualified,
_ => Qualification::Unknown,
};
Ok(ChipId {
device_class,
major,
minor,
pin_count,
temp_range,
package,
rohs_compliant,
qualification,
part_no,
})
}
}