# Zynq UltraScale+ FreeRTOS: XDpPsu interrupts work, but XDpDma interrupts never reach the driver handler

**URL:** <https://forums.freertos.org/t/zynq-ultrascale-freertos-xdppsu-interrupts-work-but-xdpdma-interrupts-never-reach-the-driver-handler/25136>\
**Category:** Xilinx\
**Tags:** debug, tutorial\
**Created:** [August 25, 2026, 1:22pm UTC](https://forums.freertos.org/t/zynq-ultrascale-freertos-xdppsu-interrupts-work-but-xdpdma-interrupts-never-reach-the-driver-handler/25136 "2026-08-25T13:22:30Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![SaraCliff](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/saracliff/32/6414_2.png) [@SaraCliff](https://forums.freertos.org/u/SaraCliff)\
**Post date:** [August 25, 2026, 1:22pm UTC](https://forums.freertos.org/t/zynq-ultrascale-freertos-xdppsu-interrupts-work-but-xdpdma-interrupts-never-reach-the-driver-handler/25136/1 "2026-08-25T13:22:30Z")

</div>

Hi everyone,

I am having an issue running the AMD/Xilinx `xdpdma_video_example.c` with FreeRTOS on a Zynq UltraScale+ MPSoC.

**Setup:**

- AUP-ZU3 / XCZU3EG
- Vitis Unified 2025.2
- FreeRTOS
- PS DisplayPort + DPDMA
- SDT flow

The original example works correctly in bare-metal: DisplayPort link training succeeds and the video is displayed.

With FreeRTOS, however, the DisplayPort initialization and link training also succeed, but nothing is displayed.

The important point is that **the `XDpPsu` interrupts work correctly** , including the HPD-related interrupts. The application enters the `XDpPsu` interrupt handler and the DisplayPort link is trained successfully.

However, **the DPDMA interrupt never reaches** :

```auto
XDpDma_InterruptHandler()

```

The DPDMA interrupt setup functions return `XST_SUCCESS`, but after enabling the interrupt I read:

```auto
DPDMA IEN = 0x00000000
ISR = 0x00000000
IEN = 0x00000000
IMR = 0x07FFFFFF

```

So it seems that the DPDMA interrupt is either not being enabled at the peripheral level or is not reaching the GIC/ISR.

Since the `XDpPsu` interrupts work under the same FreeRTOS application, I suspect there may be something related to the FreeRTOS interrupt configuration or Cortex-A53 GIC integration.

Has anyone successfully used `XDpDma_InterruptHandler()` with FreeRTOS on Zynq UltraScale+?

Could FreeRTOS interrupt priorities, the IRQ/vector handling, or the way the Xilinx `XScuGic` interrupts are registered cause this behaviour?

Thanks!

---

<div class="post-metadata">

**Author:** ![richard-damon](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/richard-damon/32/38_2.png) [@richard-damon](https://forums.freertos.org/u/richard-damon)\
**Post date:** [August 25, 2026, 1:36pm UTC](https://forums.freertos.org/t/zynq-ultrascale-freertos-xdppsu-interrupts-work-but-xdpdma-interrupts-never-reach-the-driver-handler/25136/2 "2026-08-25T13:36:27Z")

</div>

I don’t know if it has been fixed, as I haven’t used the Zynq port for a while, but it used to be that the Zynq port re-initialized the GIC at scheduler start, so any interrupts that were enable before that got disabled.

---

<div class="post-metadata">

**Author:** ![SaraCliff](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/saracliff/32/6414_2.png) [@SaraCliff](https://forums.freertos.org/u/SaraCliff)\
**Post date:** [August 26, 2026, 4:54am UTC](https://forums.freertos.org/t/zynq-ultrascale-freertos-xdppsu-interrupts-work-but-xdpdma-interrupts-never-reach-the-driver-handler/25136/3 "2026-08-26T04:54:12Z")

</div>

Thanks, that is a useful suggestion. I checked my code, and I am using the **SDT flow**.

The interrupts are configured **after the FreeRTOS scheduler has already started** :

```auto
xTaskCreate(...);
vTaskStartScheduler();

/* Inside the task */
SetupInterrupts();

```

With SDT, I use `XSetupInterruptSystem()` for both `XDpPsu` and `XDpDma`.

The `XDpPsu` interrupt works correctly: HPD is detected and link training succeeds. However, `XDpDma_InterruptHandler()` is never called.

Also, after:

```auto
XDpDma_InterruptEnable(DpDmaPtr, XDPDMA_IEN_VSYNC_INT_MASK);

```

the DPDMA `IEN` register still reads `0x00000000`.

So I don’t think the GIC is being reset after the interrupt configuration. I suspect there may be something specific to the DPDMA interrupt configuration or the SDT/FreeRTOS integration.

Thanks!

---

<div class="post-metadata">

**Author:** ![aggarg](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/aggarg/32/4245_2.png) [@aggarg](https://forums.freertos.org/u/aggarg)\
**Post date:** [August 26, 2026, 5:09am UTC](https://forums.freertos.org/t/zynq-ultrascale-freertos-xdppsu-interrupts-work-but-xdpdma-interrupts-never-reach-the-driver-handler/25136/4 "2026-08-26T05:09:46Z")

</div>

> [@SaraCliff](#):
>
> Also, after:
> 
> ```auto
> XDpDma_InterruptEnable(DpDmaPtr, XDPDMA_IEN_VSYNC_INT_MASK);
> 
> ```
> 
> the DPDMA `IEN` register still reads `0x00000000`.

Is it possible to step through and see why the register write is not working?

---

<div class="post-metadata">

**Author:** ![SaraCliff](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/saracliff/32/6414_2.png) [@SaraCliff](https://forums.freertos.org/u/SaraCliff)\
**Post date:** [August 28, 2026, 6:13pm UTC](https://forums.freertos.org/t/zynq-ultrascale-freertos-xdppsu-interrupts-work-but-xdpdma-interrupts-never-reach-the-driver-handler/25136/5 "2026-08-28T18:13:14Z")

</div>

Thanks for the suggestion.

We actually investigated this further. The `IEN` register reading back as `0x00000000` turned out not to indicate that the write failed.

AMD pointed out that `DPDMA_IEN` at `0xFD4C000C` is a **write-only (`wo`) register**, so reading it back always returns `0x00000000`, regardless of whether the write succeeded.

Instead, we checked the `DPDMA_IMR` register at `0xFD4C0008`, which is the register that shows the interrupt mask state.

After:

```auto
XDpDma_InterruptEnable(
    DpDmaPtr,
    XDPDMA_IEN_VSYNC_INT_MASK);

```

we read:

```auto
DPDMA IMR = 0x07FFFFFF

```

The VSYNC bit is bit 27, and according to the DPDMA register definition, a cleared bit in `IMR` means that the interrupt is unmasked. Therefore, the VSYNC interrupt is actually enabled at the DPDMA.

We also performed an additional test by reading `DPDMA_ISR` (`0xFD4C0004`) repeatedly without clearing it. We get:

```auto
[00] DPDMA_ISR = 0x00000000
[01] DPDMA_ISR = 0x08000000
[02] DPDMA_ISR = 0x08000000
[03] DPDMA_ISR = 0x08000000
...
[19] DPDMA_ISR = 0x08000000

```

`0x08000000` is the VSYNC interrupt bit, so this confirms that the DPDMA is actually generating/latching the VSYNC event.

Finally, we registered a simple custom ISR using the same `XSetupInterruptSystem()` mechanism:

```auto
XSetupInterruptSystem(
    DpDmaPtr,
    MyDpdmaIsr,
    DpDmaPtr->Config.IntrId,
    DpDmaPtr->Config.IntrParent,
    XINTERRUPT_DEFAULT_PRIORITY);

```

and this ISR is successfully triggered:

```auto
>>> DPDMA CPU IRQ! ISR=0x08000000 COUNT=1
>>> DPDMA CPU IRQ! ISR=0x08000000 COUNT=2
>>> DPDMA CPU IRQ! ISR=0x08000000 COUNT=3
...

```

So at this point, I don’t think stepping through `XDpDma_InterruptEnable()` is necessary. The write is reaching the hardware, as demonstrated by `IMR`, and the DPDMA interrupt is reaching the CPU.

The remaining issue seems to be specifically that the original `XDpDma_InterruptHandler()` from `xdpdma_intr.c` is not being called, while our custom ISR using the same interrupt ID (`16506`) is called correctly.

So the current question is why `XDpDma_InterruptHandler()` is not being dispatched under FreeRTOS/SDT even though the DPDMA interrupt itself is working.

---

<div class="post-metadata">

**Author:** ![aggarg](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/aggarg/32/4245_2.png) [@aggarg](https://forums.freertos.org/u/aggarg)\
**Post date:** [August 31, 2026, 7:00am UTC](https://forums.freertos.org/t/zynq-ultrascale-freertos-xdppsu-interrupts-work-but-xdpdma-interrupts-never-reach-the-driver-handler/25136/6 "2026-08-31T07:00:23Z")

</div>

> [@SaraCliff](#):
>
> Finally, we registered a simple custom ISR using the same `XSetupInterruptSystem()` mechanism:

So you are saying that when you call XSetupInterruptSystem explicitly, it works and when you call SetupInterrupts (which internally calls XSetupInterruptSystem), it does not? If so, can you check if there is any difference to the parameters passed to XSetupInterruptSystem in both the cases?
