mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-15 07:51:19 +10:00
* Migrate esp32 families to pioarduino platform
* ESP32c6 align text.handler_execute same as C3
* Use pioarduino `develop`
The latest fixes and the latest bugs!
* preliminary esp32p4.ini
* pioarduino: Update LovyanGFX
Includes Manuel's recent commit
* pioarduino 3.3.6
* pioarduino 3.3.6 *release*
chasing the release
* pioarduino: Fix OG ESP32 duplicate libs
* pioarduino: T-Beam 1W CDC mode
* pioarduino: disable network provisioning (wifiprov)
* pioarduino: use legacy esptoolpy naming (forward-compatible)
* Update lovyangfx from `develop` commit to 1.2.19
* fix esp32p4.ini
* check for esp32 w/ wifi
* esp32-p4 specific adaptations
* Switch to meshtastic/esp32_https_server fork (idf5 branch)
* don't ignore esp_lcd
* config for MUI
* fix/workaround SDMMC
* revert a6f6175, update to 3.3.8
* enable esp_hosted for esp32-p4 (experimental)
* Pioarduino 55.03.38-1
* NimBLE-Arduino -> Arduino "BLE" (3.3.x) migration (#10164)
* NimBLE-Arduino -> Arduino "BLE" (3.3.x) migration
* More NimBLE
* Fix Device Name in ATT Read Request (0x2A00).
Device Name is exposed in two places:
- Advertisement data: this is set properly in startAdvertising.
- GATT attribute Device Name (0x2A00). This one is handled internally in NimBLE
and comes from ble_svc_gap_device_name_set. This is set initially, but then
BLEDevice::createServer calls ble_svc_gap_init which resets the device name.
This causes the device to apparently "change name after pairing":
< ACL Data TX:... flags 0x00 dlen 7 #113 [hci0] 14.241149
ATT: Read Request (0x0a) len 2
Handle: 0x0003 Type: Device Name (0x2a00)
> ACL Data RX: Handle 2048 flags 0x02 dlen 11 #115 [hci0] 14.269050
ATT: Read Response (0x0b) len 6
Value[6]: 6e696d626c65 # "nimble"
Workaround this by setting the device name once again after
BLEDevice::createServer.
* Temporarily lower CORE_DEBUG_LEVEL to INFO to avoid triggering an apparent ESP-IDF Bluetooth bug when re-connecting to Pixel 8 Android devices.
Initial pairing works, but after ESP32 is rebooted, phone fails to reconnect. Meshtastic app shows it as disconnecting immediately. LightBlue shows a more detailed error "Peripheral Connection - Warning: onConnectionStatusChange: status 61" (0x3D - MIC Failure).
Bug report to Espresssif: https://github.com/espressif/esp-idf/issues/18126#issuecomment-4286197744
* Temporarily disable ble_gap_set_data_len, causes crash with Pixel 8 Android reconnect.
Crash looks like this:
[ 11966][E][BLEAdvertising.cpp:341] setScanResponseData(): ble_gap_adv_rsp_set_data: 22
[ 11975][E][BLEAdvertising.cpp:1554] start(): Host reset, wait for sync.
ERROR | ??:??:?? 11 BLE failed to start advertising
Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x420e6190 PS : 0x00060730 A0 : 0x820e158b A1 : 0x3fce50c0
A2 : 0x00000000 A3 : 0x3fcb8600 A4 : 0x3fcb85cc A5 : 0x00000000
A6 : 0x00000000 A7 : 0x00000c03 A8 : 0x00000000 A9 : 0x3fce50b0
A10 : 0x0000000e A11 : 0x00000000 A12 : 0x00000010 A13 : 0x3fce50e0
A14 : 0x00000c03 A15 : 0x00000001 SAR : 0x0000001e EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000 LBEG : 0x400570e8 LEND : 0x400570f3 LCOUNT : 0x00000000
Backtrace: 0x420e618d:0x3fce50c0 0x420e1588:0x3fce5110 0x420dfe87:0x3fce5200 0x420dfefb:0x3fce5220 0x420dff3f:0x3fce5240 0x4219602b:0x3fce5260 0x4037b0e5:0x3fce5280 0x4201edf3:0x3fce52a0
Connection seems fast enough even without this. We'll investigate the
reason for the crash and re-enable once it's safe.
---------
Co-authored-by: Catalin Patulea <cronos586@gmail.com>
* Add extension from pioarduino nag
"Jason2866.esp-decoder"
* Cleanup after merge
* ESP32: Disable classic bluetooth
* Cleanup: Fix ADC channels on new variants
* InkHUD: Fix type casting for message size in saveToFlash method
inkhud compiles again!
* update p4 esp_hosted for BT
* I thought I fixed this
* fix linker error using response file (p4 only)
* fix infinite loop
* Fix Power.cpp check warning
Local variable 'config' shadows outer variable [shadowVariable]
* Build ESP32 original with NimBLE ('custom_sdkconfig' approach). (#10235)
* Re-enable littlefs json manifest
This works locally again :)
Not sure what changed
* Re-add tool-mklittlefs
* sensecap indicator fixes after upgrade arduino-esp & lovyanGFX libs
* hackaday fix
* robot tbeam cache error fix
Co-authored-by: Copilot <copilot@github.com>
* trunk fmt
* ignore trunk
* BLEDevice::deinit() added
Co-authored-by: Copilot <copilot@github.com>
* platformio-custom: Modify mtjson target dependency to prevent fake-success. (#10291)
Co-authored-by: Copilot <copilot@github.com>
* Fix ESP32-C6 linker errors.
Align .text.handler_execute section to 4 bytes and update watchdog timer core mask configuration
Co-authored-by: Copilot <copilot@github.com>
* tlora-c6: Disable Screen
MESHTASTIC_EXCLUDE_SCREEN=1 on tlora-c6.
It doesn't have a screen, and this gets it compiling again (saving flash).
* Use mverch's iram_memset hack for all OG-ESP32
* Refactor watchdog timer initialization and handling
* use adc_channel_t in variant.h
* Fix variant headers
* More idiomatic default ethernet that doesn't break the build
* Elecrows: Delete problematic variant.cpp
Not needed after USE_ETHERNET_DEFAULT
---------
Co-authored-by: mverch67 <manuel.verch@gmx.de>
Co-authored-by: Manuel <71137295+mverch67@users.noreply.github.com>
Co-authored-by: Catalin Patulea <cronos586@gmail.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
282 lines
9.2 KiB
C++
282 lines
9.2 KiB
C++
#include "PowerFSM.h"
|
|
#include "PowerMon.h"
|
|
#include "configuration.h"
|
|
#include "esp_task_wdt.h"
|
|
#include "main.h"
|
|
|
|
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
|
#include "nimble/NimbleBluetooth.h"
|
|
#endif
|
|
|
|
#include <MeshtasticOTA.h>
|
|
|
|
#if HAS_WIFI
|
|
#include "mesh/wifi/WiFiAPClient.h"
|
|
#endif
|
|
|
|
#include "esp_mac.h"
|
|
#include "meshUtils.h"
|
|
#include "sleep.h"
|
|
#include "soc/rtc.h"
|
|
#include "target_specific.h"
|
|
#include <Preferences.h>
|
|
#include <driver/rtc_io.h>
|
|
#include <nvs.h>
|
|
#include <nvs_flash.h>
|
|
|
|
// Weak empty variant shutdown prep function.
|
|
// May be redefined by variant files.
|
|
void variant_shutdown() __attribute__((weak));
|
|
void variant_shutdown() {}
|
|
|
|
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
|
void setBluetoothEnable(bool enable)
|
|
{
|
|
#if defined(USE_WS5500) || defined(USE_CH390D)
|
|
if ((config.bluetooth.enabled == true) && (config.network.wifi_enabled == false))
|
|
#elif HAS_WIFI
|
|
if (!isWifiAvailable() && config.bluetooth.enabled == true)
|
|
#else
|
|
if (config.bluetooth.enabled == true)
|
|
#endif
|
|
{
|
|
if (!nimbleBluetooth) {
|
|
nimbleBluetooth = new NimbleBluetooth();
|
|
}
|
|
if (enable && !nimbleBluetooth->isActive()) {
|
|
powerMon->setState(meshtastic_PowerMon_State_BT_On);
|
|
nimbleBluetooth->setup();
|
|
}
|
|
// For ESP32, no way to recover from bluetooth shutdown without reboot
|
|
// BLE advertising automatically stops when MCU enters light-sleep(?)
|
|
// For deep-sleep, shutdown hardware with nimbleBluetooth->deinit(). Requires reboot to reverse
|
|
}
|
|
}
|
|
#else
|
|
void setBluetoothEnable(bool enable) {}
|
|
void updateBatteryLevel(uint8_t level) {}
|
|
#endif
|
|
|
|
void getMacAddr(uint8_t *dmac)
|
|
{
|
|
#if defined(CONFIG_IDF_TARGET_ESP32C6) && defined(CONFIG_SOC_IEEE802154_SUPPORTED)
|
|
auto res = esp_base_mac_addr_get(dmac);
|
|
assert(res == ESP_OK);
|
|
#else
|
|
auto res = esp_efuse_mac_get_default(dmac);
|
|
assert(res == ESP_OK);
|
|
#endif
|
|
}
|
|
|
|
#if HAS_32768HZ
|
|
#define CALIBRATE_ONE(cali_clk) calibrate_one(cali_clk, #cali_clk)
|
|
|
|
static uint32_t calibrate_one(rtc_cal_sel_t cal_clk, const char *name)
|
|
{
|
|
const uint32_t cal_count = 1000;
|
|
// const float factor = (1 << 19) * 1000.0f; unused var?
|
|
uint32_t cali_val;
|
|
for (int i = 0; i < 5; ++i) {
|
|
cali_val = rtc_clk_cal(cal_clk, cal_count);
|
|
}
|
|
return cali_val;
|
|
}
|
|
|
|
void enableSlowCLK()
|
|
{
|
|
rtc_clk_32k_enable(true);
|
|
|
|
CALIBRATE_ONE(RTC_CAL_RTC_MUX);
|
|
uint32_t cal_32k = CALIBRATE_ONE(RTC_CAL_32K_XTAL);
|
|
|
|
if (cal_32k == 0) {
|
|
LOG_DEBUG("32k XTAL OSC has not started up");
|
|
} else {
|
|
rtc_clk_slow_freq_set(RTC_SLOW_FREQ_32K_XTAL);
|
|
LOG_DEBUG("Switch RTC Source to 32.768kHz succeeded, using 32k XTAL");
|
|
CALIBRATE_ONE(RTC_CAL_RTC_MUX);
|
|
CALIBRATE_ONE(RTC_CAL_32K_XTAL);
|
|
}
|
|
CALIBRATE_ONE(RTC_CAL_RTC_MUX);
|
|
CALIBRATE_ONE(RTC_CAL_32K_XTAL);
|
|
if (rtc_clk_slow_freq_get() != RTC_SLOW_FREQ_32K_XTAL) {
|
|
LOG_WARN("Failed to switch 32K XTAL RTC source to 32.768kHz !!! ");
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void esp32Setup()
|
|
{
|
|
/* We explicitly don't want to do call randomSeed,
|
|
// as that triggers the esp32 core to use a less secure pseudorandom function.
|
|
uint32_t seed = esp_random();
|
|
LOG_DEBUG("Set random seed %u", seed);
|
|
randomSeed(seed);
|
|
*/
|
|
|
|
#ifdef ADC_V
|
|
pinMode(ADC_V, INPUT);
|
|
#endif
|
|
|
|
LOG_DEBUG("Total heap: %d", ESP.getHeapSize());
|
|
LOG_DEBUG("Free heap: %d", ESP.getFreeHeap());
|
|
LOG_DEBUG("Total PSRAM: %d", ESP.getPsramSize());
|
|
LOG_DEBUG("Free PSRAM: %d", ESP.getFreePsram());
|
|
|
|
nvs_stats_t nvs_stats;
|
|
auto res = nvs_get_stats(NULL, &nvs_stats);
|
|
assert(res == ESP_OK);
|
|
LOG_DEBUG("NVS: UsedEntries %d, FreeEntries %d, AllEntries %d, NameSpaces %d", nvs_stats.used_entries, nvs_stats.free_entries,
|
|
nvs_stats.total_entries, nvs_stats.namespace_count);
|
|
|
|
LOG_DEBUG("Setup Preferences in Flash Storage");
|
|
|
|
// Create object to store our persistent data
|
|
Preferences preferences;
|
|
preferences.begin("meshtastic", false);
|
|
|
|
uint32_t rebootCounter = preferences.getUInt("rebootCounter", 0);
|
|
rebootCounter++;
|
|
preferences.putUInt("rebootCounter", rebootCounter);
|
|
// store firmware version and hwrevision for access from OTA firmware
|
|
String fwrev = preferences.getString("firmwareVersion", "");
|
|
if (fwrev.compareTo(optstr(APP_VERSION)) != 0)
|
|
preferences.putString("firmwareVersion", optstr(APP_VERSION));
|
|
uint8_t hwven = preferences.getUInt("hwVendor", 0);
|
|
if (hwven != HW_VENDOR)
|
|
preferences.putUInt("hwVendor", HW_VENDOR);
|
|
preferences.end();
|
|
LOG_DEBUG("Number of Device Reboots: %d", rebootCounter);
|
|
#if !MESHTASTIC_EXCLUDE_WIFI
|
|
String version = MeshtasticOTA::getVersion();
|
|
if (version.isEmpty()) {
|
|
LOG_INFO("MeshtasticOTA firmware not available");
|
|
} else {
|
|
LOG_INFO("MeshtasticOTA firmware version %s", version.c_str());
|
|
}
|
|
MeshtasticOTA::initialize();
|
|
#endif
|
|
|
|
// enableModemSleep();
|
|
|
|
// Since we are turning on watchdogs rather late in the release schedule, we really don't want to catch any
|
|
// false positives. The wait-to-sleep timeout for shutting down radios is 30 secs, so pick 45 for now.
|
|
// #define APP_WATCHDOG_SECS 45
|
|
#define APP_WATCHDOG_SECS 90
|
|
|
|
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
|
|
const esp_task_wdt_config_t wdt_config = {
|
|
.timeout_ms = APP_WATCHDOG_SECS * 1000,
|
|
.idle_core_mask = (1U << CONFIG_FREERTOS_NUMBER_OF_CORES) - 1U,
|
|
.trigger_panic = true,
|
|
};
|
|
res = esp_task_wdt_init(&wdt_config);
|
|
if (res == ESP_ERR_INVALID_STATE) {
|
|
LOG_WARN("Task watchdog already initialized, reconfiguring existing instance");
|
|
res = esp_task_wdt_reconfigure(&wdt_config);
|
|
}
|
|
assert(res == ESP_OK);
|
|
#else
|
|
res = esp_task_wdt_init(APP_WATCHDOG_SECS, true);
|
|
if (res == ESP_ERR_INVALID_STATE) {
|
|
LOG_WARN("Task watchdog already initialized, reusing existing instance");
|
|
res = ESP_OK;
|
|
}
|
|
assert(res == ESP_OK);
|
|
#endif
|
|
res = esp_task_wdt_status(NULL);
|
|
if (res == ESP_ERR_NOT_FOUND) {
|
|
res = esp_task_wdt_add(NULL);
|
|
}
|
|
assert(res == ESP_OK);
|
|
|
|
#if HAS_32768HZ
|
|
enableSlowCLK();
|
|
#endif
|
|
}
|
|
|
|
/// loop code specific to ESP32 targets
|
|
void esp32Loop()
|
|
{
|
|
esp_task_wdt_reset(); // service our app level watchdog
|
|
|
|
// for debug printing
|
|
// radio.radioIf.canSleep();
|
|
}
|
|
|
|
void cpuDeepSleep(uint32_t msecToWake)
|
|
{
|
|
/*
|
|
Some ESP32 IOs have internal pullups or pulldowns, which are enabled by default.
|
|
If an external circuit drives this pin in deep sleep mode, current consumption may
|
|
increase due to current flowing through these pullups and pulldowns.
|
|
|
|
To isolate a pin, preventing extra current draw, call rtc_gpio_isolate() function.
|
|
For example, on ESP32-WROVER module, GPIO12 is pulled up externally.
|
|
GPIO12 also has an internal pulldown in the ESP32 chip. This means that in deep sleep,
|
|
some current will flow through these external and internal resistors, increasing deep
|
|
sleep current above the minimal possible value.
|
|
|
|
Note: we don't isolate pins that are used for the LORA, LED, i2c, or ST7735 Display for the Chatter2, spi or the wake
|
|
button(s), maybe we should not include any other GPIOs...
|
|
*/
|
|
#if SOC_RTCIO_HOLD_SUPPORTED
|
|
static const uint8_t rtcGpios[] = {
|
|
#ifndef HELTEC_VISION_MASTER_E213
|
|
// For this variant, >20mA leaks through the display if pin 2 held
|
|
// Todo: check if it's safe to remove this pin for all variants
|
|
2,
|
|
#endif
|
|
#ifndef USE_JTAG
|
|
13,
|
|
#endif
|
|
34, 35, 37};
|
|
|
|
for (int i = 0; i < sizeof(rtcGpios); i++)
|
|
rtc_gpio_isolate((gpio_num_t)rtcGpios[i]);
|
|
#endif
|
|
|
|
// FIXME, disable internal rtc pullups/pulldowns on the non isolated pins. for inputs that we aren't using
|
|
// to detect wake and in normal operation the external part drives them hard.
|
|
#ifdef BUTTON_PIN
|
|
// Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39.
|
|
#if SOC_RTCIO_HOLD_SUPPORTED && SOC_PM_SUPPORT_EXT_WAKEUP
|
|
uint64_t gpioMask = (1ULL << (config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN));
|
|
#endif
|
|
#ifdef ALT_BUTTON_WAKE
|
|
gpioMask |= (1ULL << BUTTON_PIN_ALT);
|
|
#endif
|
|
#ifdef BUTTON_NEED_PULLUP
|
|
gpio_pullup_en((gpio_num_t)BUTTON_PIN);
|
|
#endif
|
|
|
|
// Not needed because both of the current boards have external pullups
|
|
// FIXME change polarity in hw so we can wake on ANY_HIGH instead - that would allow us to use all three buttons (instead
|
|
// of just the first) gpio_pullup_en((gpio_num_t)BUTTON_PIN);
|
|
|
|
#ifdef ESP32S3_WAKE_TYPE
|
|
esp_sleep_enable_ext1_wakeup(gpioMask, ESP32S3_WAKE_TYPE);
|
|
#else
|
|
#if SOC_PM_SUPPORT_EXT_WAKEUP
|
|
#ifdef CONFIG_IDF_TARGET_ESP32
|
|
// ESP_EXT1_WAKEUP_ALL_LOW has been deprecated since esp-idf v5.4 for any other target.
|
|
esp_sleep_enable_ext1_wakeup(gpioMask, ESP_EXT1_WAKEUP_ALL_LOW);
|
|
#else
|
|
esp_sleep_enable_ext1_wakeup(gpioMask, ESP_EXT1_WAKEUP_ANY_LOW);
|
|
#endif
|
|
#endif
|
|
|
|
#endif // #end ESP32S3_WAKE_TYPE
|
|
#endif
|
|
variant_shutdown();
|
|
|
|
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
|
|
// We want RTC peripherals to stay on
|
|
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
|
#endif
|
|
|
|
esp_sleep_enable_timer_wakeup(msecToWake * 1000ULL); // call expects usecs
|
|
esp_deep_sleep_start(); // TBD mA sleep current (battery)
|
|
}
|