Skip to content

Commit 03e56ec

Browse files
committed
Fix powman_test so it runs on Arm and RISC-V.
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.
1 parent 3dfa983 commit 03e56ec

File tree

4 files changed

+569
-79
lines changed

4 files changed

+569
-79
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: 21 additions & 38 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,30 @@ 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::interrupt_unmask(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+
hal::arch::delay(150_000);
141136
print_aot_status(&mut powman);
142137
rollover_test(&mut powman);
143-
loop_test(&mut powman);
138+
loop_test(&mut powman, &mtimer);
144139
alarm_test(&mut powman);
145140

146141
let source = AotClockSource::Xosc(FractionalFrequency::from_hz(12_000_000));
147142
_ = writeln!(&GLOBAL_UART, "Switching AOT to {}", source);
148143
powman.aot_set_clock(source).expect("selecting XOSC");
149144
print_aot_status(&mut powman);
150-
loop_test(&mut powman);
145+
loop_test(&mut powman, &mtimer);
151146

152147
let source = AotClockSource::Lposc(FractionalFrequency::from_hz(32768));
153148
_ = writeln!(&GLOBAL_UART, "Switching AOT to {}", source);
154149
powman.aot_set_clock(source).expect("selecting LPOSC");
155150
print_aot_status(&mut powman);
156-
loop_test(&mut powman);
151+
loop_test(&mut powman, &mtimer);
157152

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

@@ -202,7 +197,7 @@ fn rollover_test(powman: &mut Powman) {
202197
}
203198

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

217-
let start_clocks = cortex_m::peripheral::DWT::cycle_count();
212+
let start_clocks = mtimer.read();
218213
loop {
219214
let now = powman.aot_get_time();
220215
if now == end_loop {
221216
break;
222217
}
223218
}
224-
let end_clocks = cortex_m::peripheral::DWT::cycle_count();
225-
// Compare our AOT against our CPU clock speed
226-
let delta_clocks = end_clocks.wrapping_sub(start_clocks) as u64;
219+
let end_clocks = mtimer.read();
220+
// Compare our AOT against our Machine Timer
221+
let delta_clocks = end_clocks.wrapping_sub(start_clocks);
227222
let delta_ticks = end_loop - start_loop;
228223
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;
224+
// Assume we're running at 1 MHz MTimer
225+
let ms_per_tick = (cycles_per_tick as f32 * 1000.0) / 1_000_000.0;
231226
let percent = ((ms_per_tick - 1.0) / 1.0) * 100.0;
232227
_ = writeln!(
233228
&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}%)",
229+
"Loop complete ... {delta_ticks} ticks in {delta_clocks} MTimer cycles = {cycles_per_tick} cycles/tick ~= {ms_per_tick} ms/tick ({percent:.3}%)",
235230
)
236231
;
237232
}
@@ -258,8 +253,9 @@ fn alarm_test(powman: &mut Powman) {
258253
&GLOBAL_UART,
259254
"Sleeping until alarm (* = wakeup, ! = POWMAN interrupt)...",
260255
);
256+
261257
while !powman.aot_alarm_ringing() {
262-
cortex_m::asm::wfe();
258+
hal::arch::wfe();
263259
_ = write!(&GLOBAL_UART, "*",);
264260
}
265261

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

281-
#[interrupt]
277+
#[no_mangle]
282278
#[allow(non_snake_case)]
283279
fn POWMAN_IRQ_TIMER() {
284280
Powman::static_aot_alarm_interrupt_disable();
285281
_ = 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-
);
282+
hal::arch::sev();
300283
}
301284

302285
#[panic_handler]

0 commit comments

Comments
 (0)