Move device code from main.cpp to earlyInitVariant (#9438)

This commit is contained in:
Jonathan Bennett
2026-01-26 11:54:14 -06:00
committed by GitHub
parent 0770f25e79
commit c038cfe69a
25 changed files with 208 additions and 148 deletions

View File

@@ -61,11 +61,7 @@ int32_t TrackballInterruptBase::runOnce()
uint32_t pressDuration = millis() - pressStartTime;
bool buttonStillPressed = false;
#if defined(T_DECK)
buttonStillPressed = (this->action == TB_ACTION_PRESSED);
#else
buttonStillPressed = !digitalRead(_pinPress);
#endif
if (!buttonStillPressed) {
// Button released
@@ -135,7 +131,7 @@ int32_t TrackballInterruptBase::runOnce()
}
#if defined(T_DECK) // T-deck gets a super-simple debounce on trackball
if (this->action == TB_ACTION_PRESSED && !pressDetected) {
if (this->action == TB_ACTION_PRESSED && (!pressDetected || pressStartTime == 0)) {
// Start long press detection
pressDetected = true;
pressStartTime = millis();

View File

@@ -43,10 +43,6 @@
#include "MessageStore.h"
#endif
#ifdef ELECROW_ThinkNode_M5
PCA9557 io(0x18, &Wire);
#endif
#ifdef ARCH_ESP32
#include "freertosinc.h"
#if !MESHTASTIC_EXCLUDE_WEBSERVER
@@ -312,6 +308,9 @@ __attribute__((weak, noinline)) bool loopCanSleep()
void lateInitVariant() __attribute__((weak));
void lateInitVariant() {}
void earlyInitVariant() __attribute__((weak));
void earlyInitVariant() {}
// NRF52 (and probably other platforms) can report when system is in power failure mode
// (eg. too low battery voltage) and operating it is unsafe (data corruption, bootloops, etc).
// For example NRF52 will prevent any flash writes in that case automatically
@@ -367,27 +366,14 @@ void setup()
// boot sequence will follow when battery level raises to safe mode
waitUntilPowerLevelSafe();
// TODO remove all device-specific setup code to variant.cpp
#if defined(R1_NEO)
pinMode(DCDC_EN_HOLD, OUTPUT);
digitalWrite(DCDC_EN_HOLD, HIGH);
pinMode(NRF_ON, OUTPUT);
digitalWrite(NRF_ON, HIGH);
#endif
// Defined in variant.cpp for early init code
earlyInitVariant();
#if defined(PIN_POWER_EN)
pinMode(PIN_POWER_EN, OUTPUT);
digitalWrite(PIN_POWER_EN, HIGH);
#endif
#if defined(ELECROW_ThinkNode_M5)
Wire.begin(48, 47);
io.pinMode(PCA_PIN_EINK_EN, OUTPUT);
io.pinMode(PCA_PIN_POWER_EN, OUTPUT);
io.digitalWrite(PCA_PIN_POWER_EN, HIGH);
// io.pinMode(C2_PIN, OUTPUT);
#endif
#ifdef LED_POWER
pinMode(LED_POWER, OUTPUT);
digitalWrite(LED_POWER, LED_STATE_ON);
@@ -412,62 +398,6 @@ void setup()
#endif
#endif
#if defined(T_DECK)
// GPIO10 manages all peripheral power supplies
// Turn on peripheral power immediately after MUC starts.
// If some boards are turned on late, ESP32 will reset due to low voltage.
// ESP32-C3(Keyboard) , MAX98357A(Audio Power Amplifier) ,
// TF Card , Display backlight(AW9364DNR) , AN48841B(Trackball) , ES7210(Decoder)
pinMode(KB_POWERON, OUTPUT);
digitalWrite(KB_POWERON, HIGH);
// T-Deck has all three SPI peripherals (TFT, SD, LoRa) attached to the same SPI bus
// We need to initialize all CS pins in advance otherwise there will be SPI communication issues
// e.g. when detecting the SD card
pinMode(LORA_CS, OUTPUT);
digitalWrite(LORA_CS, HIGH);
pinMode(SDCARD_CS, OUTPUT);
digitalWrite(SDCARD_CS, HIGH);
pinMode(TFT_CS, OUTPUT);
digitalWrite(TFT_CS, HIGH);
delay(100);
#elif defined(T_DECK_PRO)
pinMode(LORA_EN, OUTPUT);
digitalWrite(LORA_EN, HIGH);
pinMode(LORA_CS, OUTPUT);
digitalWrite(LORA_CS, HIGH);
pinMode(SDCARD_CS, OUTPUT);
digitalWrite(SDCARD_CS, HIGH);
pinMode(PIN_EINK_CS, OUTPUT);
digitalWrite(PIN_EINK_CS, HIGH);
#elif defined(T_LORA_PAGER)
pinMode(LORA_CS, OUTPUT);
digitalWrite(LORA_CS, HIGH);
pinMode(SDCARD_CS, OUTPUT);
digitalWrite(SDCARD_CS, HIGH);
pinMode(TFT_CS, OUTPUT);
digitalWrite(TFT_CS, HIGH);
pinMode(KB_INT, INPUT_PULLUP);
// io expander
io.begin(Wire, XL9555_SLAVE_ADDRESS0, SDA, SCL);
io.pinMode(EXPANDS_DRV_EN, OUTPUT);
io.digitalWrite(EXPANDS_DRV_EN, HIGH);
io.pinMode(EXPANDS_AMP_EN, OUTPUT);
io.digitalWrite(EXPANDS_AMP_EN, LOW);
io.pinMode(EXPANDS_LORA_EN, OUTPUT);
io.digitalWrite(EXPANDS_LORA_EN, HIGH);
io.pinMode(EXPANDS_GPS_EN, OUTPUT);
io.digitalWrite(EXPANDS_GPS_EN, HIGH);
io.pinMode(EXPANDS_KB_EN, OUTPUT);
io.digitalWrite(EXPANDS_KB_EN, HIGH);
io.pinMode(EXPANDS_SD_EN, OUTPUT);
io.digitalWrite(EXPANDS_SD_EN, HIGH);
io.pinMode(EXPANDS_GPIO_EN, OUTPUT);
io.digitalWrite(EXPANDS_GPIO_EN, HIGH);
io.pinMode(EXPANDS_SD_PULLEN, INPUT);
#elif defined(HACKADAY_COMMUNICATOR)
pinMode(KB_INT, INPUT);
#endif
concurrency::hasBeenSetup = true;
meshtastic_Config_DisplayConfig_OledType screen_model =

View File

@@ -26,8 +26,8 @@ extern NRF52Bluetooth *nrf52Bluetooth;
#if ARCH_PORTDUINO
extern HardwareSPI *DisplaySPI;
extern HardwareSPI *LoraSPI;
#endif
extern ScanI2C::DeviceAddress screen_found;
extern ScanI2C::DeviceAddress cardkb_found;
extern uint8_t kb_model;
@@ -47,16 +47,16 @@ extern bool isUSBPowered;
extern Adafruit_DRV2605 drv;
#endif
#ifdef HAS_PCA9557
#include <PCA9557.h>
extern PCA9557 io;
#endif
#ifdef HAS_I2S
#include "AudioThread.h"
extern AudioThread *audioThread;
#endif
#ifdef ELECROW_ThinkNode_M5
#include <PCA9557.h>
extern PCA9557 io;
#endif
#ifdef HAS_UDP_MULTICAST
#include "mesh/udp/UdpMulticastHandler.h"
extern UdpMulticastHandler *udpHandler;

View File

@@ -5,7 +5,7 @@ This directory tree is designed to solve two problems.
- The ESP32 arduino/platformio project doesn't support the nice "if initVariant() is found, call that after init" behavior of the nrf52 builds (they use initVariant() internally).
- Over the years a lot of 'board specific' init code has been added to init() in main.cpp. It would be great to have a general/clean mechanism to allow developers to specify board specific/unique code in a clean fashion without mucking in main.
So we are borrowing the initVariant() ideas here (by using weak gcc references). You can now define lateInitVariant() if your board needs it.
So we are borrowing the initVariant() ideas here (by using weak gcc references). You can now define earlyInitVariant() and lateInitVariant() if your board needs them. earlyInitVariant() runs at the beginning of setup() directly after waitUntilPowerLevelSafe(); while lateInitVariant() runs after the LoRa radio is initialized.
If you'd like a board specific variant to be run, add the variant.cpp file to an appropriately named
subdirectory and check for \_VARIANT_boardname in the cpp file (so that your code is only built for your board).

View File

@@ -430,15 +430,6 @@ void cpuDeepSleep(uint32_t msecToWake)
Serial1.end();
#endif
#ifdef TTGO_T_ECHO
// To power off the T-Echo, the display must be set
// as an input pin; otherwise, there will be leakage current.
pinMode(PIN_EINK_CS, INPUT);
pinMode(PIN_EINK_DC, INPUT);
pinMode(PIN_EINK_RES, INPUT);
pinMode(PIN_EINK_BUSY, INPUT);
#endif
setBluetoothEnable(false);
#ifdef RAK4630
@@ -449,57 +440,8 @@ void cpuDeepSleep(uint32_t msecToWake)
// RAK-12039 set pin for Air quality sensor
digitalWrite(AQ_SET_PIN, LOW);
#endif
#ifdef RAK14014
// GPIO restores input status, otherwise there will be leakage current
nrf_gpio_cfg_default(TFT_BL);
nrf_gpio_cfg_default(TFT_DC);
nrf_gpio_cfg_default(TFT_CS);
nrf_gpio_cfg_default(TFT_SCLK);
nrf_gpio_cfg_default(TFT_MOSI);
nrf_gpio_cfg_default(TFT_MISO);
nrf_gpio_cfg_default(SCREEN_TOUCH_INT);
nrf_gpio_cfg_default(WB_I2C1_SCL);
nrf_gpio_cfg_default(WB_I2C1_SDA);
// nrf_gpio_cfg_default(WB_I2C2_SCL);
// nrf_gpio_cfg_default(WB_I2C2_SDA);
#endif
#endif
#ifdef MESHLINK
#ifdef PIN_WD_EN
digitalWrite(PIN_WD_EN, LOW);
#endif
#endif
#if defined(HELTEC_MESH_NODE_T114) || defined(HELTEC_MESH_SOLAR)
nrf_gpio_cfg_default(PIN_GPS_PPS);
detachInterrupt(PIN_GPS_PPS);
detachInterrupt(PIN_BUTTON1);
#endif
#ifdef ELECROW_ThinkNode_M1
for (int pin = 0; pin < 48; pin++) {
if (pin == 17 || pin == 19 || pin == 20 || pin == 22 || pin == 23 || pin == 24 || pin == 25 || pin == 9 || pin == 10 ||
pin == PIN_BUTTON1 || pin == PIN_BUTTON2) {
continue;
}
pinMode(pin, OUTPUT);
}
for (int pin = 0; pin < 48; pin++) {
if (pin == 17 || pin == 19 || pin == 20 || pin == 22 || pin == 23 || pin == 24 || pin == 25 || pin == 9 || pin == 10 ||
pin == PIN_BUTTON1 || pin == PIN_BUTTON2) {
continue;
}
digitalWrite(pin, LOW);
}
for (int pin = 0; pin < 48; pin++) {
if (pin == 17 || pin == 19 || pin == 20 || pin == 22 || pin == 23 || pin == 24 || pin == 25 || pin == 9 || pin == 10 ||
pin == PIN_BUTTON1 || pin == PIN_BUTTON2) {
continue;
}
NRF_GPIO->DIRCLR = (1 << pin);
}
#endif
// Run shutdown code if specified in variant.cpp
variant_shutdown();
// Sleepy trackers or sensors can low power "sleep"

View File

@@ -11,6 +11,10 @@ custom_meshtastic_requires_dfu = false
extends = esp32s3_base
board = ESP32-S3-WROOM-1-N4
build_src_filter =
${esp32s3_base.build_src_filter}
+<../variants/esp32s3/ELECROW-ThinkNode-M5>
build_flags =
${esp32s3_base.build_flags}
-D ELECROW_ThinkNode_M5

View File

@@ -0,0 +1,12 @@
#include "variant.h"
#include <PCA9557.h>
PCA9557 io(0x18, &Wire);
void earlyInitVariant()
{
Wire.begin(48, 47);
io.pinMode(PCA_PIN_EINK_EN, OUTPUT);
io.pinMode(PCA_PIN_POWER_EN, OUTPUT);
io.digitalWrite(PCA_PIN_POWER_EN, HIGH);
}

View File

@@ -4,6 +4,8 @@
#define UART_TX 43
#define UART_RX 44
#define HAS_PCA9557
// LED
// Both of these are on the GPIO expander
#define PCA_LED_USER 1 // the Blue LED

View File

@@ -6,6 +6,10 @@ board_check = true
board_build.partitions = default_16MB.csv
upload_protocol = esptool
build_src_filter =
${esp32s3_base.build_src_filter}
+<../variants/esp32s3/hackaday-communicator>
build_flags = ${esp32s3_base.build_flags}
-D HACKADAY_COMMUNICATOR
-D BOARD_HAS_PSRAM
@@ -13,4 +17,4 @@ build_flags = ${esp32s3_base.build_flags}
lib_deps = ${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-Arduino_GFX packageName=https://github.com/meshtastic/Arduino_GFX gitBranch=master
https://github.com/meshtastic/Arduino_GFX/archive/054e81ffaf23784830a734e3c184346789349406.zip
https://github.com/meshtastic/Arduino_GFX/archive/054e81ffaf23784830a734e3c184346789349406.zip

View File

@@ -0,0 +1,6 @@
#include "variant.h"
#include "Arduino.h"
void earlyInitVariant()
{
pinMode(KB_INT, INPUT);
}

View File

@@ -15,6 +15,10 @@ board = t-deck-pro
board_check = true
upload_protocol = esptool
build_src_filter =
${esp32s3_base.build_src_filter}
+<../variants/esp32s3/t-deck-pro>
build_flags =
${esp32s3_base.build_flags} -I variants/esp32s3/t-deck-pro
-D T_DECK_PRO

View File

@@ -0,0 +1,14 @@
#include "variant.h"
#include "Arduino.h"
void earlyInitVariant()
{
pinMode(LORA_EN, OUTPUT);
digitalWrite(LORA_EN, HIGH);
pinMode(LORA_CS, OUTPUT);
digitalWrite(LORA_CS, HIGH);
pinMode(SDCARD_CS, OUTPUT);
digitalWrite(SDCARD_CS, HIGH);
pinMode(PIN_EINK_CS, OUTPUT);
digitalWrite(PIN_EINK_CS, HIGH);
}

View File

@@ -17,6 +17,10 @@ board_check = true
board_build.partitions = default_16MB.csv
upload_protocol = esptool
build_src_filter =
${esp32s3_base.build_src_filter}
+<../variants/esp32s3/t-deck>
build_flags = ${esp32s3_base.build_flags}
-D T_DECK
-D BOARD_HAS_PSRAM

View File

@@ -0,0 +1,23 @@
#include "variant.h"
#include "Arduino.h"
void earlyInitVariant()
{
// GPIO10 manages all peripheral power supplies
// Turn on peripheral power immediately after MUC starts.
// If some boards are turned on late, ESP32 will reset due to low voltage.
// ESP32-C3(Keyboard) , MAX98357A(Audio Power Amplifier) ,
// TF Card , Display backlight(AW9364DNR) , AN48841B(Trackball) , ES7210(Decoder)
pinMode(KB_POWERON, OUTPUT);
digitalWrite(KB_POWERON, HIGH);
// T-Deck has all three SPI peripherals (TFT, SD, LoRa) attached to the same SPI bus
// We need to initialize all CS pins in advance otherwise there will be SPI communication issues
// e.g. when detecting the SD card
pinMode(LORA_CS, OUTPUT);
digitalWrite(LORA_CS, HIGH);
pinMode(SDCARD_CS, OUTPUT);
digitalWrite(SDCARD_CS, HIGH);
pinMode(TFT_CS, OUTPUT);
digitalWrite(TFT_CS, HIGH);
delay(100);
}

View File

@@ -17,6 +17,10 @@ board_check = true
board_build.partitions = default_16MB.csv
upload_protocol = esptool
build_src_filter =
${esp32s3_base.build_src_filter}
+<../variants/esp32s3/tlora-pager>
build_flags = ${esp32s3_base.build_flags}
-I variants/esp32s3/tlora-pager
-D T_LORA_PAGER

View File

@@ -0,0 +1,31 @@
#include "variant.h"
#include "ExtensionIOXL9555.hpp"
extern ExtensionIOXL9555 io;
void earlyInitVariant()
{
pinMode(LORA_CS, OUTPUT);
digitalWrite(LORA_CS, HIGH);
pinMode(SDCARD_CS, OUTPUT);
digitalWrite(SDCARD_CS, HIGH);
pinMode(TFT_CS, OUTPUT);
digitalWrite(TFT_CS, HIGH);
pinMode(KB_INT, INPUT_PULLUP);
// io expander
io.begin(Wire, XL9555_SLAVE_ADDRESS0, SDA, SCL);
io.pinMode(EXPANDS_DRV_EN, OUTPUT);
io.digitalWrite(EXPANDS_DRV_EN, HIGH);
io.pinMode(EXPANDS_AMP_EN, OUTPUT);
io.digitalWrite(EXPANDS_AMP_EN, LOW);
io.pinMode(EXPANDS_LORA_EN, OUTPUT);
io.digitalWrite(EXPANDS_LORA_EN, HIGH);
io.pinMode(EXPANDS_GPS_EN, OUTPUT);
io.digitalWrite(EXPANDS_GPS_EN, HIGH);
io.pinMode(EXPANDS_KB_EN, OUTPUT);
io.digitalWrite(EXPANDS_KB_EN, HIGH);
io.pinMode(EXPANDS_SD_EN, OUTPUT);
io.digitalWrite(EXPANDS_SD_EN, HIGH);
io.pinMode(EXPANDS_GPIO_EN, OUTPUT);
io.digitalWrite(EXPANDS_GPIO_EN, HIGH);
io.pinMode(EXPANDS_SD_PULLEN, INPUT);
}

View File

@@ -42,3 +42,21 @@ void initVariant()
pinMode(PIN_LED3, OUTPUT);
ledOff(PIN_LED3);
}
void variant_shutdown()
{
for (int pin = 0; pin < 48; pin++) {
if (pin == SX126X_BUSY || pin == PIN_SPI_SCK || pin == SX126X_DIO1 || pin == PIN_SPI_MOSI || pin == PIN_SPI_MISO ||
pin == SX126X_CS || pin == SX126X_RESET || pin == PIN_NFC1 || pin == PIN_NFC2 || pin == PIN_BUTTON1 ||
pin == PIN_BUTTON2) {
continue;
}
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
if (pin >= 32) {
NRF_P1->DIRCLR = (1 << (pin - 32));
} else {
NRF_GPIO->DIRCLR = (1 << pin);
}
}
}

View File

@@ -19,6 +19,7 @@
*/
#include "variant.h"
#include "Arduino.h"
#include "nrf.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
@@ -36,3 +37,10 @@ void initVariant()
pinMode(PIN_LED1, OUTPUT);
ledOff(PIN_LED1);
}
void variant_shutdown()
{
nrf_gpio_cfg_default(PIN_GPS_PPS);
detachInterrupt(PIN_GPS_PPS);
detachInterrupt(PIN_BUTTON1);
}

View File

@@ -19,6 +19,7 @@
*/
#include "variant.h"
#include "Arduino.h"
#include "nrf.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
@@ -36,3 +37,10 @@ void initVariant()
pinMode(PIN_LED1, OUTPUT);
ledOff(PIN_LED1);
}
void variant_shutdown()
{
nrf_gpio_cfg_default(PIN_GPS_PPS);
detachInterrupt(PIN_GPS_PPS);
detachInterrupt(PIN_BUTTON1);
}

View File

@@ -156,7 +156,7 @@ No longer populated on PCB
// The bluetooth transmit power on the nRF52840 is adjustable from -20dB to +8dB in steps of 4dB
// so NRF52_BLE_TX_POWER can be set to -20, -16, -12, -8, -4, 0 (default), 4, and 8.
//#define NRF52_BLE_TX_POWER 8
// #define NRF52_BLE_TX_POWER 8
/*
* GPS pins

View File

@@ -19,6 +19,7 @@
*/
#include "variant.h"
#include "Arduino.h"
#include "nrf.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
@@ -38,3 +39,10 @@ void initVariant()
digitalWrite(PIN_SCREEN_VDD_CTL, LOW); // Start with power on
#endif
}
void variant_shutdown()
{
nrf_gpio_cfg_default(PIN_GPS_PPS);
detachInterrupt(PIN_GPS_PPS);
detachInterrupt(PIN_BUTTON1);
}

View File

@@ -20,4 +20,11 @@ void initVariant()
pinMode(PIN_WD_EN, OUTPUT);
digitalWrite(PIN_WD_EN, HIGH); // Enable the Watchdog at boot
#endif
}
void variant_shutdown()
{
#ifdef PIN_WD_EN
digitalWrite(PIN_WD_EN, LOW);
#endif
}

View File

@@ -43,3 +43,11 @@ void initVariant()
// pinMode(PIN_3V3_EN, OUTPUT);
// digitalWrite(PIN_3V3_EN, HIGH);
}
void earlyInitVariant()
{
pinMode(DCDC_EN_HOLD, OUTPUT);
digitalWrite(DCDC_EN_HOLD, HIGH);
pinMode(NRF_ON, OUTPUT);
digitalWrite(NRF_ON, HIGH);
}

View File

@@ -42,4 +42,21 @@ void initVariant()
// 3V3 Power Rail
pinMode(PIN_3V3_EN, OUTPUT);
digitalWrite(PIN_3V3_EN, HIGH);
}
void variant_shutdown()
{
// GPIO restores input status, otherwise there will be leakage current
nrf_gpio_cfg_default(TFT_BL);
nrf_gpio_cfg_default(TFT_DC);
nrf_gpio_cfg_default(TFT_CS);
nrf_gpio_cfg_default(TFT_SCLK);
nrf_gpio_cfg_default(TFT_MOSI);
nrf_gpio_cfg_default(TFT_MISO);
nrf_gpio_cfg_default(SCREEN_TOUCH_INT);
nrf_gpio_cfg_default(WB_I2C1_SCL);
nrf_gpio_cfg_default(WB_I2C1_SDA);
// nrf_gpio_cfg_default(WB_I2C2_SCL);
// nrf_gpio_cfg_default(WB_I2C2_SDA);
}

View File

@@ -42,3 +42,13 @@ void initVariant()
pinMode(PIN_LED3, OUTPUT);
ledOff(PIN_LED3);
}
void variant_shutdown()
{
// To power off the T-Echo, the display must be set
// as an input pin; otherwise, there will be leakage current.
pinMode(PIN_EINK_CS, INPUT);
pinMode(PIN_EINK_DC, INPUT);
pinMode(PIN_EINK_RES, INPUT);
pinMode(PIN_EINK_BUSY, INPUT);
}