Skip to content

Add native Linux/Ardulinux repeater target#2025

Open
l5yth wants to merge 6 commits into
meshcore-dev:devfrom
l5yth:linux
Open

Add native Linux/Ardulinux repeater target#2025
l5yth wants to merge 6 commits into
meshcore-dev:devfrom
l5yth:linux

Conversation

@l5yth
Copy link
Copy Markdown

@l5yth l5yth commented Mar 14, 2026

This is a continuation of #1137 (and #395) to fix #619. The goal is to keep this diff clean and rebased on upstream so it can eventually be merged into the MeshCore firmware, but I'm also happy to maintain the fork until then.

It adds a linux_repeater PlatformIO environment that compiles the simple repeater firmware for Linux SBCs (Raspberry Pi Zero, 3, 4, 5) using the ArduLinux Arduino-compatibility layer. Compared to #1137, it no longer depends on Meshtastic's Portduino framework, and repeater name/password/etc. no longer need compile-time constants, they're parsed from an INI file on first run and changed thereafter via CLI or remote config.

New files

  • variants/linux/, LinuxBoard (SPI + libgpiod GPIO init), LinuxSX1262/LinuxSX1262Wrapper (RadioLib SX1262 driver), target.cpp/h, PlatformIO config, INI templates, systemd unit, and udev rules
  • boards/linux.json, board descriptor

Shared-helper changes (guarded by ARDULINUX_PLATFORM)

  • IdentityStore, ClientACL, CommonCLI, RegionMap: use the 2-arg fs::open(path, mode) (string-mode, as on RP2040) since the ArduLinux FS has no 3-arg overload
  • TxtDataHelpers: use sprintf/PRId32 instead of ltoa (not available)
  • MyMesh: filesystem init, formatFileSystem() stub, and saveIdentity() path for Linux; apply INI config as first-run defaults before loadPrefs()

Real hardware GPIO/I2C in LinuxBoard is compiled in automatically (guarded by ARDULINUX_HARDWARE, which ArduLinux defines when libgpiod is detected via pkg-config); without it the build falls back to ArduLinux's simulated devices.

The following repeater is live and in service using this linux branch on a Raspberry Pi 4B with a LoRa hat: MeshCoreD LinuxRepeater (63, region BER)

I'll attach screenshots from remote management as manual testing did not reveal any issues.

Screenshot_20260314-191150 Screenshot_20260314-191141

/cc @ggodlewski

@l5yth
Copy link
Copy Markdown
Author

l5yth commented Mar 15, 2026

The benefit of Portduino is it "just works" (tm) with very little overhead on our end.

If we prefer to not use an external framework, we can also implement a minimal Arduino abstraction layer ourselves. I gave it a go (unreviewed yet) and it only adds ~600-800 lines of code to the Linux variant.

l5yth#3

Please let me know if you prefer it this way over the rather minimalist Portduino variant.

@ggodlewski
Copy link
Copy Markdown

The benefit of Portduino is it "just works" (tm) with very little overhead on our end.

If we prefer to not use an external framework, we can also implement a minimal Arduino abstraction layer ourselves. I gave it a go (unreviewed yet) and it only adds ~600-800 lines of code to the Linux variant.

l5yth#3

Please let me know if you prefer it this way over the rather minimalist Portduino variant.

I like it more. Portduino did not allow me to run 2 concurrent meshcore services at once (with separate config and workdir).

@liamcottle
Copy link
Copy Markdown
Member

liamcottle commented Mar 15, 2026

I haven't read through all the comments and discussions on this, but my personal preference would be to avoid depending on a Meshtastic owned project.

Portduino does look like a neat project, but I tend to avoid GPL licensed code, and we've had issues with using some of their GPL licensed code in MIT related projects in the past.

Plus, it would be good to not have to rely on an external project getting updated if we can do it in house with a small wrapper/helper class to shim out the Arduino methods as you suggested.

@l5yth
Copy link
Copy Markdown
Author

l5yth commented Mar 16, 2026

Thanks, I appreciate the early feedback.

@ggodlewski are you still using your Pi Zero 2W? Mind giving this a test? It is upgraded to 1.14.0 now and I added your config to a ini file named .pow-sx1262 - it does read the ini on first run, so you don't need to set advert name and admin password as build flag anymore. It might need to recreate the com_prefs in the working dir.

@liamcottle Thanks for the comment. I spent some more time replacing the Portduino framework but it turns out it's not as straight-forward as I hoped it would be. As a middle ground, what do you think about hosting our own minimalist 'portduino' framework in the meshcore-dev organization (meshduino?)? Would give us a bit more control and we can iterate faster without needing to add too much code to the firmware itself.

Comment thread variants/linux/LinuxBoard.cpp Outdated
else if (strcmp(key, "lora_tx_power") == 0) lora_tx_power = atoi(value);
else if (strcmp(key, "current_limit") == 0) current_limit = atof(value);
else if (strcmp(key, "dio2_as_rf_switch") == 0) dio2_as_rf_switch = value != 0;
else if (strcmp(key, "rx_boosted_gain") == 0) rx_boosted_gain = value != 0;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value != 0 means "the pointer is not null". should this check whether the string pointer exists, not whether the config value is truthy

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are correct. This always returns true, apparently. Fixed l5yth#6

ggodlewski and others added 4 commits May 31, 2026 19:07
* variants: add scaffolding for linux native

* address review comments

* address review comments
* variants: allow linux repeater to be configured at runtime

* address review comments

* address review comments

* address review comments
* replace portduino with ardulinux

* replace portduino with ardulinux

* replace portduino with ardulinux

* Remove flags now owned by the ardulinux platform framework

ARDULINUX_LINUX_HARDWARE, -lgpiod, and -li2c are detected and injected
by builder/frameworks/arduino.py via pkg-config. Hardcoding them here
caused linker failures on machines without libgpiod even though the
framework would have gracefully omitted them.

Also switch variants/ardulinux to the git+ platform URL (dropping the
platform-native + platform_packages indirection), update the linux
variant board name, and add arduino to the frameworks list in linux.json.

* address review comments

* Remove stale portduino branding note

The startup string was already fixed in l5yth/ardulinux — main.cpp
says "An application written with ardulinux". Remove the pending-fix
note and update the description to match the current behaviour.

* replace portduino with ardulinux

* Wire up ardulinux platform and fix SPI/VFS/printf for Linux target

variants/ardulinux/platformio.ini: revert local symlink:// back to
git+ URL — the symlink only works in a co-located checkout and would
break CI.

variants/linux/LinuxBoard.cpp:
- Add empty ardulinuxSetup() to satisfy the weak symbol; without it the
  default prints a noisy "No ardulinuxSetup() found" message on startup.
- Replace Serial.printf with printf — Serial.printf is not available
  until after Serial.begin(); using stdio printf is safe at this
  init-time call site.
- Pass 2MHz frequency to SPI.begin() to match the expected SPI clock.

variants/linux/target.cpp: fix spiTransfer — ArduLinux's SPI only has
a 2-arg transfer(buf, len) that operates in-place; copy out→in first
then call the 2-arg form.

examples/simple_repeater/main.cpp: fix arduLinuxVFS → ardulinuxVFS
(case was wrong; symbol is defined as ardulinuxVFS in ArduLinuxFS.cpp).

* set app info to meshcored

* fix linux sx1262 wrapper

* address review: fix GPIO hardware guard, document spiTransfer, use printf

* docs: fix linux variant README (binary name, deps, SPI setup, config keys; use install(1))
@l5yth l5yth changed the title Add native Linux/Portduino repeater target Add native Linux/Ardulinux repeater target May 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants