This is a story of doing some debugging, and how various possibilities were eliminated.
Last week an SSL certificate that is needed for access to Adafruit IO expired. The older certificate was embedded in CircuitPython and also in the NINA-FW firmware. The NINA-FW firmware runs on an ESP32, which is meant to be used as a WiFi co-processor. NINA-FW was originally written byArduino, was forked by us, and is used for Adafruit’s AirLift series of boards and breakouts.
CircuitPython 8.2.2 was released to include the new certificate. We also rebuilt the NINA-FW firmware to include this new certificate, in version v1.7.5. On boards like the PyPortal or MatrixPortal M4, NINA-FW is updated by loading a simple serial-“passthrough” program, written with Arduino, on the board’s main microcontroller. The passthrough passes bytes in both directions between the board’s USB serial port and the UART port on the ESP32.
However, the new NINA-FW would not load properly using the passthrough. We tried rebuilding the release in a couple of different ways, but the upload would always fail partway through the upload.
I was wondering what was wrong with the passthrough. It’s a very simple program, just reading bytes and writing them to the other side. I tried a number of small tweaks on the basic loop, to no avail.
Over the weekend, I attacked the problem in a divide-and-conquer way. When there are multiple possible causes, you try to eliminate a cause to narrow down what the problem could be.
First I made a testbed with a Feather M4 (SAMD51) and an ESP32 breakout board that was wired the same way the chips were connected on a MatrixPortal or PyPortal. I reproduced the upload failure. Then I made passthrough programs for other Feather boards: SAMD21 (M0), nRF52840, and RP2040. The upload failure also occurred with SAMD21, but there was no problem with the nRF52840 and RP2040 Feathers.
That told me that the problem was something with the passthrough only on SAMD boards. The next question was whether the problem was related to the UART implementation, or to the USB serial implementation for SAMD boards. I made another testbed, connecting a standard USB-serial adapter to a UART port on a SAMD Feather, and then connecting a second UART port on the SAMD to the ESP32. I modified the passthrough program to be UART-to-UART, instead of UART-to-USB-serial. That worked with SAMD boards, which told me the problem was with the USB code “stack”.
While investigating the USB code, I discovered that we had provided an Arduino compile option to use the TinyUSB stack instead of the native SAMD USB stack. I recompiled the original passthrough with TinyUSB, and it worked! I tested a little more, and then rebuilt all the passthroughs with TinyUSB. The problem was solved. What’s wrong with the USB stack is still unknown, but that is a problem for another day.
Please check to see if you have chunks of FF data in your build.
USB cannot send lots of 1’s in a row and needs to insert an extra transition in there.
This will mess up timings as it is done at a low level after a number of 1’s (6 if memory serves me well)
I had this issue once with a self made camera system which approached max USB bandwidth.
Trick I used was to let the FPGA on that board XOR the data with 0xA5 and then convert it back at the receiver end.