-
Notifications
You must be signed in to change notification settings - Fork 171
Description
Script Command
git clone https://github.com/adafruit/Raspberry-Pi-Installer-Scripts.git
cd Raspberry-Pi-Installer-Scripts
sudo /home/pi/.pyenv/shims/python adafruit-pitft.py --display=28c --rotation=90 --install-type=console --reboot noOperating System
Raspberry Pi OS Trixie Lite (64-bit)
Hardware
Raspberry Pi Zero 2 W and Adafruit PiTFT Plus (2.8" capacitive touch)
Behavior
On 50% of boot cycles, the PiTFT Plus shows the normal output from initialization and works fine. During these boot cycles, /dev/fb0 exists and /dev/fb1 does not exist.
On the other 50% of boot cycles, the PiTFT Plus is inaccessible and remains in its state at power-on (blank screen, output from previous boot cycle, etc.) During these boot cycles, /dev/fb1 exists and /dev/fb0 does not exist.
This behavior is reproducible: repeatedly booting the Raspberry Pi Zero 2 W resulted in one of these two states.
Description
Boot cycles that result in a functional PiTFT contain the following lines in journalctl and dmesg:
simple-framebuffer 1eaf0000.framebuffer: framebuffer at 0x1eaf0000, 0x10a800 bytes
simple-framebuffer 1eaf0000.framebuffer: format=a8r8g8b8, mode=656x416x32, linelength=2624
Console: switching to colour frame buffer device 82x26
simple-framebuffer 1eaf0000.framebuffer: fb0: simplefb registered!
...
[drm] Initialized ili9341 1.0.0 for spi0.0 on minor 1
Console: switching to colour frame buffer device 40x30
ili9341 spi0.0: [drm] fb0: ili9341drmfb frame buffer device
Boot cycles that result in a non-functional PiTFT contain the following lines in journalctl and dmesg:
simple-framebuffer 1eaf0000.framebuffer: framebuffer at 0x1eaf0000, 0x10a800 bytes
simple-framebuffer 1eaf0000.framebuffer: format=a8r8g8b8, mode=656x416x32, linelength=2624
Console: switching to colour frame buffer device 82x26
simple-framebuffer 1eaf0000.framebuffer: fb0: simplefb registered!
...
[drm] Initialized ili9341 1.0.0 for spi0.0 on minor 0
ili9341 spi0.0: [drm] fb1: ili9341drmfb frame buffer device
Attached are the journalctl and dmesg dumps for example nonworking and working boot cycles.
Additional information
Upon further investigation, I traced the output in the latter chunk of journalctl/dmesg output above to /usr/local/bin/con2fbmap-helper.sh, which contains this:
# Wait up to 30 seconds for /dev/fb0 or /dev/fb1 to appear
for i in {1..300}; do
for fbdev in 0 1; do
if [ -e /dev/fb$fbdev ]; then
echo "Found /dev/fb$fbdev, checking if it's ili9341..."
# Check if it's actually the ili9341 device
if dmesg | grep -q "ili9341.*fb$fbdev"; then
echo "ili9341 framebuffer ready, mapping console..."
con2fbmap 1 $fbdev
echo "Console mapped to framebuffer $fbdev"
exit 0
fi
fi
done
sleep 0.1
done
The problem looks clear to me: in both cases, initialization begins with a mapping to fb0, but then con2fbmap-helper.sh waits for the display device (ili9341) to appear as either fb0 or fb1. If it happens to appear as fb0, then configuration proceeds normally and the display works. But if it happens to appear as fb1, then the kernel attempts to configure the display on fb1, which does not match up with the earlier device reservations at fb0.
(edit) Looking at the journalctl/dmesg output again, I found this additional difference:
Working:
kernel: rc rc0: vc4-hdmi as /devices/platform/soc/3f902000.hdmi/rc/rc0
kernel: input: vc4-hdmi as /devices/platform/soc/3f902000.hdmi/rc/rc0/input0
kernel: input: vc4-hdmi HDMI Jack as /devices/platform/soc/3f902000.hdmi/sound/card0/input1
kernel: [drm] Initialized vc4 0.0.0 for soc:gpu on minor 0
Nonworking:
kernel: rc rc0: vc4-hdmi as /devices/platform/soc/3f902000.hdmi/rc/rc0
kernel: input: vc4-hdmi as /devices/platform/soc/3f902000.hdmi/rc/rc0/input1
kernel: input: vc4-hdmi HDMI Jack as /devices/platform/soc/3f902000.hdmi/sound/card0/input2
kernel: [drm] Initialized vc4 0.0.0 for soc:gpu on minor 1
Notably, in the working configuration, the "Initialized vc4 0.0.0 for soc:gpu" line occurs before the "Initialized ili9341" line (i.e., HDMI is initialized first and is initialized as "minor 0" on /dev/fb1 which forces the PiTFT to be initialized as "minor 1" on /dev/fb0). In the nonworking configuration, it's the opposite.
Bottom line: There is apparently a race condition occurring during the boot cycle between vc4-hdmi and ili9341.
As a workaround - editing /boot/firmware/config.txt to delete or comment out the line dtoverlay=vc4-kms-v3d results in a consistently working PiTFT Plus for six consecutive boot cycles. Re-adding that line caused the race condition and the inconsistent behavior to recur.