From fa15ae4503d87933c619a32110f8bd5e8817aece Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 8 Aug 2024 22:26:37 +1000 Subject: [PATCH] rp2/machine_bitstream: Implement bitstream for RISC-V using mcycle. Signed-off-by: Damien George --- ports/rp2/machine_bitstream.c | 46 +++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/ports/rp2/machine_bitstream.c b/ports/rp2/machine_bitstream.c index 8240fdad6..4ef97f0c8 100644 --- a/ports/rp2/machine_bitstream.c +++ b/ports/rp2/machine_bitstream.c @@ -34,6 +34,25 @@ #define MP_HAL_BITSTREAM_NS_OVERHEAD (9) +#if PICO_RISCV + +__attribute__((naked)) void mcycle_init(void) { + __asm volatile ( + "li a0, 4\n" + "csrw mcountinhibit, a0\n" + "ret\n" + ); +} + +__attribute__((naked)) uint32_t mcycle_get(void) { + __asm volatile ( + "csrr a0, mcycle\n" + "ret\n" + ); +} + +#endif + void __time_critical_func(machine_bitstream_high_low)(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len) { uint32_t fcpu_mhz = mp_hal_get_cpu_freq() / 1000000; // Convert ns to clock ticks [high_time_0, period_0, high_time_1, period_1]. @@ -49,14 +68,16 @@ void __time_critical_func(machine_bitstream_high_low)(mp_hal_pin_obj_t pin, uint } mp_hal_pin_output(pin); + uint32_t irq_state = mp_hal_quiet_timing_enter(); + + #if PICO_ARM + // Set systick reset value. systick_hw->rvr = 0x00FFFFFF; // Enable the systick counter, source CPU clock. systick_hw->csr = 5; - uint32_t irq_state = mp_hal_quiet_timing_enter(); - for (size_t i = 0; i < len; ++i) { uint8_t b = buf[i]; for (size_t j = 0; j < 8; ++j) { @@ -72,6 +93,27 @@ void __time_critical_func(machine_bitstream_high_low)(mp_hal_pin_obj_t pin, uint } } + #elif PICO_RISCV + + mcycle_init(); + + for (size_t i = 0; i < len; ++i) { + uint8_t b = buf[i]; + for (size_t j = 0; j < 8; ++j) { + uint32_t *t = &timing_ns[b >> 6 & 2]; + uint32_t start_ticks = mcycle_get(); + mp_hal_pin_high(pin); + while ((mcycle_get() - start_ticks) < t[0]) { + } + b <<= 1; + mp_hal_pin_low(pin); + while ((mcycle_get() - start_ticks) < t[1]) { + } + } + } + + #endif + mp_hal_quiet_timing_exit(irq_state); }