Skip to content

Commit 1aa792e

Browse files
committed
Upgrade powman_test to work on RISC-V and Arm.
Interrupt priorities aren't supported yet, but handling a POWMAN timer IRQ from our new default MachineExternal interrupt handler seems to work OK. I also fixed the RISC-V WFE (or "block") instruction.
1 parent 0ed549b commit 1aa792e

File tree

4 files changed

+509
-54
lines changed

4 files changed

+509
-54
lines changed

rp235x-hal-examples/riscv_examples.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pio_dma
1717
pio_proc_blink
1818
pio_side_set
1919
pio_synchronized
20+
powman_test
2021
pwm_blink
2122
pwm_blink_embedded_hal_1
2223
rom_funcs

rp235x-hal-examples/rp235x_riscv.x

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,51 @@ PROVIDE(__pre_init = default_pre_init);
8080
/* A PAC/HAL defined routine that should initialize custom interrupt controller if needed. */
8181
PROVIDE(_setup_interrupts = default_setup_interrupts);
8282

83+
PROVIDE(TIMER0_IRQ_0 = DefaultIrqHandler);
84+
PROVIDE(TIMER0_IRQ_1 = DefaultIrqHandler);
85+
PROVIDE(TIMER0_IRQ_2 = DefaultIrqHandler);
86+
PROVIDE(TIMER0_IRQ_3 = DefaultIrqHandler);
87+
PROVIDE(TIMER1_IRQ_0 = DefaultIrqHandler);
88+
PROVIDE(TIMER1_IRQ_1 = DefaultIrqHandler);
89+
PROVIDE(TIMER1_IRQ_2 = DefaultIrqHandler);
90+
PROVIDE(TIMER1_IRQ_3 = DefaultIrqHandler);
91+
PROVIDE(PWM_IRQ_WRAP_0 = DefaultIrqHandler);
92+
PROVIDE(PWM_IRQ_WRAP_1 = DefaultIrqHandler);
93+
PROVIDE(DMA_IRQ_0 = DefaultIrqHandler);
94+
PROVIDE(DMA_IRQ_1 = DefaultIrqHandler);
95+
PROVIDE(DMA_IRQ_2 = DefaultIrqHandler);
96+
PROVIDE(DMA_IRQ_3 = DefaultIrqHandler);
97+
PROVIDE(USBCTRL_IRQ = DefaultIrqHandler);
98+
PROVIDE(PIO0_IRQ_0 = DefaultIrqHandler);
99+
PROVIDE(PIO0_IRQ_1 = DefaultIrqHandler);
100+
PROVIDE(PIO1_IRQ_0 = DefaultIrqHandler);
101+
PROVIDE(PIO1_IRQ_1 = DefaultIrqHandler);
102+
PROVIDE(PIO2_IRQ_0 = DefaultIrqHandler);
103+
PROVIDE(PIO2_IRQ_1 = DefaultIrqHandler);
104+
PROVIDE(IO_IRQ_BANK0 = DefaultIrqHandler);
105+
PROVIDE(IO_IRQ_BANK0_NS = DefaultIrqHandler);
106+
PROVIDE(IO_IRQ_QSPI = DefaultIrqHandler);
107+
PROVIDE(IO_IRQ_QSPI_NS = DefaultIrqHandler);
108+
PROVIDE(SIO_IRQ_FIFO = DefaultIrqHandler);
109+
PROVIDE(SIO_IRQ_BELL = DefaultIrqHandler);
110+
PROVIDE(SIO_IRQ_FIFO_NS = DefaultIrqHandler);
111+
PROVIDE(SIO_IRQ_BELL_NS = DefaultIrqHandler);
112+
PROVIDE(SIO_IRQ_MTIMECMP = DefaultIrqHandler);
113+
PROVIDE(CLOCKS_IRQ = DefaultIrqHandler);
114+
PROVIDE(SPI0_IRQ = DefaultIrqHandler);
115+
PROVIDE(SPI1_IRQ = DefaultIrqHandler);
116+
PROVIDE(UART0_IRQ = DefaultIrqHandler);
117+
PROVIDE(UART1_IRQ = DefaultIrqHandler);
118+
PROVIDE(ADC_IRQ_FIFO = DefaultIrqHandler);
119+
PROVIDE(I2C0_IRQ = DefaultIrqHandler);
120+
PROVIDE(I2C1_IRQ = DefaultIrqHandler);
121+
PROVIDE(OTP_IRQ = DefaultIrqHandler);
122+
PROVIDE(TRNG_IRQ = DefaultIrqHandler);
123+
PROVIDE(PLL_SYS_IRQ = DefaultIrqHandler);
124+
PROVIDE(PLL_USB_IRQ = DefaultIrqHandler);
125+
PROVIDE(POWMAN_IRQ_POW = DefaultIrqHandler);
126+
PROVIDE(POWMAN_IRQ_TIMER = DefaultIrqHandler);
127+
83128
/* # Multi-processing hook function
84129
fn _mp_hook() -> bool;
85130

rp235x-hal-examples/src/bin/powman_test.rs

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ use rp235x_hal::{
1313
uart::{DataBits, StopBits, UartConfig, UartPeripheral},
1414
};
1515

16-
use cortex_m_rt::exception;
17-
use pac::interrupt;
18-
1916
// Some traits we need
2017
use core::fmt::Write;
2118
use hal::fugit::RateExtU32;
@@ -67,7 +64,7 @@ impl GlobalUart {
6764

6865
/// Entry point to our bare-metal application.
6966
///
70-
/// The `#[hal::entry]` macro ensures the Cortex-M start-up code calls this function
67+
/// The `#[hal::entry]` macro ensures the start-up code calls this function
7168
/// as soon as all global variables and the spinlock are initialised.
7269
///
7370
/// The function configures the rp235x peripherals, then writes to the UART in
@@ -76,11 +73,6 @@ impl GlobalUart {
7673
fn main() -> ! {
7774
// Grab our singleton objects
7875
let mut pac = pac::Peripherals::take().unwrap();
79-
let mut cp = cortex_m::Peripherals::take().unwrap();
80-
81-
// Enable the cycle counter
82-
cp.DCB.enable_trace();
83-
cp.DWT.enable_cycle_counter();
8476

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

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

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

133127
unsafe {
134-
cortex_m::peripheral::NVIC::unmask(pac::Interrupt::POWMAN_IRQ_TIMER);
128+
hal::arch::enable_irq(pac::Interrupt::POWMAN_IRQ_TIMER);
129+
hal::arch::interrupt_enable();
135130
}
136131

137132
_ = writeln!(&GLOBAL_UART, "Starting AOT...");
138133
powman.aot_start();
139134
// we don't know what oscillator we're on, so give it time to start whatever it is
140-
cortex_m::asm::delay(150_000);
135+
for _ in 0..150_000 {
136+
hal::arch::nop();
137+
}
141138
print_aot_status(&mut powman);
142139
rollover_test(&mut powman);
143-
loop_test(&mut powman);
140+
loop_test(&mut powman, &mtimer);
144141
alarm_test(&mut powman);
145142

146143
let source = AotClockSource::Xosc(FractionalFrequency::from_hz(12_000_000));
147144
_ = writeln!(&GLOBAL_UART, "Switching AOT to {}", source);
148145
powman.aot_set_clock(source).expect("selecting XOSC");
149146
print_aot_status(&mut powman);
150-
loop_test(&mut powman);
147+
loop_test(&mut powman, &mtimer);
151148

152149
let source = AotClockSource::Lposc(FractionalFrequency::from_hz(32768));
153150
_ = writeln!(&GLOBAL_UART, "Switching AOT to {}", source);
154151
powman.aot_set_clock(source).expect("selecting LPOSC");
155152
print_aot_status(&mut powman);
156-
loop_test(&mut powman);
153+
loop_test(&mut powman, &mtimer);
157154

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

@@ -202,7 +199,7 @@ fn rollover_test(powman: &mut Powman) {
202199
}
203200

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

217-
let start_clocks = cortex_m::peripheral::DWT::cycle_count();
214+
let start_clocks = mtimer.read();
218215
loop {
219216
let now = powman.aot_get_time();
220217
if now == end_loop {
221218
break;
222219
}
223220
}
224-
let end_clocks = cortex_m::peripheral::DWT::cycle_count();
225-
// Compare our AOT against our CPU clock speed
221+
let end_clocks = mtimer.read();
222+
// Compare our AOT against our Machine Timer
226223
let delta_clocks = end_clocks.wrapping_sub(start_clocks) as u64;
227224
let delta_ticks = end_loop - start_loop;
228225
let cycles_per_tick = delta_clocks / delta_ticks;
229-
// Assume we're running at 150 MHz
230-
let ms_per_tick = (cycles_per_tick as f32 * 1000.0) / 150_000_000.0;
226+
// Assume we're running at 1 MHz MTimer
227+
let ms_per_tick = (cycles_per_tick as f32 * 1000.0) / 1_000_000.0;
231228
let percent = ((ms_per_tick - 1.0) / 1.0) * 100.0;
232229
_ = writeln!(
233230
&GLOBAL_UART,
234-
"Loop complete ... {delta_ticks} ticks in {delta_clocks} CPU clock cycles = {cycles_per_tick} cycles/tick ~= {ms_per_tick} ms/tick ({percent:.3}%)",
231+
"Loop complete ... {delta_ticks} ticks in {delta_clocks} MTimer cycles = {cycles_per_tick} cycles/tick ~= {ms_per_tick} ms/tick ({percent:.3}%)",
235232
)
236233
;
237234
}
@@ -258,8 +255,9 @@ fn alarm_test(powman: &mut Powman) {
258255
&GLOBAL_UART,
259256
"Sleeping until alarm (* = wakeup, ! = POWMAN interrupt)...",
260257
);
258+
261259
while !powman.aot_alarm_ringing() {
262-
cortex_m::asm::wfe();
260+
hal::arch::wfe();
263261
_ = write!(&GLOBAL_UART, "*",);
264262
}
265263

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

281-
#[interrupt]
279+
#[no_mangle]
282280
#[allow(non_snake_case)]
283281
fn POWMAN_IRQ_TIMER() {
284282
Powman::static_aot_alarm_interrupt_disable();
285283
_ = write!(&GLOBAL_UART, "!");
286-
cortex_m::asm::sev();
287-
}
288-
289-
#[exception]
290-
unsafe fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! {
291-
let _ = writeln!(&GLOBAL_UART, "HARD FAULT:\n{:#?}", ef);
292-
293-
hal::reboot::reboot(
294-
hal::reboot::RebootKind::BootSel {
295-
msd_disabled: false,
296-
picoboot_disabled: false,
297-
},
298-
hal::reboot::RebootArch::Normal,
299-
);
284+
hal::arch::sev();
300285
}
301286

302287
#[panic_handler]

0 commit comments

Comments
 (0)