Skip to content
This repository has been archived by the owner on Sep 20, 2023. It is now read-only.

bcm283x: complete DMA support #172

Closed
simokawa opened this issue Dec 9, 2017 · 9 comments
Closed

bcm283x: complete DMA support #172

simokawa opened this issue Dec 9, 2017 · 9 comments

Comments

@simokawa
Copy link
Contributor

simokawa commented Dec 9, 2017

What is the status of BCM283X DMA support?
I am interested in using DMA for

  1. Output: PWM for usual GIO pins
  2. Input: Frequent periodic GIO pin read (for quadrature encoders)

Both seem supported by Pigpio.
I found some code in bcm283x/dma.go but it does not seem to have an interface for it.

I am considering to play with DMA in the next few weeks. If there is anything I can help to implementing them in periph, please let me know.

Thanks,

@maruel
Copy link
Contributor

maruel commented Dec 9, 2017

Thanks for the inquiry! I have various local branches in various states of brokenness. :) There were challenges:

  • Figure out a way to describe a stream both as a list of events and as a bit stream, done as periph.io/x/periph/conn/gpio/gpiostream.
  • Make it work at all on one CPU. Kinda done.
  • From the various ways to drive inputs and outputs, find the one that has the best trade off latency vs memory.
    • Specifically with the bcm283x, I tried all of:
      • using one DMA channel, daisy chained one bit toggle per controlBlock, one writing to gpioMap.outputSet, one to gpioMap.outputClear.
      • using two simultaneous DMA channels one per 0 toggle and one per 1 toggle, one writing to gpioMap.outputSet, one to gpioMap.outputClear.
      • using one DMA channel, writing to gpioMap.level.
      • using the PCM engine to have a fully synchronized clock + input + output (prototyping).
    • In particular, using a dual DMA channels solution has too much jitter to be able to use it to drive NRZ LEDs. :(
  • Implement on at least two CPU classes to understand differences and similarities. Didn't need to be fully functional, but that was a useful learning experience.
  • Figure out an API that is simpler yet powerful to wrap this up.
    • In particular, I'd like to enable functionality for simultaneous I/O if possible.
    • Figure out a teardown / cleanup API that is easy and safe to use, otherwise the user is left in a state where (s)he has to hard reset the host.

I've pushed one of my "less bad" branches as https://github.com/google/periph/tree/2_bcm_dma and https://github.com/google/periph/tree/7_allwinner. Allwinner support is not needed for this feature, it's just FYI.

@simokawa
Copy link
Contributor Author

simokawa commented Dec 9, 2017

Thanks for the information! I will take a look at your branch.

@maruel
Copy link
Contributor

maruel commented Dec 9, 2017

The TL;DR; of the above is that focusing on getting the PCM driver up and running is probably a more efficient use of our time, but for simple edge streams with high tolerances like for a servo on an arbitrary pin, the dual DMA channels with one controlBlock per bit toggle is probably going to be a good route.

@maruel
Copy link
Contributor

maruel commented Dec 9, 2017

In my case, my end goal is to have tight tolerance enough to drive https://github.com/google/periph/blob/master/experimental/devices/nrzled/nrzled.go which cannot be efficiently encoded as bit toggle.

@maruel
Copy link
Contributor

maruel commented Dec 9, 2017

In practice we could totally abuse other ports like SPI and UART for similar purposes, only if the kernel drivers had proper clock calculation logic...

@simokawa
Copy link
Contributor Author

Ok, I think I mostly implemented the features.
(full version) https://github.com/simokawa/periph/tree/dmapull
(initial partial PR) #207

However, there is a big mystery why DMA pacing is working...
In other words, who is writing to PWM FIFO. Here is a context:

  • DMA write is paced by DREQ and DMA keep writing while DREQ is asserted, so DREQ must be de-asserted for pacing.
  • DREQ is de-asserted when PWM FIFO is full or above a threshold, this means someone needs to keep filling FIFO (by running DMA engine).
  • If I understand correctly, periph never starts such DMA.
  • In my RPi B+, it seems DMA 14 ch is active and writing to PWM FIFO after reboot. Who started and owns this???

Can we assume the system starts such DMA or is it specific to my system?

% uname -a
Linux raspberrypi 4.1.19+ #858 Tue Mar 15 15:52:03 GMT 2016 armv6l GNU/Linux

I guess we need to set up DMA writing FIFO by ourselves but it is also undesirable to have 2 channels writing to PWM FIFO simultaneously.

@maruel
Copy link
Contributor

maruel commented Dec 27, 2017

About the last point, it is on Raspbian Lite or with X? Because you may need to uninstall the audio subsystem (?)

@simokawa
Copy link
Contributor Author

I guess it is with X but I installed it more than a year ago and don't quite remember how I installed it. I already commented out "dtparam=audio=on" in boot/config.txt. I tried not to load snd-bcm2835 but it did not work.

Anyway, it turned out I have installed pi-blaster and the daemon starts automatically after reboot and starts DMA to write PWM FIFO.
After uninstalling pi-blaster, DMA pacing is broken as expected :-).
We have to start DMA writing FIFO by ourselves.

@maruel maruel changed the title BCM283X DMA support bcm283x: complete DMA support Nov 9, 2018
@maruel
Copy link
Contributor

maruel commented Sep 20, 2023

Ported to periph/host#44.

@maruel maruel closed this as completed Sep 20, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants