From b0d53dadb38ada44d8911f14c6f60573b41d7278 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 5 Mar 2024 10:27:36 +0000 Subject: [PATCH] Hub75: avoid clobbering shared IRQ handlers. MicroPython's DMA class uses shared IRQ handlers, which would be clobbered by Hub75's use of an exclusive handler. Additionally clean up some dead code (DMA_IRQ_1??), more epxlicitly clean up the claimed PIOs and programs, and do not use a fixed DMA channel. This seems to have fixed a bug whereupon Hub75 would hardlock on the 5th soft reset. --- drivers/hub75/hub75.cpp | 23 +++++++++-------------- drivers/hub75/hub75.hpp | 2 +- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/hub75/hub75.cpp b/drivers/hub75/hub75.cpp index 1d30c75af..a894b70df 100644 --- a/drivers/hub75/hub75.cpp +++ b/drivers/hub75/hub75.cpp @@ -113,12 +113,6 @@ void Hub75::FM6126A_setup() { void Hub75::start(irq_handler_t handler) { if(handler) { - dma_channel = 0; - - // Try as I might, I can't seem to coax MicroPython into leaving PIO in a known state upon soft reset - // check for claimed PIO and prepare a clean slate. - stop(handler); - if (panel_type == PANEL_FM6126A) { FM6126A_setup(); } @@ -139,7 +133,7 @@ void Hub75::start(irq_handler_t handler) { // Prevent flicker in Python caused by the smaller dataset just blasting through the PIO too quickly pio_sm_set_clkdiv(pio, sm_data, width <= 32 ? 2.0f : 1.0f); - dma_channel_claim(dma_channel); + dma_channel = dma_claim_unused_channel(true); dma_channel_config config = dma_channel_get_default_config(dma_channel); channel_config_set_transfer_data_size(&config, DMA_SIZE_32); channel_config_set_bswap(&config, false); @@ -148,15 +142,13 @@ void Hub75::start(irq_handler_t handler) { // Same handler for both DMA channels - irq_set_exclusive_handler(DMA_IRQ_0, handler); - irq_set_exclusive_handler(DMA_IRQ_1, handler); + irq_add_shared_handler(DMA_IRQ_0, handler, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY); dma_channel_set_irq0_enabled(dma_channel, true); irq_set_enabled(pio_get_dreq(pio, sm_data, true), true); irq_set_enabled(DMA_IRQ_0, true); - row = 0; bit = 0; @@ -169,10 +161,9 @@ void Hub75::start(irq_handler_t handler) { void Hub75::stop(irq_handler_t handler) { irq_set_enabled(DMA_IRQ_0, false); - irq_set_enabled(DMA_IRQ_1, false); irq_set_enabled(pio_get_dreq(pio, sm_data, true), false); - if(dma_channel_is_claimed(dma_channel)) { + if(dma_channel != -1 && dma_channel_is_claimed(dma_channel)) { dma_channel_set_irq0_enabled(dma_channel, false); irq_remove_handler(DMA_IRQ_0, handler); //dma_channel_wait_for_finish_blocking(dma_channel); @@ -184,17 +175,21 @@ void Hub75::stop(irq_handler_t handler) { if(pio_sm_is_claimed(pio, sm_data)) { pio_sm_set_enabled(pio, sm_data, false); pio_sm_drain_tx_fifo(pio, sm_data); + pio_remove_program(pio, &hub75_data_rgb888_program, data_prog_offs); pio_sm_unclaim(pio, sm_data); } if(pio_sm_is_claimed(pio, sm_row)) { pio_sm_set_enabled(pio, sm_row, false); pio_sm_drain_tx_fifo(pio, sm_row); + if (inverted_stb) { + pio_remove_program(pio, &hub75_row_inverted_program, row_prog_offs); + } else { + pio_remove_program(pio, &hub75_row_program, row_prog_offs); + } pio_sm_unclaim(pio, sm_row); } - pio_clear_instruction_memory(pio); - // Make sure the GPIO is in a known good state // since we don't know what the PIO might have done with it gpio_put_masked(0b111111 << pin_r0, 0); diff --git a/drivers/hub75/hub75.hpp b/drivers/hub75/hub75.hpp index 994740a84..cbd8fcbd6 100644 --- a/drivers/hub75/hub75.hpp +++ b/drivers/hub75/hub75.hpp @@ -73,7 +73,7 @@ class Hub75 { Pixel background = 0; // DMA & PIO - uint dma_channel = 0; + int dma_channel = -1; uint bit = 0; uint row = 0;