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

Lines changed: 34 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 30 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy