Skip to content

Commit

Permalink
Fix powman_test so it runs on Arm and RISC-V.
Browse files Browse the repository at this point in the history
1) Use the Machine Timer, not the cycle counter
2) Use the hal::arch module to control interrupts
3) Write a MachineExternal interrupt handler which asks Xh3irq which interrupt to run next, and then runs it.

Note: we lose the macros that do that static-mut hack for us. Maybe we can add that back in later.
  • Loading branch information
thejpster committed Sep 1, 2024
1 parent 3dfa983 commit 03e56ec
Show file tree
Hide file tree
Showing 4 changed files with 569 additions and 79 deletions.
1 change: 1 addition & 0 deletions rp235x-hal-examples/riscv_examples.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pio_dma
pio_proc_blink
pio_side_set
pio_synchronized
powman_test
pwm_blink
pwm_blink_embedded_hal_1
rom_funcs
Expand Down
45 changes: 45 additions & 0 deletions rp235x-hal-examples/rp235x_riscv.x
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,51 @@ PROVIDE(__pre_init = default_pre_init);
/* A PAC/HAL defined routine that should initialize custom interrupt controller if needed. */
PROVIDE(_setup_interrupts = default_setup_interrupts);

PROVIDE(TIMER0_IRQ_0 = DefaultIrqHandler);
PROVIDE(TIMER0_IRQ_1 = DefaultIrqHandler);
PROVIDE(TIMER0_IRQ_2 = DefaultIrqHandler);
PROVIDE(TIMER0_IRQ_3 = DefaultIrqHandler);
PROVIDE(TIMER1_IRQ_0 = DefaultIrqHandler);
PROVIDE(TIMER1_IRQ_1 = DefaultIrqHandler);
PROVIDE(TIMER1_IRQ_2 = DefaultIrqHandler);
PROVIDE(TIMER1_IRQ_3 = DefaultIrqHandler);
PROVIDE(PWM_IRQ_WRAP_0 = DefaultIrqHandler);
PROVIDE(PWM_IRQ_WRAP_1 = DefaultIrqHandler);
PROVIDE(DMA_IRQ_0 = DefaultIrqHandler);
PROVIDE(DMA_IRQ_1 = DefaultIrqHandler);
PROVIDE(DMA_IRQ_2 = DefaultIrqHandler);
PROVIDE(DMA_IRQ_3 = DefaultIrqHandler);
PROVIDE(USBCTRL_IRQ = DefaultIrqHandler);
PROVIDE(PIO0_IRQ_0 = DefaultIrqHandler);
PROVIDE(PIO0_IRQ_1 = DefaultIrqHandler);
PROVIDE(PIO1_IRQ_0 = DefaultIrqHandler);
PROVIDE(PIO1_IRQ_1 = DefaultIrqHandler);
PROVIDE(PIO2_IRQ_0 = DefaultIrqHandler);
PROVIDE(PIO2_IRQ_1 = DefaultIrqHandler);
PROVIDE(IO_IRQ_BANK0 = DefaultIrqHandler);
PROVIDE(IO_IRQ_BANK0_NS = DefaultIrqHandler);
PROVIDE(IO_IRQ_QSPI = DefaultIrqHandler);
PROVIDE(IO_IRQ_QSPI_NS = DefaultIrqHandler);
PROVIDE(SIO_IRQ_FIFO = DefaultIrqHandler);
PROVIDE(SIO_IRQ_BELL = DefaultIrqHandler);
PROVIDE(SIO_IRQ_FIFO_NS = DefaultIrqHandler);
PROVIDE(SIO_IRQ_BELL_NS = DefaultIrqHandler);
PROVIDE(SIO_IRQ_MTIMECMP = DefaultIrqHandler);
PROVIDE(CLOCKS_IRQ = DefaultIrqHandler);
PROVIDE(SPI0_IRQ = DefaultIrqHandler);
PROVIDE(SPI1_IRQ = DefaultIrqHandler);
PROVIDE(UART0_IRQ = DefaultIrqHandler);
PROVIDE(UART1_IRQ = DefaultIrqHandler);
PROVIDE(ADC_IRQ_FIFO = DefaultIrqHandler);
PROVIDE(I2C0_IRQ = DefaultIrqHandler);
PROVIDE(I2C1_IRQ = DefaultIrqHandler);
PROVIDE(OTP_IRQ = DefaultIrqHandler);
PROVIDE(TRNG_IRQ = DefaultIrqHandler);
PROVIDE(PLL_SYS_IRQ = DefaultIrqHandler);
PROVIDE(PLL_USB_IRQ = DefaultIrqHandler);
PROVIDE(POWMAN_IRQ_POW = DefaultIrqHandler);
PROVIDE(POWMAN_IRQ_TIMER = DefaultIrqHandler);

