SerialPIO stuttering due to XIP cache miss? #2427
Replies: 7 comments 11 replies
-
You can see all the source for the SerialPIO and the PIO here in the repo. The core does some computation and stuffs whole bytes into the PIO FIFO. The PIO pops out a bytes at a time to a temp register and shifts it out, free running. PIO instructions live in local RAM in the PIO and aren't affected by flash operations. If power and clocks are not interrupted, the bytes will shift it as sent in. If that blink library messes with the PIO enable or PIO clocks or stuffs data into the wrong FIFO then it could mess up the send, but not otherwise. Moving things to RAM may just make it do that corruption during transmit idle time, so the glitches don't affect output. |
Beta Was this translation helpful? Give feedback.
-
@myklemykle, Where does blinkLayer.blinkOnce() come from? I can't see an include for a library, or any other sort of reference to it in your code, just the call. Unrelated to the question, but are you sending the MIDI signal to both the tip and ring of a 3.5mm connector? Was that a workaround for capacitive coupling, in which case is one of them inverted in hardware? |
Beta Was this translation helpful? Give feedback.
-
Okay, I apologize once again for thinking I had this properly characterized when I didn't. While testing over this I've often made a change in code, flashed the board, saw a change in behavior, and presumed the two are connected. But now that I'm looking closer I find that it's probably not that particular code change that's making the difference. I am just seeing some very inconsistent pass/fail behavior on the PIO ports. They sometimes start to work again after a firmware change, but then they always stop working after the next power cycle. Below is a simpler example sketch. It shows how I'm setting up the MIDI devices and SerialPIO -- maybe that's no longer the right way to do it? The first time I flash a board (Adafruit Feather RP2040 RFM) with this sketch, I see the midi clock signal on the scope, as well as the blinking LED and the messages on the USB Serial port. But then when I cycle power on the board, the MIDI clock signal goes away -- but I still see the blinking LED and get the serial port messages. If I change the code and recompile the sketch, MIDI clock sometimes reappears again, but only until the next power cycle. It's that behavior that fooled me into thinking I'd found the cause. Instead, I'm now wondering if there's something going wrong with the initialization of SerialPIO? I've confirmed this weird behavior across several different boards, so I don't think it's hardware related. And in other sketches I've confirmed that PWM and SIO through those same two pins are still working; only MIDI over SerialPIO is having trouble.
|
Beta Was this translation helpful? Give feedback.
-
Thanks for that. It looks to me, at the moment, that when I switch to Pico USB stack the problem goes away, i.e. MIDI comes back, and is always working even when I power cycle. I simplified the sketch even more (see below) and that is still the issue. Compiling with TinyUSB breaks MIDI -- except very occasionally I will flash the board and MIDI comes back, but only until I cycle power. Also, if I leave out the MIDI device and just send raw MIDI clock messages (0xf8) to the SSerialTip1 at 31250 baud, that always works, even with TinyUSB. That makes it look like some conflict between the MIDI library and TinyUSB. As I mentioned before, this combo of TinyUSB, MIDI and PIO had been working fine all year. The problem came up after a group of upgrades I recently did all at once: MacOS 12, arduino-pico 4.0.1, arduino 2.3.0, probably some library upgrades as well. I did do some testing in between those upgrades, but unfortunately I didn't test MIDI output. So it's hard to say what the change was that broke things, sorry. But the IDE tells me that I'm now building with the latest versions of all the Arduino libs.
You're right, that's not necessary in this sketch. I pruned this down from my more complex code that lets the user select between PIO, SIO and PWM on those pins. (FWIW the stuttering problem, where MIDI messages are happening but they're garbled, I am still trying to isolate that. I don't get that problem with this sketch.) |
Beta Was this translation helpful? Give feedback.
-
I'm trying to pin down what triggers this failure, where using TinyUSB kills my MIDI output. Below is another version of the example sketch. But if I uncomment the line that instantiates a MidiInterface, I am not calling any method on that MidiInterface instance but the constructor.
|
Beta Was this translation helpful? Give feedback.
-
AH OKAY, it looks like this was all due to Arduino caching some faulty object files! I finally stated deleting the entire Arduino cache manually between builds, and now this missing-MIDI-signal problem seems to have gone away. |
Beta Was this translation helpful? Give feedback.
-
I'm reluctant to even say this because I've been wrong so often, but ATM it looks like a flaky cable has been the cause of my intermittent signal loss for the last few days. Since I replaced that, the test sketch is working in all configurations. (I may or may not still have the original problem, a present-but-flaky signal in the real sketch ... returning to that problem now.) |
Beta Was this translation helpful? Give feedback.
-
Hi, I found a weird behavior today and it's got me wondering if I understand how PIO actually works on RP2040. This is probably not a fault of the pico core but I'd appreciate any thoughts on it.
Basically I have code that sends a MIDI clock message regularly through SerialPIO, and that's always worked fine. I recently added a line of code right after the midi.sendClock() call, to call a function blinkLedsOnce(), just to blink some LEDs. But adding that function call caused MIDI to glitch out in a particular way.
A MIDI clock message is a single byte over a serial line: 0b11111000; encoded on the wire it just looks like a single positive pulse held for a duration of five bits at 31250 baud. But after I added this call to blinkLedsOnce() I started seeing that positive pulse held too long, which the UART on the other end would read as 0b11111100 or 0b11111110 or 0b11111111 . It looked as if the PIO was hanging briefly in the middle of sending a byte.
I eventually found that when I wrapped the call to blinkLedsOnce() in __not_in_flash_func(), the problem went away completely.
I don't get that. I guess that blinkLedsOnce() was being fetched from Flash into the XIP cache before I pinned it to RAM. But can a cache miss actually cause a stutter in a SerialPIO transmission in the middle of a byte? I thought that PIO had its own FIFOs and were driven directly from the system clock.
Here's the relevant code, it's pretty basic I think.
Beta Was this translation helpful? Give feedback.
All reactions