Skip to content

Instantly share code, notes, and snippets.

@almindor
Created June 26, 2019 18:56
Show Gist options
  • Save almindor/79a627cd23e766d2b5c7c6696afe4e03 to your computer and use it in GitHub Desktop.
Save almindor/79a627cd23e766d2b5c7c6696afe4e03 to your computer and use it in GitHub Desktop.
#![no_std]
#![no_main]
/*
* Basic blinking LEDs example using pmu sleep
* for "sleep" in a loop. Blinks each led once and goes to the next one.
*/
extern crate panic_halt;
use riscv_rt::entry;
use hifive1::hal::prelude::*;
use hifive1::hal::e310x::Peripherals;
use hifive1::sprintln;
const PMU_KEY_VAL: u32 = 0x51F15E;
const SLEEP_PROGRAM: [u32; 8] = [
0x2F0, // assert corerst
0x3F0, // assert hfclkrst
0x3D0, // deassert pmu_out_1
0x3C0, // deassert pmu_out_0
0x3C0, // repeats
0x3C0,
0x3C0,
0x3C0,
];
const WAKE_PROGRAM: [u32; 8] = [
0x3F0, // assert all resets and enable all power supplies
0x2F8, // idle 2^8 cycles, then deassert hfclkrst
0x030, // deassert corerst and padrst
0x030, // repeats
0x030,
0x030,
0x030,
0x030,
];
#[entry]
fn main() -> ! {
let p = Peripherals::take().unwrap();
let gpio = p.GPIO0.split();
// Configure clocks
let clocks = hifive1::clock::configure(p.PRCI, p.AONCLK, 320.mhz().into());
// Configure UART for stdout
hifive1::stdout::configure(p.UART0, gpio.pin17, gpio.pin16, 115_200.bps(), clocks);
// set correct sleep and wake programs
unsafe {
for i in 0..7 {
p.PMU.pmukey.write(|w| w.bits(PMU_KEY_VAL));
p.PMU.pmusleeppm[i].write(|w| w.bits(SLEEP_PROGRAM[i]));
// sprintln!("Set sleep p[{}] = 0x{:X}", i, SLEEP_PROGRAM[i]);
p.PMU.pmukey.write(|w| w.bits(PMU_KEY_VAL));
p.PMU.pmuwakepm[i].write(|w| w.bits(WAKE_PROGRAM[i]));
// sprintln!("Set wake p[{}] = 0x{:X}", i, WAKE_PROGRAM[i]);
}
}
// let mut i = 0;
// for sr in &p.PMU.pmusleeppm {
// sprintln!("Sleep instr{} = 0x{:X}", i, sr.read().bits());
// i = i + 1;
// }
// i = 0;
// for wr in &p.PMU.pmuwakepm {
// sprintln!("Wake instr{} = 0x{:X}", i, wr.read().bits());
// i = i + 1;
// }
sprintln!("Going to sleep");
unsafe {
// set interrupt source to RTC enabled, each pmu register needs key set before write
p.PMU.pmukey.write(|w| w.bits(PMU_KEY_VAL));
p.PMU.pmuie.write(|w| w.rtc().set_bit());
// set RTC clock scale to once per second for easy calculation
p.RTC.rtccfg.write(|w| w.scale().bits(15));
// get current RTC clock value scaled
let rtc_now = p.RTC.rtcs.read().bits();
// set RTC clock comparator
p.RTC.rtccmp.write(|w| w.bits(rtc_now + 15)); // 15 second delay on sleep
// go to sleep for 15s, need to set pmukey here as well
p.PMU.pmukey.write(|w| w.bits(PMU_KEY_VAL));
p.PMU.pmusleep.write(|w| w.bits(0xFFFF));
}
sprintln!("EOL");
loop {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment