Rpi zero 2w in Prusa 3D printer; aka: data received via UART (over GPIO) disturbs the boot process

Hello.

I finally have rpi zero 2w prepared for my 3D printer.
However I figured out that it doesn’t work.

It doesn’t boot.

Extlinux created a boot menu, and during early boot, the printer sends some data over UART, which disturbs the boot process. The disturbance occurs because U-Boot is waiting for a key press (‘hit any key to…’). As a result, some garbage is shown on the screen when UART is connected to the printer and boot process is happy, because it received magical any key ;P.

I’m still playing with it (device trees and overlays, try to hack extlinux boot process…) but I’m running out of ideas.

I definitely overlooked something.

I just don’t want to get data from UART at this early boot to be processed by boot loader, then boot a system and after all that, OctoPrint can handle printer.

Any idea please?

1 Like

Okay, I figured out that I basically don’t want an interruptable U-Boot autoboot.

So, I started to experiment with:

boot.loader.timeout = 0;

And continuint with:

  nixpkgs.overlays = [
    (self: super: {
      ubootRaspberryPi3_64bit = super.ubootRaspberryPi3_64bit.override { extraConfig = ''
        CONFIG_BOOTDELAY=-2
        CONFIG_DISABLE_CONSOLE=y
        CONFIG_SILENT_CONSOLE=y
        CONFIG_SILENT_CONSOLE_UPDATE_ON_SET=y
        CONFIG_SYS_DEVICE_NULLDEV=y
      ''; };
...

Ok.
I have known issue for people who take care about robots :).

And it works…

Quicky more hacky way is below.
Basically just change activation string from any key,
to semi random string disables parsing of garbage received via UART.

  nixpkgs.overlays = [
    (self: super: {
      ubootRaspberryPi3_64bit = super.ubootRaspberryPi3_64bit.overrideAttrs (oldAttrs: {
        extraConfig = ''
          CONFIG_BOOTDELAY=-2
          CONFIG_SILENT_CONSOLE=y
          CONFIG_SYS_DEVICE_NULLDEV=y
          CONFIG_SILENT_CONSOLE_UPDATE_ON_SET=y
          CONFIG_SILENT_U_BOOT_ONLY=y
          CONFIG_AUTOBOOT_KEYED=y
          CONFIG_AUTOBOOT_PROMPT="NO UART\0"
          CONFIG_AUTOBOOT_DELAY_STR="dfg\0"
          CONFIG_AUTOBOOT_STOP_STR="1234\0"
        '';
      });
...

However, I still need to edit extlinux configuration manually and remove
MENU and TIMEOUT lines. Because I just want to go to last generation only.

TIMEOUT -10 line, which is generated by boot.loader.timeout = 0;
doesn’t seems to work and we are stuck in menu.

Maybe I need just add some hacks to:

which removes MENU and TIMEOUT from generated file.

2 Likes

So U-boot seems to be solved. Now extlinux menu hack follows.

  1. Download module generic-extlinux-compatible from NixOS.
  2. Put disabledModules = [ "${modulesPath}/system/boot/loader/generic-extlinux-compatible" ]; into my copy of default.nix from generic-extlinux-compatible module.
  3. Update extlinux-conf-builder.sh to propagate my changes (just remove part where MENU and TIMEOUT were used).
  4. Put import ./stage2/extra-modules/generic-extlinux-compatible into my flake.nix.
  5. Profit.

I’m able to boot Raspberry Pi Zero 2w inside my printer.

@marmolak hey, thanks for sharing your progress and the solution that ultimately worked for you.

I’m trying to achieve the same thing with a rpi3a+ connected via uart to a prusa mk3s. The uart “noise” is also interfering with the boot process.

I wasn’t successful in making it work with your solution though. uboot seems to build fine with the extra config, but when running it plugged into the printer it still accepts input from the printers uart and ends up stuck.

Would you mind sharing a complete snippet of how you tamed uboot? (flake, or deriv of the sd-card image build). Thanks!

P.S. I am assuming that changes to extlinux.conf are optional and not necessary for uboot to ignore input from uart, so I haven’t tried applying them.

Hello.

You really need mess with extlinux.conf, because recompiled uboot ignores input but extlinux menu not (yeah, extlinux compatibility is part of uboot). So boot is interrupted by noise later at next step.

I just messed with only two lines here.

Hope it helps.
This hack remove possibility to boot older generations but I don’t use this
feature because rpi si buried in my printer without any input device nor display connected.

PS: it’s just not tested version of private repository.

I was able to get past u-boot without needing to change extlinux.conf. Just requiring a keyed autoboot was enough to make things working for me. (I still wanted the ability to go back a generation, if I take the RPi out of the printer for debugging). Here are the config variables I used:

    (self: super: {
      ubootRaspberryPi3_64bit = super.ubootRaspberryPi3_64bit.overrideAttrs (oldAttrs: {
        extraConfig = ''
          CONFIG_AUTOBOOT=y
          CONFIG_AUTOBOOT_KEYED=y
          CONFIG_AUTOBOOT_STOP_STR="\x0b"
          CONFIG_AUTOBOOT_KEYED_CTRLC=y
          CONFIG_AUTOBOOT_PROMPT="autoboot in 1 second (hold 'CTRL^C' to abort)\n"
          CONFIG_BOOT_RETRY_TIME=15
          CONFIG_RESET_TO_RETRY=y
        '';
      });
    })

Still, I couldn’t get uart to function after loading the kernel. The device would show up, but it would neither send nor receive any data.

Interestingly, because I had hooked up a uart<->usb dongle to test things, I noticed that the input and output u-boot would send & receive would turn out to be garbled. I didn’t verify this, but I assume that data wasn’t being sent or received at the configured 115200 baud rate. I haven’t spent the effort to find out what was the actual baud rate, but I confirmed it wasn’t any other “standard” one.

I have not experienced any issues with using the official RPiOS 2022-09-22 (kernel 5.15.61).

A couple of minor notes:

  • removing enable_uart=1 in config.txt does not seem to have any effect in u-boot not using the uart interface
  • I have tried various approaches in trying to get u-boot to completely ignore the serial device. I couldn’t find success in changing the device trees, applying patches to the rpi env config, tweaking the CONFIG variables to ignore serial support (it either doesn’t work when running, or ends up with a myriad of compilation errors).
1 Like

I’m happy to discover this thread. The last system I have left not yet converted to NixOS is an rpi3, currently running a getting-a-bit-too-old ubuntu. It has a GPS hat for NTP, and the serial data from the GPS causes exactly this issue with uboot.

The solution with ubuntu was to simply not use uboot; it just uses the standard raspberry pi boot loader directly. That config didn’t boot NixOS when I tried previously, leaving me with a choice between debugging a broken boot using a standard bootloader that’s for some reason considered not supported anymore, or digging into compiling uboot without serial because it apparently has no simple options to just leave the serial alone.

1 Like

Hello.

Thank you. I tested your solution and it’s much better :).
Yeah, I was hurry to learn how modules work.

BTW: I started to have issues with wifi after specific revision on my rpi zero 2w.

I fully reflashed SD card with new image but I only encounter same issue (no wifi configured).
Maybe your solution and generations can help me with debugging this issues.

Hello.

Seems like extlinux module hack is needed.
I created some generations and after using only changes proposed into u-boot, i stuck on boot menu again :(.

Do you have similar results when another generation is created?

@marmolak

Do you have similar results when another generation is created?

I went back to using OctoPi for now, but as far as I recall I didn’t encounter that issue. I’ll post an update whenever I come back to try this again.

Just for curiosity: what does Octopi have that NixOS doesn’t have?
What are you missing on NixOS?