-
Notifications
You must be signed in to change notification settings - Fork 989
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multi gpiochip support for native environment #5743
base: master
Are you sure you want to change the base?
Conversation
|
Signed the CLA |
Sadly I can't get the build green right now. Seems some like to push to main broken code/tests :-( PRs would be better, instead of pushing to main^^ |
Sorry about that. It's Github CI work. Pushing to master is the only way to test it. The PR here looks great. I'll test drive it on my various rigs as soon as I can. |
While tinkering with Meshtastic on the popular Radxa Zero 3E/W, trying to employ an ebyte E22-900M30S I stumbled across the SBCs GPIO partitioning.
However, let's recap what an E22-900M30S requires in regards to SPI/GPIO. Motivated by Xiao BLE/BLE Sense + Ebyte E22-900M30S, an E22-900M30S requires at least:
In case DIO2 is driving TXEN, two GPIOs can be saved, which is most often the setup seen and employed by myself.
Even though the Radxa Zero 3E/Ws size and its 40-Pin GPIO header provide a first impression as if the header is RPI compliant: you are to some extend mislead.
Let's start with identifying the Radxas single SPI interface (see below), which employs PIN 19, 21, 23 and 24.
As there are just four more GPIOs required (NRST, DIO1, RXEN, BUSY), one could employ any close by GPIOs.
However, the moment one will perform a
gpioinfo
, one will detect the following (full dump: gpioinfo.log ):Note, I annotated already the PINs that enable the sole SPI interface on gpiochip4. No matter which GPIO PINs were chosen previsouly, it is by no means possible to optimise the handling of BUSY, DIO1, RXEN and NRST by the same gpiochip that already handles SPI, as gpiochip4 just handles 3 further GPIOs. Especially, as meshtastic wants to control the CS*, the current config format is limited to specifying the gpiochip that handles CS*.
Now, when specifying a
config.yaml
, today it can solely support a mapping of PIN name and number, while gpiochip can solely be specified once globally. E.g.:The PIN number in case of native is anyway a bit odd, as it does not really mean PIN no. but rather line. Thus, if there is a mismatch between both, one has to use line in Linux (i.e. Meshtastic native environment).
With this patch, I propose to extend this format to allow for each PIN to specify its gpiochip and line. The old format is kept for backwards compatibility, while the current gpiochip can be considered as 'fallback' or 'globally gpiochip'. Thus, with this given patch, the above format is supported as well as the below:
You can notice, that TXen still employs the old format, which the YAML parser handles fine.
But how does that work, and why is it just a matter of parsing a YAML and enabling it? Already today, the portduino framework supports the handling of gpiochip and line per PIN. In particular the functions
LinuxGPIOPin(pin_size_t n, const char *chipLabel, const int linuxPinNum, const char *portduinoPinName);
(https://github.com/meshtastic/framework-portduino/blob/master/cores/portduino/linux/gpio/LinuxGPIOPin.h#L40), wheren
is employed for the PIN,linuxPinNum
used for theline
within Linux, whilechipLabel
obviously is meant for the gpiochip name. The last parameterportduinoPinName
is an artificial name to make portduino happy, which could ben
as string.The magic of setting portduino properly up in regards to the mapping is subsequently taken care of in portduinos
void gpioBind(GPIOPinIf *p)
(https://github.com/meshtastic/framework-portduino/blob/master/cores/portduino/PortduinoGPIO.cpp#L38). Luckily, this is handled already well insrc/platform/portduino/PortduinoGlue.cpp
->int initGPIOPin(int pinNum, const std::string gpioChipName)
.Thus it is just a matter of enhancing
src/platform/portduino/PortduinoGlue.cpp
->int initGPIOPin(int pinNum, const std::string gpioChipName)
. As one can see, I extendedinitGPIOPin
with the parameterline
and reworked the YAML parsing, while keeping the backwards compatibility. To ensure, that all affected spots were detected, the individual enum such ascs
was reworked tocs_pin
,cs_line
andcs_gpiochip
to follow the current implementation pattern.In light of Meshtastic, the patch and the new config format mean, that Meshtastic internally uses the PIN no., which must not be the true line number. While portduino was made aware of the mapping of PIN no. to gpiochip and line, and thus can perform a seemless mapping. For the new config, it is solely crucial that the PIN no. is unique, otherwise the mapping won't work properly in portduino. Meanwhile, the PIN no. could be even artificially chosen.
Last, I reworked code that was multiple times copied into structs and foreachs.
With this, not only Radxa Zero 3E/W can perform a native meshtastic with the above (2nd)
config.yaml
, but one could also employ long term multiple gpiochips of other sorts for a chosen LoRa chip.