-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Improvements to Audio DMA management #2043
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
As identified in adafruit#1908, when both AudioOut and PDMIn are used, hard locks can occur. Because audio_dma_stop didn't clear audio_dma_state[], a future call to audio_dma_load_next_block could occur using a DMA object which belongs to PDMIn. I believe that this Closes: adafruit#1908 though perhaps it is still not the full story. Testing performed: Loaded a sketch similar to the one on adafruit#1908 that tends to reproduce the bug within ~30s. Ran for >300s without hard lock. HOWEVER, while my cpx is no longer hard locking, it occasionally (<1 / 200s) announces Code done running. Waiting for reload. (and does so), even though my main loop is surrounded by a 'while True:' condition, so there are still gremlins nearby.
It turns out the "disable" error will fire in practice, we'll fix that next.
audio_dma_stop can be reached twice in normal usage of AudioOut. This may bear further investigation, but stop it here, by making the function check for a previously freed channel number. This also prevents the event channel from being disabled twice. The first stop location is from audio_dma_get_playing, when the buffers are exhausted; the second is from common_hal_audioio_audioout_stop when checking the 'playing' flag.
@tannewt while I based this off master, I would be happy to roll a new request that would go against 4.x.x. Let me know. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for poking at this problem! Looks like the non-AudioIO builds are unhappy. Likely you'll need to add an #if check somewhere.
These were most useful debugging, but because this code can be reached "outside of the VM", it's not actually permitted to throw exceptions here.
Some ports which actually don't have audioio or audiobusio were still calling into audio_dma_background(). This wasn't an error until the assignment to audio_dma_state in audio_dma_stop was added, though it's not clear why.
The linker error that travis found is a little weird, because it concerns an undefined symbol that I didn't undefine or add references to, inside a function that I didn't modify. That said, the fix I found and which is now reflected in this PR is to change one |
@tannewt looks like travis is OK with the latest changes, so I'm ready for your review again. TIA! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great! Thank you for the improvements.
This includes a fix which directly addresses the original problem, as well as some further fixes for other weirdness I noticed along the way. In particular, while I saw some spurious soft-resets with only the first fix, I believe the change to
audio_dma_stop
somehow has the side effect of fixing some spurious soft resets I was seeing during testing. Or, at least, they changed from 1 per ~300s to <1 per 30,000s while running the #1908 reproducer.Testing performed: Ran the reproducer script overnight on a CPX, no hard lockup.
@c-k-dillard said the first commit in this PR fixed things for them too.