joan2937 / pigpio

pigpio is a C library for the Raspberry which allows control of the General Purpose Input Outputs (GPIO).
The Unlicense
1.43k stars 403 forks source link

CM4 HDMI Audio + pigpio conflict? #579

Open dave-tho opened 1 year ago

dave-tho commented 1 year ago

Heya, I seem to be getting a conflict when using pigpiod and HDMI audio on a CM4 - I've also created a topic in the pi forums to see if anyone else is seeing the same problem: https://forums.raspberrypi.com/viewtopic.php?t=353130

Reading through some of the other issues here, and based on some comments it does seem like there's potential conflicts with PWM and HDMI audio - but nothing really specific to my case.

Setup: CM4 + Official CM4 IO Board

Can you confirm if this is likely to be a problem - any potential suggestions about a workaround or a different route I should take would be appreciated.

guymcswain commented 1 year ago

Picking up from linked thread above:

Please try starting pigpiod with -d 11. A shot in the dark to avoid a possible DMA conflict.

dave-tho commented 1 year ago

Picking up from linked thread above:

Please try starting pigpiod with -d 11. A shot in the dark to avoid a possible DMA conflict.

Heya, apologies for the delayed reply - I wanted to try changing the DMA channels yesterday (as suggested in linked thread) but didn't get the time.

Short story: yes that worked! If I launch the daemon with a different DMA channel defined audio continues to play.

Long story: I've also been looking at the HDMI port and configuration - realised I was using HDMI1 rather than the default HDMI0 port. Frustratingly, changing to HDMI0 also allows me to play audio while pigpiod is running, without having to specify DMA channel 11 (try the simple things first next time!).

As originally mentioned in my other other post on the raspberry forums, I'm actually using the Pi4J library with the pigpio provider - the pigpiod example was the minimalistic version that reproduced the issue for me. Trying to run everything back up using HDMI0, I can play audio still and even drive some SPI comms - however as soon as I use PWM, I get back to the "aplay" hangs.

I think there's definitely something related to DMA channel usage at play here and I've read some posts around identify free DMA channel, so will look in to this and update.

I'd like to keep this issue open until I can report back on this issue if that's okay?

In the mean time I was wondering if there was a method for setting the DMA channel used by pigpio by default - I couldn't find anything in the Pi4J documentation, so assume it just lets pigpio default. I came across a config.txt parameter "dtoverlay=pigpio dma_channel=11" but this appeared to do nothing in my failing scenario above.

pelwell commented 1 year ago

This is what happens when code bypasses the kernel and directly accesses hardware - potential conflicts go undetected until things get messy. Some sort of pigpio DMA channel configuration parameter seems like the way to go.

I came across a config.txt parameter "dtoverlay=pigpio dma_channel=11"

A dtoverlay/pigpio crossover? What fresh hell is this? But seriously, I can't find any reference to that overlay - it's certainly not one of ours - and have no idea how it might work unless pigpio has been taught to look inside /proc/device-tree.

guymcswain commented 1 year ago

I'd like to keep this issue open until I can report back on this issue if that's okay?

Yes. There's a related issue with pigpio on pi4 at the very least. I see the latest BCM2711 specification has now documented DMA channels 12+ as "DMA4 channels" and the current source code treats these as "Lite" channels.

I was wondering if there was a method for setting the DMA channel used by pigpio by default - I couldn't find anything in the Pi4J documentation, so assume it just lets pigpio default. I came across a config.txt parameter "dtoverlay=pigpio dma_channel=11" but this appeared to do nothing in my failing scenario above.

I'm unfamiliar with how dtoverlay interacts with an executable like pigpio. If it is a mechanism that allows the environment variables to be modified, then it could be used for the purpose of changing the default dma channels. All I know is that pigpio.h defines these defaults and pigpiod can modify them via command line arguments. A quick search reveals that Pi4J is Java programming environment, so my assumption is it uses a client socket interface to interact with pigpiod. I know that you cannot change those defaults via the client. It comes down to whatever is initializing the daemon.

[EDIT] It can be done in a systemd service file that starts pigpiod as a service.

dave-tho commented 1 year ago

Pi4J does not use the pigpio daemon, it apparently uses the libraries directly via it's "pi4j-plugin-pigpio" - I'm assuming some "lovely" Java JNI pain will ensue.

I'll start by digging in to that further to understand exactly what it's using and how it's controlling pigpio to see whether it's worth continuining down that route - pi4j was chosen for simplicity due to something else I've been doing but its obviously not helping to understand the potential conflict here.

If it's going to make more sense, I might just look at controlling pigpio directly through the C interface (or even over socket to pigpiod) - I've already seen the interface is there to configure the default DMA channels used (gpioCfgDMAchannels).

Thanks again for the input to this though both, it's really appreciated!

guymcswain commented 1 year ago

Trying to run everything back up using HDMI0, I can play audio still and even drive some SPI comms - however as soon as I use PWM, I get back to the "aplay" hangs.

Presumably another DMA channel conflict with HDMI audio? PWM functions use DMA. As a quick experiment could you try sudo pigpiod -e 5

dave-tho commented 1 year ago

Presumably another DMA channel conflict with HDMI audio? PWM functions use DMA. As a quick experiment could you try sudo pigpiod -e 5

Yeah I'd assume (and hoping) so. I can't try that at the moment as my PWM driving code is tied up in this pi4j implementation. I did find out that the bcm2711 should actually be using channels 7 (primary) and 6 (secondary):

image

I also found that pi4j definitely calls the native pigpio interface - however it's using version 71 and hasn't implemented the gpioCfgDMAchannels() method.

I'm currently trying to get their native libraries to compile so initially I can just change the values in pigpio.h for the dma channels - hoping this will be the quickest way to test - watch this space :D

guymcswain commented 1 year ago

Completely orthogonal to the issue at hand - DMA conflict with HDMI audio - but may help you avoid some pain integrating the Java native stuff:

A review of the historical issues in this repo will show that Java users have fought problems with the manner in which pigpio implemented signal handling. The signal handling didn't just impact Java environments, but it appeared to be more exposed, or the users more vocal, there. For whatever reason, prioritization, Java discrimination or just ignorance, those issues weren't addressed comprehensively until the past 12-24 months and are staged in the develop branch of the repo that is still waiting for an opportunity for release. For this and a few other minor issues that were fixed, it may be worth your time to use the develop branch.

Caveat Emptor (from pigpio web page): If you intend to rely on signals sent to your application, you should turn off the internal signal handling as shown in this example:

int cfg = gpioCfgGetInternals();
cfg |= PI_CFG_NOSIGHANDLER;  // (1<<10)
gpioCfgSetInternals(cfg);
int status = gpioInitialise();
dave-tho commented 1 year ago

Apologies for the delay in updating on this - I've had very little time to continue investigating the past couple of days - but did want to provide some information about "progress" that has been made.

In parallel to the audio issues, I was also having screen rotation issues (simple lcd_rotate was not working). To try and eliminate as much as possible, I disabled the 3D graphics driver in the boot config.txt (commenting out "dtoverlay=vc4-kms-v3c") and was able to use the rotate command. I'm still investigating to understand the correct set of kernel cmdline to use instead of disabling the driver completely - but a positive side effect of disabling the driver was that audio and GPIO control now both work!

My intended solution probably doesn't require 3D graphics enabling, as I'll be displaying fairly static web pages - however, it's still important to me to understand this better and end up with a fully working environment, so I will continue and check in to these DMA conflicts further as mentioned above.

Thanks again for the advice guy, I'll take this in to account as I continue to develop this solution.