nrf-hal icon indicating copy to clipboard operation
nrf-hal copied to clipboard

Consider supporting extended DMA transfers

Open hannobraun opened this issue 5 years ago • 4 comments

This issue was first opened in the old nrf52-hal repository. Original discussion: https://github.com/jamesmunns/nrf52-hal/issues/14


The nRF52832's DMA channels are limited to buffers with a maximum length of 255 bytes. This is very limiting. For example, in the DW1000 driver, I need to support registers that are much longer than that (although there are ways to read/write subsets).

There is a way to use multiple consecutive buffers to circumvent this limitation. The product specification alludes to this (see section 10.1), but doesn't really explain how this works. I found the following discussions that provide a clearer picture:

  • https://devzone.nordicsemi.com/f/nordic-q-a/18638/easydma-array-list
  • https://devzone.nordicsemi.com/f/nordic-q-a/19891/transfer-more-than-255-bytes-with-spi-master-on-nrf52

Since this technique requires additional system resources (PPI, TIMER) and applies to all DMA channels, I think it's probably best to provide this as a separate layer that builds on top of DMA users like SPIM.

hannobraun avatar Sep 12 '18 13:09 hannobraun

Hey @hannobraun, do you think a solution like https://github.com/nrf-rs/nrf52-hal/pull/40 would work? My idea would be roughly as follows:

  • Continue offering a "blocking" implementation of each peripheral, essentially what we have now
  • Offer an "async" version of each peripheral which does the following:
    • Provides the interrupt handler, transparent to the user
    • uses a static BBQueue (one for each peripheral and each direction)
    • uses something like this demo to allow the user to enable/configure the buffer size, at least until it is possible to have the UarteAsync instance totally own the BBQueue in a way that makes sense

jamesmunns avatar Jan 03 '19 15:01 jamesmunns

@jamesmunns I left some comments in your pull request. Whether it is an alternative to the approach suggested in this issue, I don't know. My impression is that this approach would enable the blocking API to support larger buffers with little hassle (from the user's perspective). You're suggesting a non-blocking API, which seems somewhat orthogonal.

hannobraun avatar Jan 04 '19 07:01 hannobraun

I used exactly that feature of the nRF52832 in C already and it's really not that much sorcery. You need to set some triggers on the PPI bus accordingly to start the next transfer with the transfer done event. You will still require some stop condition (e.g. an ISR) that stops the chain of write/read events, such that it does not trigger the chain for all eternity (I think this is kinda sad and I would have loved a register to set a max transfers value or total buffer size).

I think this should be easily doable but would require some nicer higher level interface to the PPI bus.

Yatekii avatar Feb 06 '19 09:02 Yatekii

I think this should be easily doable but would require some nicer higher level interface to the PPI bus.

Which would be a nice thing to have in itself!

hannobraun avatar Feb 07 '19 16:02 hannobraun