/* # Multi-processing hook function
fn _mp_hook() -> bool;

Expand Down
59 changes: 21 additions & 38 deletions rp235x-hal-examples/src/bin/powman_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ use rp235x_hal::{
uart::{DataBits, StopBits, UartConfig, UartPeripheral},
};

use cortex_m_rt::exception;
use pac::interrupt;

// Some traits we need
use core::fmt::Write;
use hal::fugit::RateExtU32;
Expand Down Expand Up @@ -67,7 +64,7 @@ impl GlobalUart {

/// Entry point to our bare-metal application.
///
/// The `#[hal::entry]` macro ensures the Cortex-M start-up code calls this function
/// The `#[hal::entry]` macro ensures the start-up code calls this function
/// as soon as all global variables and the spinlock are initialised.
///
/// The function configures the rp235x peripherals, then writes to the UART in
Expand All @@ -76,11 +73,6 @@ impl GlobalUart {
fn main() -> ! {
// Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap();
let mut cp = cortex_m::Peripherals::take().unwrap();

// Enable the cycle counter
cp.DCB.enable_trace();
cp.DWT.enable_cycle_counter();

// Set up the watchdog driver - needed by the clock setup code
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);
Expand All @@ -99,6 +91,8 @@ fn main() -> ! {

// The single-cycle I/O block controls our GPIO pins
let sio = hal::Sio::new(pac.SIO);
let mut mtimer = sio.machine_timer;
mtimer.set_enabled(true);

// Set the pins to their default state
let pins = gpio::Pins::new(
Expand Down Expand Up @@ -131,29 +125,30 @@ fn main() -> ! {
_ = writeln!(&GLOBAL_UART, "AOT time: 0x{:016x}", powman.aot_get_time());

unsafe {
cortex_m::peripheral::NVIC::unmask(pac::Interrupt::POWMAN_IRQ_TIMER);
hal::arch::interrupt_unmask(pac::Interrupt::POWMAN_IRQ_TIMER);
hal::arch::interrupt_enable();
}

_ = writeln!(&GLOBAL_UART, "Starting AOT...");
powman.aot_start();
// we don't know what oscillator we're on, so give it time to start whatever it is
cortex_m::asm::delay(150_000);
hal::arch::delay(150_000);
print_aot_status(&mut powman);
rollover_test(&mut powman);
loop_test(&mut powman);
loop_test(&mut powman, &mtimer);
alarm_test(&mut powman);

let source = AotClockSource::Xosc(FractionalFrequency::from_hz(12_000_000));
_ = writeln!(&GLOBAL_UART, "Switching AOT to {}", source);
powman.aot_set_clock(source).expect("selecting XOSC");
print_aot_status(&mut powman);
loop_test(&mut powman);
loop_test(&mut powman, &mtimer);

let source = AotClockSource::Lposc(FractionalFrequency::from_hz(32768));
_ = writeln!(&GLOBAL_UART, "Switching AOT to {}", source);
powman.aot_set_clock(source).expect("selecting LPOSC");
print_aot_status(&mut powman);
loop_test(&mut powman);
loop_test(&mut powman, &mtimer);

_ = writeln!(&GLOBAL_UART, "Rebooting now");

Expand Down Expand Up @@ -202,7 +197,7 @@ fn rollover_test(powman: &mut Powman) {
}

/// In this function, we see how long it takes to pass a certain number of ticks.
fn loop_test(powman: &mut Powman) {
fn loop_test(powman: &mut Powman, mtimer: &hal::sio::MachineTimer) {
let start_loop = 0;
let end_loop = 2_000; // 2 seconds
_ = writeln!(
Expand All @@ -214,24 +209,24 @@ fn loop_test(powman: &mut Powman) {
powman.aot_set_time(start_loop);
powman.aot_start();

let start_clocks = cortex_m::peripheral::DWT::cycle_count();
let start_clocks = mtimer.read();
loop {
let now = powman.aot_get_time();
if now == end_loop {
break;
}
}
let end_clocks = cortex_m::peripheral::DWT::cycle_count();
// Compare our AOT against our CPU clock speed
let delta_clocks = end_clocks.wrapping_sub(start_clocks) as u64;
let end_clocks = mtimer.read();
// Compare our AOT against our Machine Timer
let delta_clocks = end_clocks.wrapping_sub(start_clocks);
let delta_ticks = end_loop - start_loop;
let cycles_per_tick = delta_clocks / delta_ticks;
// Assume we're running at 150 MHz
let ms_per_tick = (cycles_per_tick as f32 * 1000.0) / 150_000_000.0;
// Assume we're running at 1 MHz MTimer
let ms_per_tick = (cycles_per_tick as f32 * 1000.0) / 1_000_000.0;
let percent = ((ms_per_tick - 1.0) / 1.0) * 100.0;
_ = writeln!(
&GLOBAL_UART,
"Loop complete ... {delta_ticks} ticks in {delta_clocks} CPU clock cycles = {cycles_per_tick} cycles/tick ~= {ms_per_tick} ms/tick ({percent:.3}%)",
"Loop complete ... {delta_ticks} ticks in {delta_clocks} MTimer cycles = {cycles_per_tick} cycles/tick ~= {ms_per_tick} ms/tick ({percent:.3}%)",
)
;
}
Expand All @@ -258,8 +253,9 @@ fn alarm_test(powman: &mut Powman) {
&GLOBAL_UART,
"Sleeping until alarm (* = wakeup, ! = POWMAN interrupt)...",
);

while !powman.aot_alarm_ringing() {
cortex_m::asm::wfe();
hal::arch::wfe();
_ = write!(&GLOBAL_UART, "*",);
}

Expand All @@ -278,25 +274,12 @@ fn alarm_test(powman: &mut Powman) {
_ = writeln!(&GLOBAL_UART, "Alarm cleared OK");
}

#[interrupt]
#[no_mangle]
#[allow(non_snake_case)]
fn POWMAN_IRQ_TIMER() {
Powman::static_aot_alarm_interrupt_disable();
_ = write!(&GLOBAL_UART, "!");
cortex_m::asm::sev();
}

#[exception]
unsafe fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! {
let _ = writeln!(&GLOBAL_UART, "HARD FAULT:\n{:#?}", ef);

hal::reboot::reboot(
hal::reboot::RebootKind::BootSel {
msd_disabled: false,
picoboot_disabled: false,
},
hal::reboot::RebootArch::Normal,
);
hal::arch::sev();
}

#[panic_handler]
Expand Down
Loading

0 comments on commit 03e56ec

Please sign in to comment.