# Photon 2 SPI DMA transfer deadlock

**URL:** <https://community.particle.io/t/photon-2-spi-dma-transfer-deadlock/69023>\
**Category:** Firmware\
**Created:** [January 24, 2025, 7:38am UTC](https://community.particle.io/t/photon-2-spi-dma-transfer-deadlock/69023 "2025-01-24T07:38:12Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![michschn-oww](https://avatars.discourse-cdn.com/v4/letter/m/a587f6/32.png) [@michschn-oww](https://community.particle.io/u/michschn-oww)\
**Post date:** [January 24, 2025, 7:38am UTC](https://community.particle.io/t/photon-2-spi-dma-transfer-deadlock/69023/1 "2025-01-24T07:38:12Z")

</div>

I'm seeing stability issues driving a display via SPI. I'm using LVGL as a rendering library. For stresstesting, I'm driving a continuous animation, which eventually will come to a halt. I debugged it down to the SPI DMA transfer not completing. When not using DMA, this works.

To further debug, simplified my code by remoing all threading code (Device OS is still threaded), and stopped relying on the interrupt to be notified for completion, yet the DMA transfer method eventually will not complete ☹

I'm using DeviceOS 6.2 preview, but have not yet tested the same with an older DeviceOS.

The relevant, simplified code that block that communicates with the display is below. Note that if I transfer byte-by-byte (instead of DMA), i have not seen this hang. Am I fundamentally holding it wrong?

Thanks,  
MikeS

```auto
void Display::SendCommandDma(const uint8_t *cmd, size_t cmd_size,
                             const uint8_t *param, size_t param_size) {
  SPI1.beginTransaction(spi_settings_);
  pinResetFast(pin_chipselect);
  pinResetFast(pin_datacommand);

  for (size_t i = 0; i < cmd_size; i++) {
    SPI1.transfer(cmd[i]);
  }

  pinSetFast(pin_datacommand);
  SPI1.transfer(param, NULL, param_size, NULL);
  // Not getting here when it hangs

  pinSetFast(pin_chipselect); // CS is not pulled up anymore
  SPI1.endTransaction();
  lv_display_flush_ready(display_);
}

```

---

<div class="post-metadata">

**Author:** ![rickkas7](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/rickkas7/32/8681_2.png) [@rickkas7](https://community.particle.io/u/rickkas7)\
**Post date:** [January 24, 2025, 1:46pm UTC](https://community.particle.io/t/photon-2-spi-dma-transfer-deadlock/69023/2 "2025-01-24T13:46:53Z")

</div>

Nothing is obviously wrong with that code, however to rule out possible issues that affect DMA:

- Where is `param` stored (global variable, heap, stack, or flash)?
- How big is the data typically? In particular, more than 4095 bytes?
- Is param\_size ever 0? That might be an issue.

Can you put a short delay, like a millisecond, between the command transfer and setting the datacommand GPIO? This is just to see if it makes a difference.

---

<div class="post-metadata">

**Author:** ![michschn-oww](https://avatars.discourse-cdn.com/v4/letter/m/a587f6/32.png) [@michschn-oww](https://community.particle.io/u/michschn-oww)\
**Post date:** [January 24, 2025, 4:39pm UTC](https://community.particle.io/t/photon-2-spi-dma-transfer-deadlock/69023/3 "2025-01-24T16:39:45Z")

</div>

`param` is on the heap, allocated in setup. the data is often more than 4k, up to some ~150k if the update refreshes the whole screen. What happens at the 4k boundary? is it recommended to break the transfer into chunks?

---

<div class="post-metadata">

**Author:** ![rickkas7](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/rickkas7/32/8681_2.png) [@rickkas7](https://community.particle.io/u/rickkas7)\
**Post date:** [January 24, 2025, 4:56pm UTC](https://community.particle.io/t/photon-2-spi-dma-transfer-deadlock/69023/4 "2025-01-24T16:56:54Z")

</div>

The largest DMA transfer is 4095 bytes. The SPI.transfer with DMA call will split that up for you automatically, so you don't really need to split it, but it's worth investigating as a possible source of a bug.

The reason I mention the source is that you can't DMA from flash directly and it's copied in chunks, though that does not apply in your case, and now that I think about it, it might only apply to nRF52.

So it's not obvious why it's not working.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/particle/original/3X/3/2/3291e3c9351789fe8620ae5bcec8d3fec67ff221.png) [@system](https://community.particle.io/u/system)\
**Post date:** [July 26, 2025, 4:57am UTC](https://community.particle.io/t/photon-2-spi-dma-transfer-deadlock/69023/5 "2025-07-26T04:57:13Z")

</div>

Closed on July 26, 2025, 4:57am UTC

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.
