Skip to content

Commit dabb0aa

Browse files
authored
Merge pull request #10049 from jepler/keep-dma-irq-enabled-rp2350
raspberrypi: Don't block DMA_IRQ_1 during common_hal_mcu_disable_interrupts
2 parents 255eea9 + f331a85 commit dabb0aa

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

ports/raspberrypi/common-hal/microcontroller/__init__.c

+34
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@
2323
#include "src/rp2_common/hardware_sync/include/hardware/sync.h"
2424

2525
#include "hardware/watchdog.h"
26+
#include "hardware/irq.h"
2627

2728
void common_hal_mcu_delay_us(uint32_t delay) {
2829
mp_hal_delay_us(delay);
2930
}
3031

3132
volatile uint32_t nesting_count = 0;
33+
#ifdef PICO_RP2040
3234
void common_hal_mcu_disable_interrupts(void) {
3335
// We don't use save_and_disable_interrupts() from the sdk because we don't want to worry about PRIMASK.
3436
// This is what we do on the SAMD21 via CMSIS.
@@ -48,6 +50,38 @@ void common_hal_mcu_enable_interrupts(void) {
4850
__dmb();
4951
asm volatile ("cpsie i" : : : "memory");
5052
}
53+
#else
54+
#include "src/rp2_common/cmsis/stub/CMSIS/Device/RP2350/Include/RP2350.h"
55+
#define PICO_ELEVATED_IRQ_PRIORITY (0x60) // between PICO_DEFAULT and PIOCO_HIGHEST_IRQ_PRIORITY
56+
static uint32_t oldBasePri = 0; // 0 (default) masks nothing, other values mask equal-or-larger priority values
57+
void common_hal_mcu_disable_interrupts(void) {
58+
if (nesting_count == 0) {
59+
// We must keep DMA_IRQ_1 (reserved for pico dvi) enabled at all times,
60+
// including during flash writes. Do this by setting the priority mask (BASEPRI
61+
// register).
62+
// grab old base priority
63+
oldBasePri = __get_BASEPRI();
64+
// and set the new one
65+
__set_BASEPRI_MAX(PICO_ELEVATED_IRQ_PRIORITY);
66+
__isb(); // Instruction synchronization barrier
67+
}
68+
nesting_count++;
69+
}
70+
71+
void common_hal_mcu_enable_interrupts(void) {
72+
uint32_t my_interrupts = save_and_disable_interrupts();
73+
if (nesting_count == 0) {
74+
reset_into_safe_mode(SAFE_MODE_INTERRUPT_ERROR);
75+
}
76+
nesting_count--;
77+
if (nesting_count == 0) {
78+
// return to the old priority setting
79+
__set_BASEPRI(oldBasePri);
80+
__isb(); // Instruction synchronization barrier
81+
}
82+
restore_interrupts(my_interrupts);
83+
}
84+
#endif
5185

5286
static bool next_reset_to_bootloader = false;
5387

ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c

+1
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self,
430430
dma_hw->inte1 = (1u << self->dma_pixel_channel);
431431
irq_set_exclusive_handler(DMA_IRQ_1, dma_irq_handler);
432432
irq_set_enabled(DMA_IRQ_1, true);
433+
irq_set_priority(DMA_IRQ_1, PICO_HIGHEST_IRQ_PRIORITY);
433434

434435
bus_ctrl_hw->priority = BUSCTRL_BUS_PRIORITY_DMA_W_BITS | BUSCTRL_BUS_PRIORITY_DMA_R_BITS;
435436

ports/raspberrypi/supervisor/port.c

+30
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
#include "pico/bootrom.h"
5353
#include "hardware/watchdog.h"
5454

55+
#ifdef PICO_RP2350
56+
#include "src/rp2_common/cmsis/stub/CMSIS/Device/RP2350/Include/RP2350.h"
57+
#endif
58+
5559
#include "supervisor/shared/serial.h"
5660

5761
#include "tusb.h"
@@ -497,6 +501,7 @@ void port_interrupt_after_ticks(uint32_t ticks) {
497501
}
498502

499503
void port_idle_until_interrupt(void) {
504+
#ifdef PICO_RP2040
500505
common_hal_mcu_disable_interrupts();
501506
#if CIRCUITPY_USB_HOST
502507
if (!background_callback_pending() && !tud_task_event_ready() && !tuh_task_event_ready() && !_woken_up) {
@@ -507,6 +512,31 @@ void port_idle_until_interrupt(void) {
507512
__WFI();
508513
}
509514
common_hal_mcu_enable_interrupts();
515+
#else
516+
// because we use interrupt priority, don't use
517+
// common_hal_mcu_disable_interrupts (because an interrupt masked by
518+
// BASEPRI will not occur)
519+
uint32_t state = save_and_disable_interrupts();
520+
521+
// Ensure BASEPRI is at 0...
522+
uint32_t oldBasePri = __get_BASEPRI();
523+
__set_BASEPRI(0);
524+
__isb();
525+
#if CIRCUITPY_USB_HOST
526+
if (!background_callback_pending() && !tud_task_event_ready() && !tuh_task_event_ready() && !_woken_up) {
527+
#else
528+
if (!background_callback_pending() && !tud_task_event_ready() && !_woken_up) {
529+
#endif
530+
__DSB();
531+
__WFI();
532+
}
533+
534+
// and restore basepri before reenabling interrupts
535+
__set_BASEPRI(oldBasePri);
536+
__isb();
537+
538+
restore_interrupts(state);
539+
#endif
510540
}
511541

512542
/**

0 commit comments

Comments
 (0)