This article documents the complete investigation process, from discovering abnormal Betaflight Blackbox logs to finally identifying the UART throughput bottleneck.
I connected TFC1’s PIOUART0 to the Pi Zero W2 UART0 (GPIO14, GPIO15), and enabled Blackbox Serial logging in Betaflight:
Serial1/4 (2kHz)PIDLOOP
Then, on the Pi Zero W2, I used blackbox-logger to capture the Blackbox data:
$ node index.js -s /dev/ttyAMA0 -d /tmp --betaflight -c 2048 --cache-expire 10
Although Betaflight Blackbox Explorer (https://blackbox.betaflight.com/) could open the file successfully, the recording length was only about one second, and the number of data points was extremely small — far too little for flight analysis.
Further analysis using Blackbox tools (https://github.com/betaflight/blackbox-tools/) revealed that the file contained only a single I frame and no P frames at all, indicating that the Blackbox data stream was clearly corrupted.
$ ./obj/blackbox_decode --debug ~/Downloads/log_2026-05-15T10-08-10-240Z.bbl
Decoding log '/Users/yagamy/Downloads/log_2026-05-15T10-08-10-240Z.bbl' to '/Users/yagamy/Downloads/log_2026-05-15T10-08-10-240Z.01.csv'...
Data file contained no events
Log 1 of 1Statistics
I frames 1 61.0 bytes avg 61 bytes total
G frames 1 0.0 bytes avg 0 bytes total
S frames 1 4.0 bytes avg 4 bytes total
Frames 1 61.0 bytes avg 61 bytes total
Data rate: Unknown, no timing information available.
At the same time, I tested another flight controller board — a SpeedyBee F405 development board — using the exact same Blackbox settings (except using UART1 instead of PIOUART0). That setup worked perfectly and produced hundreds of thousands of valid data points.
$ ./obj/blackbox_decode --debug ~/Downloads/btfl_002.bbl
Decoding log '/Users/yagamy/Downloads/btfl_002.bbl' to '/Users/yagamy/Downloads/btfl_002.01.csv'...
Data file contained no events
Log 1 of 1, start 00:01.379, end 02:51.018, duration 02:49.638
Statistics
Looptime 1023 avg 1406.8 std dev (137.4%)
I frames 5015 47.7 bytes avg 239177 bytes total
P frames 155459 27.2 bytes avg 4221344 bytes total
S frames 20 3.0 bytes avg 60 bytes total
Frames 160474 27.8 bytes avg 4460521 bytes total
Data rate 945Hz 27272 bytes/s 272800 baud
481344 iterations are missing in total (127223ms, 75.00%)
I then analyzed the raw Blackbox file (log_2026-05-15T09-13-10-319Z.bbl) while referencing the Betaflight documentation:
https://betaflight.com/docs/development/Blackbox-Internals
Betaflight reduces Blackbox bandwidth by describing predictors and expected ranges in the BBL header, allowing P frames to be compressed significantly.
Key observations:
At this point, it became necessary to investigate the Betaflight firmware itself to determine why the Blackbox output was failing.
The first step was verifying whether Blackbox field definitions were being generated correctly.
After adding debug prints into the source code, the following output appeared:
blackbox.c:1465 sendFieldDefinition: headerIndex=0 fieldIndex=1 name=time
blackbox.c:1462 sendFieldDefinition: headerIndex=0 fieldIndex=2 name=axisP[0]
blackbox.c:1462 sendFieldDefinition: headerIndex=0 fieldIndex=3 name=axisP[1]
...
This confirmed that the Blackbox header fields themselves were correct.
Next, I instrumented the firmware to count how many fields were actually written into each P frame.
if (testBlackboxCondition(CONDITION(PID))) { strcat(m_tempString + strlen(m_tempString), "PID,"); m_tmpCounter++; }
if (testBlackboxCondition(CONDITION(RC_COMMANDS))) { strcat(m_tempString + strlen(m_tempString), "RC_COMMANDS,"); m_tmpCounter++; }
...
DBG("Interframe conditions: %d", m_tmpCounter);
Unexpectedly, after adding these debug statements, Blackbox Explorer suddenly started decoding the logs correctly, and the P frame field counts also became normal.
(The test consisted of a roughly three-minute recording using a bare TFC1 board, while manually shaking the board at around the one-minute and two-minute marks.)
Further investigation eventually pointed to the TX flow control logic in the PIO-UART implementation:
On the RP2350 platform, serialTxBytesFree() frequently returned zero available bytes, causing portions of Blackbox frames to be dropped.
Statistics showed that each P frame was losing roughly 23–28 bytes:
blackbox.c:1010 Dropped 28 bytes when outputing P frame
blackbox.c:1010 Dropped 23 bytes when outputing P frame
blackbox.c:1010 Dropped 26 bytes when outputing P frame
...
Each P frame originally contained around 30–40 bytes, meaning nearly two-thirds of each frame was being discarded before transmission.
That explained why the decoded CSV files contained almost no usable fields.
From a bandwidth perspective:
In theory, 115200 bps should have been sufficient. Therefore, the initial suspicion was that the RP2350 PIO-UART TX implementation — particularly IRQ handling — was malfunctioning.
Searching through the Betaflight community revealed a recent pull request related to UART TX handling:
That PR even modified the PIO assembly code to improve TX behavior inside the IRQ handler.
The next step was therefore to merge that fix into the current Betaflight branch and retest the Blackbox output.
After observing that most P frames were incomplete, I added additional instrumentation to count how many frames were fully transmitted.
Modified source code:
Using the following CLI configuration:
# serial
serial PIOUART0 128 115200 57600 0 115200
# master
set blackbox_sample_rate = 1/16
set blackbox_device = SERIAL
set blackbox_mode = ALWAYS
set debug_mode = ACCELEROMETER
The results were shocking:
However:
Meanwhile:
The dropped data throughput was:
60721 bytes / 7.68 sec = 7910 bytes/sec
Equivalent to:
7910 * 8 = 63280 bps
Therefore, the actual required throughput was:
92152 + 63280 = 155432 bps
This immediately explained the problem:
115200 bps simply could not handle the total Blackbox bandwidth.
I then increased the PIO-UART baudrate to 921600 bps.
(Betaflight Configurator cannot configure 921600 directly, so CLI configuration was required. I also tried 230400 bps, but PIO-UART initialization failed. That issue was postponed for later investigation.)
# serial
serial PIOUART0 128 115200 57600 0 921600
# master
set blackbox_sample_rate = 1/16
set blackbox_device = SERIAL
set blackbox_mode = ALWAYS
set debug_mode = ACCELEROMETER
The results:
At this point it became clear that the issue was not a broken PIO-UART implementation, but simply insufficient UART throughput.
The following table summarizes all firmware and UART combinations tested:
| Firmware | UART Port | Baudrate | P frame count | Complete P frame count | Loss rate | Host data rate (bytes/sec) |
|---|---|---|---|---|---|---|
| OLD-FW | PIO-UART0 | 115200 | 3840 | 5 | 99.87% | 11519 |
| OLD-FW | PIO-UART0 | 921600 | 3840 | 3840 | 0% | 20538 |
| OLD-FW | UART0 | 115200 | FAILED | - | - | - |
| OLD-FW | UART0 | 921600 | FAILED | - | - | - |
| NEW-FW | PIO-UART0 | 115200 | 3840 | 5 | 99.87% | 11520 |
| NEW-FW | PIO-UART0 | 921600 | 3840 | 3840 | 0% | 20538 |
| NEW-FW | UART0 | 115200 | 3840 | 5 | 99.87% | 11520 |
| NEW-FW | UART0 | 921600 | 3840 | 3840 | 0% | 20524 |
Conclusions:
Additionally, if using RP2350 Hardware UART (UART0) for Blackbox output, firmware newer than 2026-05-19 is required to include the SERIAL_CHECK_TX fix from PR #15117.
Using the same CLI configuration but varying the Blackbox sample rate:
| Firmware | UART Port | Baudrate | Blackbox Sample Rate | Drop Rate | Host data rate (bytes/sec) |
|---|---|---|---|---|---|
| NEW-FW | PIO-UART0 | 921600 | 1/16 (500Hz) | 0% | 20538 |
| NEW-FW | PIO-UART0 | 921600 | 1/8 (1KHz) | 0% | 39506 |
| NEW-FW | PIO-UART0 | 921600 | 1/4 (2KHz) | 0% | 75951 |
| NEW-FW | PIO-UART0 | 921600 | 1/2 (4KHz) | 99.8% | 92162 |
This shows:
The SpeedyBee F405 worked correctly at 115200 bps likely because:
v4.4.2)Therefore, total throughput stayed below the UART bandwidth limit.
However, if newer firmware generated 55-field P frames on F405, it would likely encounter similar problems.
F405 version information:
2026-05-21 @09:14:49 -- Flight controller info, identifier: BTFL, version: 4.4.2
2026-05-21 @09:14:49 -- Board: SPBE/SPEEDYBEEF405MINI(STM32F405), version: 0
TFC1 (RP2350) version:
2026-05-23 @00:21:32 -- Flight controller info, identifier: BTFL, version: 2026.6.0-alpha
2026-05-23 @00:21:32 -- Board: TTIO/TFC1_RP2354B(RP2350B), version: 0
After confirming that TFC1’s PIO-UART0 could reliably output Blackbox data, the next step was integrating a Pi Zero W2.
System architecture:
This setup allowed stable reception of complete Blackbox logs.
/boot/firmware/config.txt
enable_uart=1
dtoverlay=disable-bt
/boot/firmware/cmdline.txt
(Remove console=ttyAMA0 and console=ttyS0 to prevent Linux from occupying UART0.)
console=tty1 root=PARTUUID=123afc93-02 rootfstype=ext4 fsck.repair=yes rootwait cfg80211.ieee80211_regdom=TW
$ cd ~
$ mkdir projects
$ cd projects
$ git clone https://gitea.t2t.io/drone/blackbox-logger.git
$ cd blackbox-logger
$ npm install
$ pm2 start $(pwd)/index.js --name blackbox-logger -- -s '/dev/ttyAMA0?baudrate=921600' -d /home/pi/projects/blackbox-logger/data --betaflight -c 2048 --cache-expire 10
$ pm2 save
# serial
serial UART0 64 115200 57600 0 115200
serial PIOUART0 128 115200 57600 0 921600
# master
set blackbox_sample_rate = 1/16
set blackbox_device = SERIAL
set debug_mode = ACCELEROMETER
Test video:
During the Pi Zero W2 integration process, several interesting issues appeared.
Sometimes the Pi Zero W2 could not reconnect to an Apple AirPort Express access point, even after multiple reboots.
Current “magic workaround”:
After that, WiFi works again.
The root cause is still unknown.
Pi Zero W2 can run websocketify successfully, allowing Betaflight Configurator to connect via:
ws://127.0.0.1:6761
However, connecting via:
ws://10.42.0.206:6761
produces:
Mixed Content: The page was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint
This happens because Betaflight Configurator is an Electron app, and HTTPS pages are blocked from connecting to insecure WebSocket (ws://) endpoints.
No ideal solution has been found yet.
blackbox_mode = NORMAL ProblemWhen blackbox_mode = NORMAL:
Currently, using:
set blackbox_mode = ALWAYS
works reliably.
This likely requires additional investigation into NORMAL mode state handling.
At first glance, this issue looked like a PIO-UART TX implementation bug.
However, deeper investigation revealed that the true root cause was much simpler:
The RP2350 platform exposed this problem more clearly because newer Betaflight versions output significantly more Blackbox fields, dramatically increasing throughput requirements.
Once the UART baudrate was increased to 921600 bps, the issue disappeared entirely, confirming that UART throughput — not PIO-UART correctness — was the actual bottleneck.
Are you looking for
Consulting Services,
Support Plans or
Training & Workshops?