use super::bb;
use cortex_m::asm::nop;
use time::{Hertz, U32Ext};
use tm4c123x;
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,
}
#[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,
}
#[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(Clone, Copy)]
pub struct Clocks {
pub osc: Hertz,
pub sysclk: Hertz,
}
#[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,
}
#[derive(Copy, Clone)]
pub enum RunMode {
Run,
Sleep,
DeepSleep,
}
#[derive(Copy, Clone)]
pub enum PowerState {
Off,
On,
}
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);
},
}
}
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) },
}
}
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) },
}
}
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) },
}
}
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);
}
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);
}
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);
}
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);
}
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 Clocks {
pub fn osc(&self) -> Hertz {
self.osc
}
pub fn sysclk(&self) -> Hertz {
self.sysclk
}
}
impl PowerControl {}
pub mod chip_id {
#[derive(Debug)]
pub enum Error {
UnknownDid0Ver(u8),
UnknownDid1Ver(u8),
}
#[derive(Debug)]
pub enum DeviceClass {
StellarisBlizzard,
Unknown,
}
#[derive(Debug)]
pub enum PinCount {
_28,
_48,
_100,
_64,
_144,
_157,
_168,
Unknown,
}
#[derive(Debug)]
pub enum TempRange {
Commercial,
Industrial,
Extended,
Unknown,
}
#[derive(Debug)]
pub enum Package {
Soic,
Lqfp,
Bga,
Unknown,
}
#[derive(Debug)]
pub enum Qualification {
EngineeringSample,
PilotProduction,
FullyQualified,
Unknown,
}
#[derive(Debug)]
pub enum PartNo {
Tm4c123gh6pm,
Lm4f120h5qr,
Unknown(u8),
}
#[derive(Debug)]
pub struct ChipId {
pub device_class: DeviceClass,
pub major: u8,
pub minor: u8,
pub pin_count: PinCount,
pub temp_range: TempRange,
pub package: Package,
pub rohs_compliant: bool,
pub qualification: Qualification,
pub part_no: PartNo,
}
pub fn get() -> Result<ChipId, Error> {
use tm4c123x;
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() {
5 => DeviceClass::StellarisBlizzard,
_ => 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,
_ => PartNo::Unknown(did1.prtno().bits()),
};
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,
_ => 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,
})
}
}