You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Arduino board: Circuit Playground Express, or any SAM D21 board
Arduino IDE version: 1.8.13
Summary
During a measurement, FreeTouch makes many reads to some Read-Synchronized registers in the PTC, and does so without the synchronizing read-request sequence. Because the PTC is clocked slower than the system clock, these reads cause a significant stall (~185µs each) of the Peripheral Bridge C, stalling all access to the other peripherals on the same bridge.
If DMA is trying access any of those peripherals (like the DAC or ADC) - then it will be stalled. At ~185µs stall, this is enough to lose several samples at audio rates, causing significant distortion.
Discussion
This bridge stall can be induced with any peripheral on the C bridge that has a Read Synchronized register. To induce the stall:
a) the peripheral needs to be clocked with a clock slower than GCLK0
b) make the register read without first performing the READREQ sequence
Note that if the peripheral is clocked via GLCK0 - as most are by default - then a read to a Read Synchronized register made without the READREQ sequence will still stall the bridge, but it will be for a very short time (docs. imply <8 clocks). This won't materially affect DMA audio.
However, the PTC must be clocked at 4MHz, and this is achieved by setting GCLK1 to use the 8MHz clock source and dividing down. FreeTouch sets this up. And then FreeTouch makes reads that stall the bridge.
The sketch uses DMA drive audio out to the DAC "in the background", only using CPU during DMA interrupts to compute the next buffer of samples.
In the foreground (in loop()) the sketch can call FreeTouch ever 50ms to demonstrate the issue. It can also demonstrate the issue by directly accessing the PTC, or reading TC3 configured to cause the issue. The distortion is plainly audible.
Both CONVERT and RESULT appear to be Read Synchronized registers. (Note: the sync_config call does not implement the read request sequence and does not sync reads.)
In the the Circuit Playground version, this code is:
uint16_t Adafruit_CPlay_FreeTouch::startPtcAcquire(void) {
ptcConfigIOpin();
ptcAcquire();
while (QTOUCH_PTC->CONVCONTROL.bit.CONVERT) {
yield();
}
sync_config();
uint16_t result = QTOUCH_PTC->RESULT.reg;
return result;
}
This makes the issue plainly bad: The CONVERT read is done in a spin loop... causing stalls lasting over 8ms during which only a fraction of DMA operations get in.
It is clear from the code that the READREQ register for the PTC hasn't been sleuthed out yet. There are two other SAM D21 modules with READREQ functionality (RTC & TC timers) and one imagines that PTC's is similarly constructed in layout and operation. Some more reverse engineering of the PTC is in order.
The text was updated successfully, but these errors were encountered:
thanks for the detailed writeup! more reverse engineering would be a great project for someone to undertake :) if someone is up for it, we are happy to take pull requests as we have no plans to revisit this code soon!
one could also change the structure of the code to add a longer delay/yield or add a callback. many options :)
I did a preliminary hunt for where that READREQ register might be... Alas I don't have a set up to observe QTouch's bus access patterns that might give us clue. I'll keep poking...
FreeTouch as used in libraries
Summary
During a measurement, FreeTouch makes many reads to some Read-Synchronized registers in the PTC, and does so without the synchronizing read-request sequence. Because the PTC is clocked slower than the system clock, these reads cause a significant stall (~185µs each) of the Peripheral Bridge C, stalling all access to the other peripherals on the same bridge.
If DMA is trying access any of those peripherals (like the DAC or ADC) - then it will be stalled. At ~185µs stall, this is enough to lose several samples at audio rates, causing significant distortion.
Discussion
This bridge stall can be induced with any peripheral on the C bridge that has a Read Synchronized register. To induce the stall:
a) the peripheral needs to be clocked with a clock slower than GCLK0
b) make the register read without first performing the READREQ sequence
Note that if the peripheral is clocked via GLCK0 - as most are by default - then a read to a Read Synchronized register made without the READREQ sequence will still stall the bridge, but it will be for a very short time (docs. imply <8 clocks). This won't materially affect DMA audio.
However, the PTC must be clocked at 4MHz, and this is achieved by setting GCLK1 to use the 8MHz clock source and dividing down. FreeTouch sets this up. And then FreeTouch makes reads that stall the bridge.
Demonstration
This sketch demonstrates the issue on a Circuit Playground Express: https://gist.github.com/mzero/89955e14d41d7e37a439ba806746f632
The sketch uses DMA drive audio out to the DAC "in the background", only using CPU during DMA interrupts to compute the next buffer of samples.
In the foreground (in
loop()
) the sketch can call FreeTouch ever 50ms to demonstrate the issue. It can also demonstrate the issue by directly accessing the PTC, or reading TC3 configured to cause the issue. The distortion is plainly audible.FreeTouch and PTC
The main issue is in the code:
Both
CONVERT
andRESULT
appear to be Read Synchronized registers. (Note: thesync_config
call does not implement the read request sequence and does not sync reads.)In the the Circuit Playground version, this code is:
This makes the issue plainly bad: The
CONVERT
read is done in a spin loop... causing stalls lasting over 8ms during which only a fraction of DMA operations get in.It is clear from the code that the
READREQ
register for the PTC hasn't been sleuthed out yet. There are two other SAM D21 modules withREADREQ
functionality (RTC & TC timers) and one imagines that PTC's is similarly constructed in layout and operation. Some more reverse engineering of the PTC is in order.The text was updated successfully, but these errors were encountered: