Skip to content

Commit b5887f6

Browse files
committed
minor scanvideo_dpi fixes
1 parent ba94449 commit b5887f6

File tree

1 file changed

+33
-16
lines changed

1 file changed

+33
-16
lines changed

src/rp2_common/pico_scanvideo_dpi/scanvideo.c

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,28 @@ static inline void release_scanline_irqs_enabled(int buffers_to_free_count,
559559
}
560560
}
561561

562+
// Note that this is not a general purpose function. It must be called by a caller
563+
// who can guarantee that a DMA completion IRQ will not be taken during this method
564+
static inline void abort_all_dma_channels_assuming_no_irq_preemption() {
565+
// the reason the above requirements are in place is that the DMA controller may cause
566+
// a completion IRQ during (or immediately the abort). There are *slower* ways to
567+
// work around it in software, but we want to suppress the IRQ afterwards anyway, so
568+
// as long as the spurious IRQ doesn't get taken here, then the h/w issue is of no problem
569+
dma_hw->abort = PICO_SCANVIDEO_SCANLINE_DMA_CHANNELS_MASK;
570+
// note that relying on the abort bits is no longer safe, as it may get cleared before the spurious IRQ happens
571+
// // wait for abort(s) to complete
572+
// while (dma_hw->abort & PICO_SCANVIDEO_SCANLINE_DMA_CHANNELS_MASK) tight_loop_contents();
573+
while (dma_channel_is_busy(PICO_SCANVIDEO_SCANLINE_DMA_CHANNEL)) tight_loop_contents();
574+
#if PICO_SCANVIDEO_PLANE_COUNT > 1
575+
while (dma_channel_is_busy(PICO_SCANVIDEO_SCANLINE_DMA_CHANNEL2)) tight_loop_contents();
576+
#if PICO_SCANVIDEO_PLANE_COUNT > 2
577+
while (dma_channel_is_busy(PICO_SCANVIDEO_SCANLINE_DMA_CHANNEL3)) tight_loop_contents();
578+
#endif
579+
#endif
580+
// we don't want any pending completion IRQ which may have happened in the interim
581+
dma_hw->ints0 = PICO_SCANVIDEO_SCANLINE_DMA_CHANNELS_MASK;
582+
}
583+
562584
static inline bool update_dma_transfer_state_irqs_enabled(bool cancel_if_not_complete,
563585
int *scanline_buffers_to_release) {
564586
uint32_t save = spin_lock_blocking(shared_state.dma.lock);
@@ -612,13 +634,9 @@ static inline bool update_dma_transfer_state_irqs_enabled(bool cancel_if_not_com
612634
shared_state.dma.buffers_to_release = 0;
613635
DEBUG_PINS_XOR(video_in_use, 4);
614636
}
615-
dma_channel_abort(PICO_SCANVIDEO_SCANLINE_DMA_CHANNEL);
616-
#if PICO_SCANVIDEO_PLANE_COUNT > 1
617-
dma_channel_abort(PICO_SCANVIDEO_SCANLINE_DMA_CHANNEL2);
618-
#if PICO_SCANVIDEO_PLANE_COUNT > 2
619-
dma_channel_abort(PICO_SCANVIDEO_SCANLINE_DMA_CHANNEL3);
620-
#endif
621-
#endif
637+
// note that we guarantee no IRQ preemption because this method is always called within some
638+
// type of video IRQ handle, and of those the DMA IRQ is the lowest priority.
639+
abort_all_dma_channels_assuming_no_irq_preemption();
622640
#else
623641
panic("need VIDEO_RECOVERY");
624642
#endif
@@ -630,13 +648,9 @@ static inline bool update_dma_transfer_state_irqs_enabled(bool cancel_if_not_com
630648
shared_state.dma.scanline_in_progress = 0;
631649
*scanline_buffers_to_release = shared_state.dma.buffers_to_release;
632650
shared_state.dma.buffers_to_release = 0;
633-
dma_abort(PICO_SCANVIDEO_SCANLINE_DMA_CHANNEL);
634-
#if PICO_SCANVIDEO_PLANE_COUNT > 1
635-
dma_abort(PICO_SCANVIDEO_SCANLINE_DMA_CHANNEL2);
636-
#if PICO_SCANVIDEO_PLANE_COUNT > 2
637-
dma_channel_abort(PICO_SCANVIDEO_SCANLINE_DMA_CHANNEL3);
638-
#endif
639-
#endif
651+
// note that we guarantee no IRQ preemption because this method is always called within some
652+
// type of video IRQ handle, and of those the DMA IRQ is the lowest priority.
653+
abort_all_dma_channels_assuming_no_irq_preemption();
640654
}
641655
spin_unlock(shared_state.dma.lock, save);
642656
return false;
@@ -1050,7 +1064,7 @@ extern bool scanvideo_in_vblank() {
10501064
return *(volatile bool *) &shared_state.scanline.in_vblank;
10511065
}
10521066

1053-
static uint default_scanvideo_scanline_repeat_count_fn(uint32_t scanline_id) {
1067+
static uint __no_inline_not_in_flash_func(default_scanvideo_scanline_repeat_count_fn)(uint32_t scanline_id) {
10541068
return 1;
10551069
}
10561070

@@ -1097,7 +1111,10 @@ extern scanvideo_scanline_buffer_t *__video_time_critical_func(scanvideo_begin_s
10971111
DEBUG_PINS_CLR(video_link, 1);
10981112
DEBUG_PINS_CLR(video_generation, 1);
10991113
#if PICO_SCANVIDEO_LINKED_SCANLINE_BUFFERS
1100-
if (fsb) fsb->core.link_after = 0;
1114+
if (fsb) {
1115+
fsb->core.link = 0;
1116+
fsb->core.link_after = 0;
1117+
}
11011118
#endif
11021119
return (scanvideo_scanline_buffer_t *) fsb;
11031120
}

0 commit comments

Comments
 (0)