From b6e0b416712f5be48b521fcc0304f6ad82df588f Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Mon, 26 Jan 2026 14:56:27 -0600 Subject: [PATCH 01/16] Add OTA BLE service and device settings support Introduces OTA (Over-the-Air) firmware update BLE service with new UUIDs and implementation files. Adds device settings management (header and source), updates build system for ESP-IDF/Arduino hybrid, and includes new partition and configuration files for dual OTA support. Also updates BMS CAN initialization and various build flags for improved compatibility. --- CMakeLists.txt | 3 + inc/sp140/ble/ble_ids.h | 7 + inc/sp140/ble/ota_service.h | 18 + inc/sp140/bms.h | 1 + inc/sp140/device_settings.h | 17 + partitions.csv | 6 + platformio.ini | 7 +- sdkconfig.OpenPPG-CESP32S3-CAN-SP140 | 2018 +++++++++++++++++ sdkconfig.defaults | 6 + src/CMakeLists.txt | 5 + src/sp140/CMakeLists.txt | 6 + src/sp140/ble/ble_core.cpp | 3 + src/sp140/ble/ota_service.cpp | 150 ++ src/sp140/buzzer.cpp | 4 +- .../{extra-data.ino => device_settings.cpp} | 5 + src/sp140/esc.cpp | 4 +- src/sp140/lvgl/lvgl_updates.cpp | 6 +- src/sp140/{sp140.ino => main.cpp} | 19 +- 18 files changed, 2275 insertions(+), 10 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 inc/sp140/ble/ota_service.h create mode 100644 inc/sp140/device_settings.h create mode 100644 partitions.csv create mode 100644 sdkconfig.OpenPPG-CESP32S3-CAN-SP140 create mode 100644 sdkconfig.defaults create mode 100644 src/CMakeLists.txt create mode 100644 src/sp140/CMakeLists.txt create mode 100644 src/sp140/ble/ota_service.cpp rename src/sp140/{extra-data.ino => device_settings.cpp} (98%) rename src/sp140/{sp140.ino => main.cpp} (98%) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..4cfeb78 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.16.0) +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(openppg_controller) diff --git a/inc/sp140/ble/ble_ids.h b/inc/sp140/ble/ble_ids.h index 6d22eab..bdb3357 100644 --- a/inc/sp140/ble/ble_ids.h +++ b/inc/sp140/ble/ble_ids.h @@ -67,4 +67,11 @@ #define CONTROLLER_SERVICE_UUID "01C63B60-0891-4655-BBCA-8E745C48A175" #define CONTROLLER_TELEMETRY_UUID "01C63B61-0891-4655-BBCA-8E745C48A176" +// ============================================================================ +// OTA Service (Firmware Update) +// ============================================================================ +#define OTA_SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" +#define OTA_CONTROL_UUID "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" +#define OTA_DATA_UUID "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" + #endif // INC_SP140_BLE_BLE_IDS_H_ diff --git a/inc/sp140/ble/ota_service.h b/inc/sp140/ble/ota_service.h new file mode 100644 index 0000000..d538f69 --- /dev/null +++ b/inc/sp140/ble/ota_service.h @@ -0,0 +1,18 @@ +#ifndef INC_SP140_BLE_OTA_SERVICE_H_ +#define INC_SP140_BLE_OTA_SERVICE_H_ + +#include + +/** + * Initialize the OTA BLE service. + * @param pServer Pointer to the NimBLEServer instance. + */ +void initOtaBleService(NimBLEServer* pServer); + +/** + * Check if an OTA update is currently in progress. + * @return true if OTA is active (should pause other tasks) + */ +bool isOtaInProgress(); + +#endif // INC_SP140_BLE_OTA_SERVICE_H_ diff --git a/inc/sp140/bms.h b/inc/sp140/bms.h index fcde6e9..aa0fea5 100644 --- a/inc/sp140/bms.h +++ b/inc/sp140/bms.h @@ -15,5 +15,6 @@ extern STR_BMS_TELEMETRY_140 bmsTelemetryData; extern BMS_CAN* bms_can; // BMS functions +bool initBMSCAN(SPIClass* spi); void updateBMSData(); void printBMSData(); diff --git a/inc/sp140/device_settings.h b/inc/sp140/device_settings.h new file mode 100644 index 0000000..4fc0acc --- /dev/null +++ b/inc/sp140/device_settings.h @@ -0,0 +1,17 @@ +#ifndef INC_SP140_DEVICE_SETTINGS_H_ +#define INC_SP140_DEVICE_SETTINGS_H_ + +#include "structs.h" +#include "esp32s3-config.h" + +// Constants +extern const unsigned int DEFAULT_SCREEN_ROTATION; +void refreshDeviceData(); +void writeDeviceData(); +void resetDeviceData(); +void parse_serial_commands(); +void send_device_data(); +bool sanitizeDeviceData(); +void debugHardwareConfig(const HardwareConfig& config); + +#endif // INC_SP140_DEVICE_SETTINGS_H_ diff --git a/partitions.csv b/partitions.csv new file mode 100644 index 0000000..778a346 --- /dev/null +++ b/partitions.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, , 0x4000, +otadata, data, ota, , 0x2000, +app0, app, ota_0, , 3M, +app1, app, ota_1, , 3M, +spiffs, data, spiffs, , 1500K, diff --git a/platformio.ini b/platformio.ini index 7ed8fb2..2abb15d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -23,8 +23,9 @@ lib_ignore = [env:OpenPPG-CESP32S3-CAN-SP140] platform = espressif32@6.12.0 board = m5stack-stamps3 -framework = arduino -src_folder = sp140 +framework = arduino, espidf +board_build.partitions = partitions.csv +src_folder = sp140 ; Commented out as we are using standard src structure ; If esptool.py complains about missing intelhex, install into the tool package: ; ~/.platformio/penv/bin/python -m pip install intelhex -t ~/.platformio/packages/tool-esptoolpy extra_scripts = @@ -38,6 +39,8 @@ build_flags = -D LV_LVGL_H_INCLUDE_SIMPLE ; Disable legacy individual BLE characteristics (use packed binary only) -D DISABLE_LEGACY_BLE_TELEMETRY + -D CONFIG_ARDUINO_LOOP_STACK_SIZE=8192 + -Wno-error=format build_type = debug debug_speed = 12000 diff --git a/sdkconfig.OpenPPG-CESP32S3-CAN-SP140 b/sdkconfig.OpenPPG-CESP32S3-CAN-SP140 new file mode 100644 index 0000000..16e3198 --- /dev/null +++ b/sdkconfig.OpenPPG-CESP32S3-CAN-SP140 @@ -0,0 +1,2018 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TARGET_ARCH_XTENSA=y +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009 + +# +# SDK tool configuration +# +CONFIG_SDK_TOOLPREFIX="xtensa-esp32s3-elf-" +# CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS is not set +# end of SDK tool configuration + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# end of Build type + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 +# end of Application manager + +# +# Bootloader config +# +CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0 +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 + +# +# Serial Flash Configurations +# +# CONFIG_BOOTLOADER_FLASH_DC_AWARE is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Serial Flash Configurations + +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +# end of Bootloader config + +# +# Security features +# +CONFIG_SECURE_BOOT_SUPPORTS_RSA=y +CONFIG_SECURE_TARGET_HAS_SECURE_ROM_DL_MODE=y +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +# end of Security features + +# +# Boot ROM Behavior +# +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_OCT_FLASH is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +CONFIG_ESPTOOLPY_S3_STR=y +# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="8MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +# CONFIG_ESPTOOLPY_MONITOR_BAUD_CONSOLE is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +# CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# Arduino Configuration +# +CONFIG_ARDUINO_VARIANT="esp32s3" +CONFIG_ENABLE_ARDUINO_DEPENDS=y +CONFIG_AUTOSTART_ARDUINO=y +# CONFIG_ARDUINO_RUN_CORE0 is not set +CONFIG_ARDUINO_RUN_CORE1=y +# CONFIG_ARDUINO_RUN_NO_AFFINITY is not set +CONFIG_ARDUINO_RUNNING_CORE=1 +CONFIG_ARDUINO_LOOP_STACK_SIZE=8192 +# CONFIG_ARDUINO_EVENT_RUN_CORE0 is not set +CONFIG_ARDUINO_EVENT_RUN_CORE1=y +# CONFIG_ARDUINO_EVENT_RUN_NO_AFFINITY is not set +CONFIG_ARDUINO_EVENT_RUNNING_CORE=1 +# CONFIG_ARDUINO_SERIAL_EVENT_RUN_CORE0 is not set +# CONFIG_ARDUINO_SERIAL_EVENT_RUN_CORE1 is not set +CONFIG_ARDUINO_SERIAL_EVENT_RUN_NO_AFFINITY=y +CONFIG_ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE=-1 +CONFIG_ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE=2048 +CONFIG_ARDUINO_SERIAL_EVENT_TASK_PRIORITY=24 +CONFIG_ARDUINO_UDP_RUN_CORE0=y +# CONFIG_ARDUINO_UDP_RUN_CORE1 is not set +# CONFIG_ARDUINO_UDP_RUN_NO_AFFINITY is not set +CONFIG_ARDUINO_UDP_RUNNING_CORE=0 +CONFIG_ARDUINO_UDP_TASK_PRIORITY=3 +# CONFIG_ARDUINO_ISR_IRAM is not set +# CONFIG_DISABLE_HAL_LOCKS is not set + +# +# Debug Log Configuration +# +# CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_NONE is not set +CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y +# CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_WARN is not set +# CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_INFO is not set +# CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1 +# CONFIG_ARDUHAL_LOG_COLORS is not set +# CONFIG_ARDUHAL_ESP_LOG is not set +# end of Debug Log Configuration + +CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y +# CONFIG_ARDUHAL_PARTITION_SCHEME_MINIMAL is not set +# CONFIG_ARDUHAL_PARTITION_SCHEME_NO_OTA is not set +# CONFIG_ARDUHAL_PARTITION_SCHEME_HUGE_APP is not set +# CONFIG_ARDUHAL_PARTITION_SCHEME_MIN_SPIFFS is not set +CONFIG_ARDUHAL_PARTITION_SCHEME="default" +# CONFIG_AUTOCONNECT_WIFI is not set +# CONFIG_ARDUINO_SELECTIVE_COMPILATION is not set +# end of Arduino Configuration + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +# CONFIG_COMPILER_DISABLE_GCC8_WARNINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_JTAG is not set +CONFIG_APPTRACE_DEST_NONE=y +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# ESP-ASIO +# +# CONFIG_ASIO_SSL_SUPPORT is not set +# end of ESP-ASIO + +# +# Bluetooth +# +CONFIG_BT_ENABLED=y +CONFIG_BT_SOC_SUPPORT_5_0=y + +# +# Bluetooth controller +# +CONFIG_BT_CTRL_MODE_EFF=1 +CONFIG_BT_CTRL_BLE_MAX_ACT=6 +CONFIG_BT_CTRL_BLE_MAX_ACT_EFF=6 +CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB=0 +CONFIG_BT_CTRL_PINNED_TO_CORE_0=y +# CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set +CONFIG_BT_CTRL_PINNED_TO_CORE=0 +CONFIG_BT_CTRL_HCI_MODE_VHCI=y +# CONFIG_BT_CTRL_HCI_MODE_UART_H4 is not set +CONFIG_BT_CTRL_HCI_TL=1 +CONFIG_BT_CTRL_ADV_DUP_FILT_MAX=30 +CONFIG_BT_BLE_CCA_MODE_NONE=y +# CONFIG_BT_BLE_CCA_MODE_HW is not set +# CONFIG_BT_BLE_CCA_MODE_SW is not set +CONFIG_BT_BLE_CCA_MODE=0 +CONFIG_BT_CTRL_HW_CCA_VAL=20 +CONFIG_BT_CTRL_HW_CCA_EFF=0 +CONFIG_BT_CTRL_CE_LENGTH_TYPE_ORIG=y +# CONFIG_BT_CTRL_CE_LENGTH_TYPE_CE is not set +# CONFIG_BT_CTRL_CE_LENGTH_TYPE_SD is not set +CONFIG_BT_CTRL_CE_LENGTH_TYPE_EFF=0 +CONFIG_BT_CTRL_TX_ANTENNA_INDEX_0=y +# CONFIG_BT_CTRL_TX_ANTENNA_INDEX_1 is not set +CONFIG_BT_CTRL_TX_ANTENNA_INDEX_EFF=0 +CONFIG_BT_CTRL_RX_ANTENNA_INDEX_0=y +# CONFIG_BT_CTRL_RX_ANTENNA_INDEX_1 is not set +CONFIG_BT_CTRL_RX_ANTENNA_INDEX_EFF=0 +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N24 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N21 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N18 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N15 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N12 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N9 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N6 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N3 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N0 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P3 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P6 is not set +CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P9=y +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P12 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P15 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P18 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P21 is not set +CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=11 +CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y +CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 +CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 +CONFIG_BT_CTRL_BLE_SCAN_DUPL=y +CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE=y +# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA is not set +# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE is not set +CONFIG_BT_CTRL_SCAN_DUPL_TYPE=0 +CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE=100 +CONFIG_BT_CTRL_DUPL_SCAN_CACHE_REFRESH_PERIOD=0 +# CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN is not set +# CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EN is not set +CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS=y +CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF=0 + +# +# MODEM SLEEP Options +# +# CONFIG_BT_CTRL_MODEM_SLEEP is not set +# end of MODEM SLEEP Options + +CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 +CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 +CONFIG_BT_CTRL_HCI_TL_EFF=1 +# CONFIG_BT_CTRL_AGC_RECORRECT_EN is not set +# CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX is not set +# CONFIG_BT_BLE_ADV_DATA_LENGTH_ZERO_AUX is not set +# end of Bluetooth controller + +CONFIG_BT_BLUEDROID_ENABLED=y +# CONFIG_BT_NIMBLE_ENABLED is not set +# CONFIG_BT_CONTROLLER_ONLY is not set + +# +# Bluedroid Options +# +CONFIG_BT_BTC_TASK_STACK_SIZE=3072 +CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y +# CONFIG_BT_BLUEDROID_PINNED_TO_CORE_1 is not set +CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0 +CONFIG_BT_BTU_TASK_STACK_SIZE=4352 +# CONFIG_BT_BLUEDROID_MEM_DEBUG is not set +CONFIG_BT_BLE_ENABLED=y +CONFIG_BT_GATTS_ENABLE=y +# CONFIG_BT_GATTS_PPCP_CHAR_GAP is not set +# CONFIG_BT_BLE_BLUFI_ENABLE is not set +CONFIG_BT_GATT_MAX_SR_PROFILES=8 +CONFIG_BT_GATT_MAX_SR_ATTRIBUTES=100 +# CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set +CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_AUTO=y +CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE=0 +# CONFIG_BT_GATTS_ROBUST_CACHING_ENABLED is not set +# CONFIG_BT_GATTS_DEVICE_NAME_WRITABLE is not set +# CONFIG_BT_GATTS_APPEARANCE_WRITABLE is not set +CONFIG_BT_GATTC_ENABLE=y +CONFIG_BT_GATTC_MAX_CACHE_CHAR=40 +CONFIG_BT_GATTC_NOTIF_REG_MAX=5 +# CONFIG_BT_GATTC_CACHE_NVS_FLASH is not set +CONFIG_BT_GATTC_CONNECT_RETRY_COUNT=3 +CONFIG_BT_BLE_SMP_ENABLE=y +# CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set +# CONFIG_BT_STACK_NO_LOG is not set + +# +# BT DEBUG LOG LEVEL +# +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_HCI_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_HCI_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BTM_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BTM_TRACE_LEVEL=2 +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_L2CAP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL=2 +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_SDP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_SDP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_GAP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_GAP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BNEP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BNEP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_PAN_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_PAN_TRACE_LEVEL=2 +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_A2D_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_A2D_TRACE_LEVEL=2 +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_AVDT_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_AVDT_TRACE_LEVEL=2 +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_AVCT_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_AVCT_TRACE_LEVEL=2 +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_AVRC_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_AVRC_TRACE_LEVEL=2 +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_MCA_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_MCA_TRACE_LEVEL=2 +# CONFIG_BT_LOG_HID_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_HID_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_HID_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_HID_TRACE_LEVEL=2 +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_APPL_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_APPL_TRACE_LEVEL=2 +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_GATT_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_GATT_TRACE_LEVEL=2 +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_SMP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_SMP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BTIF_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BTIF_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BTC_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BTC_TRACE_LEVEL=2 +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_OSI_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_OSI_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BLUFI_TRACE_LEVEL=2 +# end of BT DEBUG LOG LEVEL + +CONFIG_BT_ACL_CONNECTIONS=4 +CONFIG_BT_MULTI_CONNECTION_ENBALE=y +# CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST is not set +# CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY is not set +# CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set +CONFIG_BT_SMP_ENABLE=y +CONFIG_BT_SMP_MAX_BONDS=15 +# CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set +CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 +CONFIG_BT_MAX_DEVICE_NAME_LEN=32 +CONFIG_BT_BLE_RPA_TIMEOUT=900 +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y +# CONFIG_BT_BLE_42_FEATURES_SUPPORTED is not set +# CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL is not set +# end of Bluedroid Options +# end of Bluetooth + +# CONFIG_BLE_MESH is not set + +# +# CoAP Configuration +# +CONFIG_COAP_MBEDTLS_PSK=y +# CONFIG_COAP_MBEDTLS_PKI is not set +# CONFIG_COAP_MBEDTLS_DEBUG is not set +CONFIG_COAP_LOG_DEFAULT_LEVEL=0 +# end of CoAP Configuration + +# +# Driver configurations +# + +# +# ADC configuration +# +# CONFIG_ADC_FORCE_XPD_FSM is not set +CONFIG_ADC_DISABLE_DAC=y +# CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 is not set +# end of ADC configuration + +# +# MCPWM configuration +# +# CONFIG_MCPWM_ISR_IN_IRAM is not set +# end of MCPWM configuration + +# +# SPI configuration +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of SPI configuration + +# +# TWAI configuration +# +# CONFIG_TWAI_ISR_IN_IRAM is not set +# CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM is not set +# end of TWAI configuration + +# +# UART configuration +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of UART configuration + +# +# GDMA Configuration +# +# CONFIG_GDMA_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# end of GDMA Configuration +# end of Driver configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# CONFIG_ESP_TLS_INSECURE is not set +# end of ESP-TLS + +# +# ESP32S3-Specific +# +CONFIG_ESP32S3_REV_MIN_0=y +# CONFIG_ESP32S3_REV_MIN_1 is not set +# CONFIG_ESP32S3_REV_MIN_2 is not set +CONFIG_ESP32S3_REV_MIN_FULL=0 +CONFIG_ESP_REV_MIN_FULL=0 +CONFIG_ESP32S3_REV_MAX_FULL_STR_OPT=y +CONFIG_ESP32S3_REV_MAX_FULL=99 +CONFIG_ESP_REV_MAX_FULL=99 +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_160=y +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240 is not set +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=160 + +# +# Cache config +# +CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB=y +# CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE=0x4000 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_8WAYS=y +CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE=32 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_WRAP is not set +# CONFIG_ESP32S3_DATA_CACHE_16KB is not set +CONFIG_ESP32S3_DATA_CACHE_32KB=y +# CONFIG_ESP32S3_DATA_CACHE_64KB is not set +CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000 +# CONFIG_ESP32S3_DATA_CACHE_4WAYS is not set +CONFIG_ESP32S3_DATA_CACHE_8WAYS=y +CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_DATA_CACHE_LINE_16B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_32B=y +# CONFIG_ESP32S3_DATA_CACHE_LINE_64B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32 +# CONFIG_ESP32S3_DATA_CACHE_WRAP is not set +# end of Cache config + +# CONFIG_ESP32S3_SPIRAM_SUPPORT is not set +# CONFIG_ESP32S3_TRAX is not set +CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_ESP32S3_ULP_COPROC_ENABLED is not set +CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM=0 +CONFIG_ESP32S3_DEBUG_OCDAWARE=y +CONFIG_ESP32S3_BROWNOUT_DET=y +CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_ESP32S3_BROWNOUT_DET_LVL=7 +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32S3_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000 +# CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM is not set +# CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE is not set +# end of ESP32S3-Specific + +# +# ADC-Calibration +# +# end of ADC-Calibration + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +# end of Common ESP-related + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_SPI_ETHERNET_W5500 is not set +# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set +# CONFIG_ETH_USE_OPENETH is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +# end of GDB Stub + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +# CONFIG_HTTPD_WS_SUPPORT is not set +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_OTA_ALLOW_HTTP is not set +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +# end of ESP HTTPS server + +# +# Hardware Settings +# + +# +# MAC Config +# +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +# CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4 +# end of MAC Config + +# +# Sleep Config +# +# CONFIG_ESP_SLEEP_POWER_DOWN_FLASH is not set +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU=y +CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS=y +# end of Sleep Config + +# +# RTC Clock Config +# +CONFIG_RTC_CLOCK_BBPLL_POWER_ON_WITH_USB=y +# end of RTC Clock Config +# end of Hardware Settings + +# +# IPC (Inter-Processor Call) +# +CONFIG_ESP_IPC_TASK_STACK_SIZE=1536 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_IPC_ISR_ENABLE=y +# end of IPC (Inter-Processor Call) + +# +# LCD and Touch Panel +# + +# +# LCD Touch Drivers are maintained in the IDF Component Registry +# + +# +# LCD Peripheral Configuration +# +CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32 +# CONFIG_LCD_RGB_ISR_IRAM_SAFE is not set +# end of LCD Peripheral Configuration +# end of LCD and Touch Panel + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y +# end of ESP NETIF Adapter + +# +# PHY +# +CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP_PHY_MAX_TX_POWER=20 +# CONFIG_ESP_PHY_REDUCE_TX_POWER is not set +CONFIG_ESP_PHY_ENABLE_USB=y +CONFIG_ESP_PHY_RF_CAL_PARTIAL=y +# CONFIG_ESP_PHY_RF_CAL_NONE is not set +# CONFIG_ESP_PHY_RF_CAL_FULL is not set +CONFIG_ESP_PHY_CALIBRATION_MODE=0 +# end of PHY + +# +# Power Management +# +# CONFIG_PM_ENABLE is not set +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y +# end of Power Management + +# +# ESP Ringbuf +# +# CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH is not set +# CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH is not set +# end of ESP Ringbuf + +# +# ESP System Settings +# +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y + +# +# Memory protection +# +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_USB_CDC is not set +# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set +CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_MULTIPLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y +CONFIG_ESP_SYSTEM_BBPLL_RECALIB=y +# end of ESP System Settings + +# +# High resolution timer (esp_timer) +# +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of High resolution timer (esp_timer) + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_ENABLED=y +CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y +# CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER is not set +CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0 +CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF=5 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +# CONFIG_ESP_WIFI_FTM_ENABLE is not set +# CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE is not set +# CONFIG_ESP_WIFI_GCMP_SUPPORT is not set +# CONFIG_ESP_WIFI_GMAC_SUPPORT is not set +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y +# CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set +CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=7 +# end of Wi-Fi + +# +# Core dump +# +# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +# CONFIG_FATFS_USE_FASTSEEK is not set +# end of FAT Filesystem support + +# +# Modbus configuration +# +CONFIG_FMB_COMM_MODE_TCP_EN=y +CONFIG_FMB_TCP_PORT_DEFAULT=502 +CONFIG_FMB_TCP_PORT_MAX_CONN=5 +CONFIG_FMB_TCP_CONNECTION_TOUT_SEC=20 +CONFIG_FMB_COMM_MODE_RTU_EN=y +CONFIG_FMB_COMM_MODE_ASCII_EN=y +CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_FMB_QUEUE_LENGTH=20 +CONFIG_FMB_PORT_TASK_STACK_SIZE=4096 +CONFIG_FMB_SERIAL_BUF_SIZE=256 +CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8 +CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000 +CONFIG_FMB_PORT_TASK_PRIO=10 +# CONFIG_FMB_PORT_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_FMB_PORT_TASK_AFFINITY_CPU0=y +# CONFIG_FMB_PORT_TASK_AFFINITY_CPU1 is not set +CONFIG_FMB_PORT_TASK_AFFINITY=0x0 +CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT=y +CONFIG_FMB_CONTROLLER_SLAVE_ID=0x00112233 +CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_FMB_CONTROLLER_STACK_SIZE=4096 +CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20 +# CONFIG_FMB_TIMER_PORT_ENABLED is not set +# CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD is not set +# end of Modbus configuration + +# +# FreeRTOS +# +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y +CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y +# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set +CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +CONFIG_FREERTOS_HZ=1000 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set +# CONFIG_FREERTOS_ASSERT_DISABLE is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +# CONFIG_FREERTOS_LEGACY_HOOKS is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +# CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH is not set +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# end of Heap memory debugging + +# +# jsmn +# +# CONFIG_JSMN_PARENT_LINKS is not set +# CONFIG_JSMN_STRICT is not set +# end of jsmn + +# +# libsodium +# +# end of libsodium + +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_LEVEL=3 +CONFIG_LOG_COLORS=y +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Log output + +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +# CONFIG_LWIP_NETIF_API is not set +CONFIG_LWIP_TCPIP_TASK_PRIO=18 +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +# CONFIG_LWIP_CHECK_THREAD_SAFETY is not set +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +CONFIG_LWIP_SO_RCVBUF=y +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP_DEFAULT_TTL=64 +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_ESP_MLDV6_REPORT=y +CONFIG_LWIP_MLDV6_TMR_INTERVAL=40 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_DHCP_COARSE_TIMER_SECS=1 + +# +# DHCP server +# +CONFIG_LWIP_DHCPS=y +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5760 +CONFIG_LWIP_TCP_WND_DEFAULT=5760 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +CONFIG_LWIP_TCP_OOSEQ_TIMEOUT=6 +CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=4 +# CONFIG_LWIP_TCP_SACK_OUT is not set +# CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# CONFIG_LWIP_SLIP_SUPPORT is not set + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_SNTP_MAX_SERVERS=1 +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +# end of SNTP + +# +# DNS +# +CONFIG_LWIP_DNS_MAX_SERVERS=3 +# CONFIG_LWIP_FALLBACK_DNS_SERVER_SUPPORT is not set +# end of DNS + +CONFIG_LWIP_ESP_LWIP_ASSERT=y + +# +# Hooks +# +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +# end of Hooks + +# CONFIG_LWIP_DEBUG is not set +# end of LWIP + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set + +# +# mbedTLS v2.28.x related +# +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +# end of mbedTLS v2.28.x related + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +# CONFIG_MBEDTLS_CMAC_C is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA512_C=y +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_X509_CHECK_KEY_USAGE=y +CONFIG_MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +CONFIG_MBEDTLS_RC4_DISABLED=y +# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set +# CONFIG_MBEDTLS_RC4_ENABLED is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +# CONFIG_MBEDTLS_SECURITY_RISKS is not set +# end of mbedTLS + +# +# mDNS +# +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_TASK_STACK_SIZE=4096 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +# CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set +CONFIG_MDNS_TASK_AFFINITY=0x0 +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +# CONFIG_MDNS_STRICT_MODE is not set +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# CONFIG_MDNS_NETWORKING_SOCKET is not set +CONFIG_MDNS_MULTIPLE_INSTANCE=y +# end of mDNS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set +# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set +# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# Newlib +# +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +# end of Newlib + +# +# NVS +# +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# end of NVS + +# +# OpenSSL +# +# CONFIG_OPENSSL_DEBUG is not set +CONFIG_OPENSSL_ERROR_STACK=y +# CONFIG_OPENSSL_ASSERT_DO_NOTHING is not set +CONFIG_OPENSSL_ASSERT_EXIT=y +# end of OpenSSL + +# +# OpenThread +# +# CONFIG_OPENTHREAD_ENABLED is not set +# end of OpenThread + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# Main Flash configuration +# + +# +# Optional and Experimental Features (READ DOCS FIRST) +# + +# +# Features here require specific hardware (READ DOCS FIRST!) +# +# CONFIG_SPI_FLASH_HPM_ENA is not set +CONFIG_SPI_FLASH_HPM_AUTO=y +# CONFIG_SPI_FLASH_HPM_DIS is not set +CONFIG_SPI_FLASH_HPM_ON=y +CONFIG_SPI_FLASH_HPM_DC_AUTO=y +# CONFIG_SPI_FLASH_HPM_DC_DISABLE is not set +# end of Optional and Experimental Features (READ DOCS FIRST) +# end of Main Flash configuration + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +# CONFIG_SPI_FLASH_ROM_IMPL is not set +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set +# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP=y +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TCP Transport +# + +# +# Websocket +# +CONFIG_WS_TRANSPORT=y +CONFIG_WS_BUFFER_SIZE=1024 +# end of Websocket +# end of TCP Transport + +# +# TinyUSB Stack +# +# CONFIG_TINYUSB is not set +# end of TinyUSB Stack + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# end of Unity unit testing library + +# +# USB-OTG +# +CONFIG_USB_OTG_SUPPORTED=y +CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE=256 +CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED=y +# CONFIG_USB_HOST_HW_BUFFER_BIAS_IN is not set +# CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT is not set + +# +# Root Hub configuration +# +CONFIG_USB_HOST_DEBOUNCE_DELAY_MS=250 +CONFIG_USB_HOST_RESET_HOLD_MS=30 +CONFIG_USB_HOST_RESET_RECOVERY_MS=30 +CONFIG_USB_HOST_SET_ADDR_RECOVERY_MS=10 +# end of Root Hub configuration +# end of USB-OTG + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_VFS_SUPPORT_TERMIOS=y + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +# CONFIG_WIFI_PROV_BLE_BONDING is not set +# CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION is not set +# CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV is not set +# end of Wi-Fi Provisioning Manager + +# +# Supplicant +# +CONFIG_WPA_MBEDTLS_CRYPTO=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# CONFIG_WPA_MBO_SUPPORT is not set +# CONFIG_WPA_DPP_SUPPORT is not set +# end of Supplicant +# end of Component config + +# +# Compatibility options +# +# CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set +# end of Compatibility options + +# Deprecated options for backward compatibility +CONFIG_TOOLPREFIX="xtensa-esp32s3-elf-" +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +CONFIG_CXX_EXCEPTIONS=y +CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_DISABLE_GCC8_WARNINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +CONFIG_BLUEDROID_ENABLED=y +# CONFIG_NIMBLE_ENABLED is not set +CONFIG_BTC_TASK_STACK_SIZE=3072 +CONFIG_BLUEDROID_PINNED_TO_CORE_0=y +# CONFIG_BLUEDROID_PINNED_TO_CORE_1 is not set +CONFIG_BLUEDROID_PINNED_TO_CORE=0 +CONFIG_BTU_TASK_STACK_SIZE=4352 +# CONFIG_BLUEDROID_MEM_DEBUG is not set +CONFIG_GATTS_ENABLE=y +# CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set +CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y +CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0 +CONFIG_GATTC_ENABLE=y +# CONFIG_GATTC_CACHE_NVS_FLASH is not set +CONFIG_BLE_SMP_ENABLE=y +# CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set +# CONFIG_HCI_TRACE_LEVEL_NONE is not set +# CONFIG_HCI_TRACE_LEVEL_ERROR is not set +CONFIG_HCI_TRACE_LEVEL_WARNING=y +# CONFIG_HCI_TRACE_LEVEL_API is not set +# CONFIG_HCI_TRACE_LEVEL_EVENT is not set +# CONFIG_HCI_TRACE_LEVEL_DEBUG is not set +# CONFIG_HCI_TRACE_LEVEL_VERBOSE is not set +CONFIG_HCI_INITIAL_TRACE_LEVEL=2 +# CONFIG_BTM_TRACE_LEVEL_NONE is not set +# CONFIG_BTM_TRACE_LEVEL_ERROR is not set +CONFIG_BTM_TRACE_LEVEL_WARNING=y +# CONFIG_BTM_TRACE_LEVEL_API is not set +# CONFIG_BTM_TRACE_LEVEL_EVENT is not set +# CONFIG_BTM_TRACE_LEVEL_DEBUG is not set +# CONFIG_BTM_TRACE_LEVEL_VERBOSE is not set +CONFIG_BTM_INITIAL_TRACE_LEVEL=2 +# CONFIG_L2CAP_TRACE_LEVEL_NONE is not set +# CONFIG_L2CAP_TRACE_LEVEL_ERROR is not set +CONFIG_L2CAP_TRACE_LEVEL_WARNING=y +# CONFIG_L2CAP_TRACE_LEVEL_API is not set +# CONFIG_L2CAP_TRACE_LEVEL_EVENT is not set +# CONFIG_L2CAP_TRACE_LEVEL_DEBUG is not set +# CONFIG_L2CAP_TRACE_LEVEL_VERBOSE is not set +CONFIG_L2CAP_INITIAL_TRACE_LEVEL=2 +# CONFIG_RFCOMM_TRACE_LEVEL_NONE is not set +# CONFIG_RFCOMM_TRACE_LEVEL_ERROR is not set +CONFIG_RFCOMM_TRACE_LEVEL_WARNING=y +# CONFIG_RFCOMM_TRACE_LEVEL_API is not set +# CONFIG_RFCOMM_TRACE_LEVEL_EVENT is not set +# CONFIG_RFCOMM_TRACE_LEVEL_DEBUG is not set +# CONFIG_RFCOMM_TRACE_LEVEL_VERBOSE is not set +CONFIG_RFCOMM_INITIAL_TRACE_LEVEL=2 +# CONFIG_SDP_TRACE_LEVEL_NONE is not set +# CONFIG_SDP_TRACE_LEVEL_ERROR is not set +CONFIG_SDP_TRACE_LEVEL_WARNING=y +# CONFIG_SDP_TRACE_LEVEL_API is not set +# CONFIG_SDP_TRACE_LEVEL_EVENT is not set +# CONFIG_SDP_TRACE_LEVEL_DEBUG is not set +# CONFIG_SDP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BTH_LOG_SDP_INITIAL_TRACE_LEVEL=2 +# CONFIG_GAP_TRACE_LEVEL_NONE is not set +# CONFIG_GAP_TRACE_LEVEL_ERROR is not set +CONFIG_GAP_TRACE_LEVEL_WARNING=y +# CONFIG_GAP_TRACE_LEVEL_API is not set +# CONFIG_GAP_TRACE_LEVEL_EVENT is not set +# CONFIG_GAP_TRACE_LEVEL_DEBUG is not set +# CONFIG_GAP_TRACE_LEVEL_VERBOSE is not set +CONFIG_GAP_INITIAL_TRACE_LEVEL=2 +CONFIG_BNEP_INITIAL_TRACE_LEVEL=2 +# CONFIG_PAN_TRACE_LEVEL_NONE is not set +# CONFIG_PAN_TRACE_LEVEL_ERROR is not set +CONFIG_PAN_TRACE_LEVEL_WARNING=y +# CONFIG_PAN_TRACE_LEVEL_API is not set +# CONFIG_PAN_TRACE_LEVEL_EVENT is not set +# CONFIG_PAN_TRACE_LEVEL_DEBUG is not set +# CONFIG_PAN_TRACE_LEVEL_VERBOSE is not set +CONFIG_PAN_INITIAL_TRACE_LEVEL=2 +# CONFIG_A2D_TRACE_LEVEL_NONE is not set +# CONFIG_A2D_TRACE_LEVEL_ERROR is not set +CONFIG_A2D_TRACE_LEVEL_WARNING=y +# CONFIG_A2D_TRACE_LEVEL_API is not set +# CONFIG_A2D_TRACE_LEVEL_EVENT is not set +# CONFIG_A2D_TRACE_LEVEL_DEBUG is not set +# CONFIG_A2D_TRACE_LEVEL_VERBOSE is not set +CONFIG_A2D_INITIAL_TRACE_LEVEL=2 +# CONFIG_AVDT_TRACE_LEVEL_NONE is not set +# CONFIG_AVDT_TRACE_LEVEL_ERROR is not set +CONFIG_AVDT_TRACE_LEVEL_WARNING=y +# CONFIG_AVDT_TRACE_LEVEL_API is not set +# CONFIG_AVDT_TRACE_LEVEL_EVENT is not set +# CONFIG_AVDT_TRACE_LEVEL_DEBUG is not set +# CONFIG_AVDT_TRACE_LEVEL_VERBOSE is not set +CONFIG_AVDT_INITIAL_TRACE_LEVEL=2 +# CONFIG_AVCT_TRACE_LEVEL_NONE is not set +# CONFIG_AVCT_TRACE_LEVEL_ERROR is not set +CONFIG_AVCT_TRACE_LEVEL_WARNING=y +# CONFIG_AVCT_TRACE_LEVEL_API is not set +# CONFIG_AVCT_TRACE_LEVEL_EVENT is not set +# CONFIG_AVCT_TRACE_LEVEL_DEBUG is not set +# CONFIG_AVCT_TRACE_LEVEL_VERBOSE is not set +CONFIG_AVCT_INITIAL_TRACE_LEVEL=2 +# CONFIG_AVRC_TRACE_LEVEL_NONE is not set +# CONFIG_AVRC_TRACE_LEVEL_ERROR is not set +CONFIG_AVRC_TRACE_LEVEL_WARNING=y +# CONFIG_AVRC_TRACE_LEVEL_API is not set +# CONFIG_AVRC_TRACE_LEVEL_EVENT is not set +# CONFIG_AVRC_TRACE_LEVEL_DEBUG is not set +# CONFIG_AVRC_TRACE_LEVEL_VERBOSE is not set +CONFIG_AVRC_INITIAL_TRACE_LEVEL=2 +# CONFIG_MCA_TRACE_LEVEL_NONE is not set +# CONFIG_MCA_TRACE_LEVEL_ERROR is not set +CONFIG_MCA_TRACE_LEVEL_WARNING=y +# CONFIG_MCA_TRACE_LEVEL_API is not set +# CONFIG_MCA_TRACE_LEVEL_EVENT is not set +# CONFIG_MCA_TRACE_LEVEL_DEBUG is not set +# CONFIG_MCA_TRACE_LEVEL_VERBOSE is not set +CONFIG_MCA_INITIAL_TRACE_LEVEL=2 +# CONFIG_HID_TRACE_LEVEL_NONE is not set +# CONFIG_HID_TRACE_LEVEL_ERROR is not set +CONFIG_HID_TRACE_LEVEL_WARNING=y +# CONFIG_HID_TRACE_LEVEL_API is not set +# CONFIG_HID_TRACE_LEVEL_EVENT is not set +# CONFIG_HID_TRACE_LEVEL_DEBUG is not set +# CONFIG_HID_TRACE_LEVEL_VERBOSE is not set +CONFIG_HID_INITIAL_TRACE_LEVEL=2 +# CONFIG_APPL_TRACE_LEVEL_NONE is not set +# CONFIG_APPL_TRACE_LEVEL_ERROR is not set +CONFIG_APPL_TRACE_LEVEL_WARNING=y +# CONFIG_APPL_TRACE_LEVEL_API is not set +# CONFIG_APPL_TRACE_LEVEL_EVENT is not set +# CONFIG_APPL_TRACE_LEVEL_DEBUG is not set +# CONFIG_APPL_TRACE_LEVEL_VERBOSE is not set +CONFIG_APPL_INITIAL_TRACE_LEVEL=2 +# CONFIG_GATT_TRACE_LEVEL_NONE is not set +# CONFIG_GATT_TRACE_LEVEL_ERROR is not set +CONFIG_GATT_TRACE_LEVEL_WARNING=y +# CONFIG_GATT_TRACE_LEVEL_API is not set +# CONFIG_GATT_TRACE_LEVEL_EVENT is not set +# CONFIG_GATT_TRACE_LEVEL_DEBUG is not set +# CONFIG_GATT_TRACE_LEVEL_VERBOSE is not set +CONFIG_GATT_INITIAL_TRACE_LEVEL=2 +# CONFIG_SMP_TRACE_LEVEL_NONE is not set +# CONFIG_SMP_TRACE_LEVEL_ERROR is not set +CONFIG_SMP_TRACE_LEVEL_WARNING=y +# CONFIG_SMP_TRACE_LEVEL_API is not set +# CONFIG_SMP_TRACE_LEVEL_EVENT is not set +# CONFIG_SMP_TRACE_LEVEL_DEBUG is not set +# CONFIG_SMP_TRACE_LEVEL_VERBOSE is not set +CONFIG_SMP_INITIAL_TRACE_LEVEL=2 +# CONFIG_BTIF_TRACE_LEVEL_NONE is not set +# CONFIG_BTIF_TRACE_LEVEL_ERROR is not set +CONFIG_BTIF_TRACE_LEVEL_WARNING=y +# CONFIG_BTIF_TRACE_LEVEL_API is not set +# CONFIG_BTIF_TRACE_LEVEL_EVENT is not set +# CONFIG_BTIF_TRACE_LEVEL_DEBUG is not set +# CONFIG_BTIF_TRACE_LEVEL_VERBOSE is not set +CONFIG_BTIF_INITIAL_TRACE_LEVEL=2 +# CONFIG_BTC_TRACE_LEVEL_NONE is not set +# CONFIG_BTC_TRACE_LEVEL_ERROR is not set +CONFIG_BTC_TRACE_LEVEL_WARNING=y +# CONFIG_BTC_TRACE_LEVEL_API is not set +# CONFIG_BTC_TRACE_LEVEL_EVENT is not set +# CONFIG_BTC_TRACE_LEVEL_DEBUG is not set +# CONFIG_BTC_TRACE_LEVEL_VERBOSE is not set +CONFIG_BTC_INITIAL_TRACE_LEVEL=2 +# CONFIG_OSI_TRACE_LEVEL_NONE is not set +# CONFIG_OSI_TRACE_LEVEL_ERROR is not set +CONFIG_OSI_TRACE_LEVEL_WARNING=y +# CONFIG_OSI_TRACE_LEVEL_API is not set +# CONFIG_OSI_TRACE_LEVEL_EVENT is not set +# CONFIG_OSI_TRACE_LEVEL_DEBUG is not set +# CONFIG_OSI_TRACE_LEVEL_VERBOSE is not set +CONFIG_OSI_INITIAL_TRACE_LEVEL=2 +# CONFIG_BLUFI_TRACE_LEVEL_NONE is not set +# CONFIG_BLUFI_TRACE_LEVEL_ERROR is not set +CONFIG_BLUFI_TRACE_LEVEL_WARNING=y +# CONFIG_BLUFI_TRACE_LEVEL_API is not set +# CONFIG_BLUFI_TRACE_LEVEL_EVENT is not set +# CONFIG_BLUFI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BLUFI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BLUFI_INITIAL_TRACE_LEVEL=2 +# CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK is not set +CONFIG_SMP_ENABLE=y +# CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY is not set +CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30 +CONFIG_ADC2_DISABLE_DAC=y +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +# CONFIG_ESP_SYSTEM_PD_FLASH is not set +CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_IPC_TASK_STACK_SIZE=1536 +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# CONFIG_ESP32_REDUCE_PHY_TX_POWER is not set +CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y +# CONFIG_ESP32S2_PANIC_PRINT_HALT is not set +CONFIG_ESP32S2_PANIC_PRINT_REBOOT=y +# CONFIG_ESP32S2_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP32S2_PANIC_GDBSTUB is not set +CONFIG_ESP32S2_ALLOW_RTC_FAST_MEM_AS_HEAP=y +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_SW_COEXIST_ENABLE=y +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_MB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=4096 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT=y +CONFIG_MB_CONTROLLER_SLAVE_ID=0x00112233 +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +# CONFIG_MB_TIMER_PORT_ENABLED is not set +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_L2_TO_L3_COPY is not set +# CONFIG_USE_ONLY_LWIP_SELECT is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=12 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5760 +CONFIG_TCP_WND_DEFAULT=5760 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +# CONFIG_USB_ENABLED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# End of deprecated options diff --git a/sdkconfig.defaults b/sdkconfig.defaults new file mode 100644 index 0000000..b7682f1 --- /dev/null +++ b/sdkconfig.defaults @@ -0,0 +1,6 @@ +CONFIG_FREERTOS_HZ=1000 +CONFIG_AUTOSTART_ARDUINO=y +CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y +CONFIG_BT_ENABLED=y +CONFIG_BT_CONTROLLER_ENABLED=y +CONFIG_COMPILER_CXX_EXCEPTIONS=y diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..b7fa655 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,5 @@ +file(GLOB_RECURSE SOURCES "sp140/*.cpp") + +idf_component_register(SRCS ${SOURCES} + INCLUDE_DIRS "../inc" "../inc/sp140" "../inc/sp140/lvgl" + REQUIRES arduino) diff --git a/src/sp140/CMakeLists.txt b/src/sp140/CMakeLists.txt new file mode 100644 index 0000000..d827803 --- /dev/null +++ b/src/sp140/CMakeLists.txt @@ -0,0 +1,6 @@ +# This file was automatically generated for projects +# without default 'CMakeLists.txt' file. + +FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/sp140/*.*) + +idf_component_register(SRCS ${app_sources}) diff --git a/src/sp140/ble/ble_core.cpp b/src/sp140/ble/ble_core.cpp index e97b54e..4c108e8 100644 --- a/src/sp140/ble/ble_core.cpp +++ b/src/sp140/ble/ble_core.cpp @@ -8,6 +8,7 @@ #include "sp140/ble/config_service.h" #include "sp140/ble/controller_service.h" #include "sp140/ble/esc_service.h" +#include "sp140/ble/ota_service.h" namespace { @@ -53,6 +54,7 @@ void setupBLE() { initBmsBleService(pServer); initEscBleService(pServer); initControllerBleService(pServer); + initOtaBleService(pServer); NimBLEAdvertising* advertising = pServer->getAdvertising(); advertising->setName("OpenPPG Controller"); @@ -62,6 +64,7 @@ void setupBLE() { advertising->addServiceUUID(NimBLEUUID(BMS_TELEMETRY_SERVICE_UUID)); advertising->addServiceUUID(NimBLEUUID(ESC_TELEMETRY_SERVICE_UUID)); advertising->addServiceUUID(NimBLEUUID(CONTROLLER_SERVICE_UUID)); + advertising->addServiceUUID(NimBLEUUID(OTA_SERVICE_UUID)); advertising->enableScanResponse(true); advertising->start(); diff --git a/src/sp140/ble/ota_service.cpp b/src/sp140/ble/ota_service.cpp new file mode 100644 index 0000000..fa4c3cd --- /dev/null +++ b/src/sp140/ble/ota_service.cpp @@ -0,0 +1,150 @@ +#include "sp140/ble/ota_service.h" + +#include +#include "esp_ota_ops.h" +#include "esp_partition.h" +#include "sp140/ble/ble_ids.h" + +namespace { + +// OTA Commands +const uint8_t CMD_START = 0x01; +const uint8_t CMD_END = 0x02; +const uint8_t CMD_ABORT = 0x03; + +// OTA Responses +const uint8_t RESP_SUCCESS = 0x00; +const uint8_t RESP_ERROR_BEGIN = 0xE1; +const uint8_t RESP_ERROR_WRITE = 0xE2; +const uint8_t RESP_ERROR_END = 0xE3; +const uint8_t RESP_ERROR_UNKNOWN = 0xFF; + +volatile bool otaInProgress = false; +esp_ota_handle_t updateHandle = 0; +const esp_partition_t* updatePartition = nullptr; +size_t receivedBytes = 0; + +void sendResponse(NimBLECharacteristic* pChar, uint8_t responseCode) { + pChar->setValue(&responseCode, 1); + pChar->notify(); + USBSerial.printf("OTA: Sent response 0x%02X\n", responseCode); +} + +class OtaControlCallback : public NimBLECharacteristicCallbacks { + void onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo) override { + (void)connInfo; + std::string value = pChar->getValue(); + if (value.length() == 0) return; + + uint8_t command = value[0]; + + if (command == CMD_START) { + USBSerial.println("OTA: Start command received"); + + updatePartition = esp_ota_get_next_update_partition(nullptr); + if (!updatePartition) { + USBSerial.println("OTA Error: No update partition found"); + sendResponse(pChar, RESP_ERROR_BEGIN); + return; + } + + USBSerial.printf("OTA: Writing to partition subtype %d at offset 0x%x\n", + updatePartition->subtype, updatePartition->address); + + // OTA_SIZE_UNKNOWN allows flashing any size, but requires enough space + esp_err_t err = esp_ota_begin(updatePartition, OTA_SIZE_UNKNOWN, &updateHandle); + if (err != ESP_OK) { + USBSerial.printf("OTA Error: esp_ota_begin failed (0x%x)\n", err); + sendResponse(pChar, RESP_ERROR_BEGIN); + return; + } + + otaInProgress = true; + receivedBytes = 0; + sendResponse(pChar, RESP_SUCCESS); + + } else if (command == CMD_END) { + USBSerial.println("OTA: End command received"); + + if (!otaInProgress) { + sendResponse(pChar, RESP_ERROR_UNKNOWN); + return; + } + + esp_err_t err = esp_ota_end(updateHandle); + if (err != ESP_OK) { + USBSerial.printf("OTA Error: esp_ota_end failed (0x%x)\n", err); + sendResponse(pChar, RESP_ERROR_END); + otaInProgress = false; + return; + } + + err = esp_ota_set_boot_partition(updatePartition); + if (err != ESP_OK) { + USBSerial.printf("OTA Error: set_boot_partition failed (0x%x)\n", err); + sendResponse(pChar, RESP_ERROR_END); + otaInProgress = false; + return; + } + + USBSerial.println("OTA: Success! Restarting..."); + sendResponse(pChar, RESP_SUCCESS); + delay(1000); + ESP.restart(); + + } else if (command == CMD_ABORT) { + USBSerial.println("OTA: Abort command received"); + if (otaInProgress) { + esp_ota_end(updateHandle); + otaInProgress = false; + } + sendResponse(pChar, RESP_SUCCESS); + } + } +}; + +class OtaDataCallback : public NimBLECharacteristicCallbacks { + void onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo) override { + (void)connInfo; + if (!otaInProgress) return; + + std::string value = pChar->getValue(); + if (value.length() > 0) { + esp_err_t err = esp_ota_write(updateHandle, value.data(), value.length()); + if (err != ESP_OK) { + USBSerial.printf("OTA Error: Write failed (0x%x)\n", err); + // Optionally notify control char of error, but might be slow + } else { + receivedBytes += value.length(); + // Verbose logging only every 10KB to avoid spam + if (receivedBytes % 10240 < value.length()) { + USBSerial.printf("OTA: Received %d bytes\n", receivedBytes); + } + } + } + } +}; + +} // namespace + +void initOtaBleService(NimBLEServer* pServer) { + NimBLEService* pService = pServer->createService(OTA_SERVICE_UUID); + + NimBLECharacteristic* pControlChar = pService->createCharacteristic( + OTA_CONTROL_UUID, + NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY + ); + pControlChar->setCallbacks(new OtaControlCallback()); + + NimBLECharacteristic* pDataChar = pService->createCharacteristic( + OTA_DATA_UUID, + NIMBLE_PROPERTY::WRITE_NR // Write No Response for speed + ); + pDataChar->setCallbacks(new OtaDataCallback()); + + pService->start(); +} + +bool isOtaInProgress() { + return otaInProgress; +} diff --git a/src/sp140/buzzer.cpp b/src/sp140/buzzer.cpp index de65343..4e4bde6 100644 --- a/src/sp140/buzzer.cpp +++ b/src/sp140/buzzer.cpp @@ -4,8 +4,8 @@ #include "sp140/shared-config.h" #include "sp140/esp32s3-config.h" -#include -#include +#include +#include #define DEBUG_SERIAL USBSerial diff --git a/src/sp140/extra-data.ino b/src/sp140/device_settings.cpp similarity index 98% rename from src/sp140/extra-data.ino rename to src/sp140/device_settings.cpp index 8eedce6..33355e4 100644 --- a/src/sp140/extra-data.ino +++ b/src/sp140/device_settings.cpp @@ -1,8 +1,13 @@ // Copyright 2020 // OpenPPG +#include "Arduino.h" +#include +#include "sp140/device_settings.h" +#include "../../inc/sp140/esp32s3-config.h" #include // Add ESP32 Preferences library #include "../../inc/sp140/throttle.h" +#include "../../inc/sp140/globals.h" /** * WebSerial Protocol Documentation diff --git a/src/sp140/esc.cpp b/src/sp140/esc.cpp index 1a435c8..00e9046 100644 --- a/src/sp140/esc.cpp +++ b/src/sp140/esc.cpp @@ -129,14 +129,14 @@ void readESCTelemetry() { if (lastSuccessfulCommTimeMs == 0 || (currentTimeMs - lastSuccessfulCommTimeMs) > TELEMETRY_TIMEOUT_MS) { if (escTelemetryData.escState != TelemetryState::NOT_CONNECTED) { // Log state change only if it actually changed - USBSerial.printf("ESC State: %d -> NOT_CONNECTED (Timeout)\n", escTelemetryData.escState); + USBSerial.printf("ESC State: %d -> NOT_CONNECTED (Timeout)\n", static_cast(escTelemetryData.escState)); escTelemetryData.escState = TelemetryState::NOT_CONNECTED; // Optional: Consider resetting telemetry values here if needed when disconnected } } else { if (escTelemetryData.escState != TelemetryState::CONNECTED) { // Log state change only if it actually changed - USBSerial.printf("ESC State: %d -> CONNECTED\n", escTelemetryData.escState); + USBSerial.printf("ESC State: %d -> CONNECTED\n", static_cast(escTelemetryData.escState)); escTelemetryData.escState = TelemetryState::CONNECTED; } } diff --git a/src/sp140/lvgl/lvgl_updates.cpp b/src/sp140/lvgl/lvgl_updates.cpp index 96cf7d2..6680b64 100644 --- a/src/sp140/lvgl/lvgl_updates.cpp +++ b/src/sp140/lvgl/lvgl_updates.cpp @@ -454,7 +454,7 @@ void updateLvglMainScreen( int ones = whole_part % 10; // Populate character positions using static buffers - static char power_digit_buffers[4][2]; + static char power_digit_buffers[4][12]; // Tens digit (only show if >= 10kW) if (tens > 0) { @@ -533,7 +533,7 @@ void updateLvglMainScreen( int ones = whole_part % 10; // Populate each character position using static character buffers - static char digit_buffers[7][2]; // Static buffers for single digits + static char digit_buffers[7][12]; // Static buffers for single digits // Clear all positions first for (int i = 0; i < 7; i++) { @@ -598,7 +598,7 @@ void updateLvglMainScreen( int tens = (feet / 10) % 10; int ones = feet % 10; - static char digit_buffers_ft[7][2]; // Static buffers for feet + static char digit_buffers_ft[7][12]; // Static buffers for feet // Adjust width of position 4 for feet (should be normal width, not narrow) lv_obj_set_size(altitude_char_labels[4], 17, 24); // char_width=19, char_height=24 diff --git a/src/sp140/sp140.ino b/src/sp140/main.cpp similarity index 98% rename from src/sp140/sp140.ino rename to src/sp140/main.cpp index 1a2b3e2..ab1813f 100644 --- a/src/sp140/sp140.ino +++ b/src/sp140/main.cpp @@ -1,6 +1,7 @@ // Copyright 2020 // OpenPPG #include "Arduino.h" +#include "sp140/device_settings.h" #include "../../inc/sp140/esp32s3-config.h" @@ -45,6 +46,22 @@ #include #include +// Forward declarations +void disarmSystem(); +bool armSystem(); +void afterCruiseEnd(); +void afterCruiseStart(); +void pushTelemetrySnapshot(); +void initButtons(); +void setup140(); +void setupTasks(); +void audioTask(void* parameter); +void updateESCBLETask(void* parameter); +void webSerialTask(void* parameter); +void toggleArm(); +void toggleCruise(); +void syncESCTelemetry(); + // Global variable for shared SPI SPIClass* hardwareSPI = nullptr; @@ -1087,7 +1104,7 @@ void handleThrottle() { } } - int finalPwm; + int finalPwm = ESC_DISARMED_PWM; // Handle throttle based on current device state switch (currentState) { From 2bf9acf58c9e5c13031555b0beb0d6d38644f702 Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Mon, 26 Jan 2026 15:06:16 -0600 Subject: [PATCH 02/16] Update BLE OTA service to Espressif standard Refactored OTA BLE service to use Espressif standard UUIDs and characteristics, separating command, data, and status. Added checks to suppress BLE notifications during OTA updates across all telemetry and config services. Improves compatibility and prevents notification conflicts during firmware updates. --- inc/sp140/ble/ble_ids.h | 9 +++-- src/sp140/ble/bms_service.cpp | 7 ++-- src/sp140/ble/config_service.cpp | 5 ++- src/sp140/ble/controller_service.cpp | 3 +- src/sp140/ble/esc_service.cpp | 5 ++- src/sp140/ble/ota_service.cpp | 57 +++++++++++++++++----------- src/sp140/main.cpp | 3 +- 7 files changed, 55 insertions(+), 34 deletions(-) diff --git a/inc/sp140/ble/ble_ids.h b/inc/sp140/ble/ble_ids.h index bdb3357..dd5f944 100644 --- a/inc/sp140/ble/ble_ids.h +++ b/inc/sp140/ble/ble_ids.h @@ -68,10 +68,11 @@ #define CONTROLLER_TELEMETRY_UUID "01C63B61-0891-4655-BBCA-8E745C48A176" // ============================================================================ -// OTA Service (Firmware Update) +// OTA Service (Firmware Update) - Espressif Standard // ============================================================================ -#define OTA_SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" -#define OTA_CONTROL_UUID "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" -#define OTA_DATA_UUID "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" +#define OTA_SERVICE_UUID "00008018-0000-1000-8000-00805F9B34FB" +#define OTA_DATA_UUID "00008019-0000-1000-8000-00805F9B34FB" // RX: Firmware data +#define OTA_STATUS_UUID "0000801A-0000-1000-8000-00805F9B34FB" // TX: Notifications/Status +#define OTA_COMMAND_UUID "0000801B-0000-1000-8000-00805F9B34FB" // RX: Commands (Start/End) #endif // INC_SP140_BLE_BLE_IDS_H_ diff --git a/src/sp140/ble/bms_service.cpp b/src/sp140/ble/bms_service.cpp index 4478473..217d809 100644 --- a/src/sp140/ble/bms_service.cpp +++ b/src/sp140/ble/bms_service.cpp @@ -5,6 +5,7 @@ #include "sp140/ble.h" #include "sp140/ble/ble_ids.h" #include "sp140/ble/ble_utils.h" +#include "sp140/ble/ota_service.h" namespace { @@ -152,7 +153,7 @@ void updateBMSPackedTelemetry(const STR_BMS_TELEMETRY_140& telemetry, uint8_t bm reinterpret_cast(&packet), sizeof(BLE_BMS_Telemetry_V1)); - if (deviceConnected) { + if (deviceConnected && !isOtaInProgress()) { pBMSPackedTelemetry->notify(); } } @@ -223,8 +224,8 @@ void updateBMSTelemetry(const STR_BMS_TELEMETRY_140& telemetry) { setAndNotifyOnChange(pBMSChargeMos, static_cast(telemetry.is_charge_mos ? 1 : 0), lastChargeMos); setAndNotifyOnChange(pBMSDischargeMos, static_cast(telemetry.is_discharge_mos ? 1 : 0), lastDischargeMos); - if (!deviceConnected) { - return; // No notifications needed without a subscriber. + if (!deviceConnected || isOtaInProgress()) { + return; // No notifications needed without a subscriber or if OTA is running. } if (pBMSSOC) pBMSSOC->notify(); diff --git a/src/sp140/ble/config_service.cpp b/src/sp140/ble/config_service.cpp index 803766b..6c7d265 100644 --- a/src/sp140/ble/config_service.cpp +++ b/src/sp140/ble/config_service.cpp @@ -17,6 +17,7 @@ #include "sp140/globals.h" #include "sp140/throttle.h" #include "version.h" +#include "sp140/ble/ota_service.h" extern void writeDeviceData(); extern QueueHandle_t throttleUpdateQueue; @@ -363,7 +364,9 @@ void updateThrottleBLE(int value) { try { pThrottleCharacteristic->setValue(reinterpret_cast(&value), sizeof(value)); - pThrottleCharacteristic->notify(); + if (!isOtaInProgress()) { + pThrottleCharacteristic->notify(); + } vTaskDelay(pdMS_TO_TICKS(5)); } catch (...) { USBSerial.println("Error sending BLE notification"); diff --git a/src/sp140/ble/controller_service.cpp b/src/sp140/ble/controller_service.cpp index efc09ed..7fb8bec 100644 --- a/src/sp140/ble/controller_service.cpp +++ b/src/sp140/ble/controller_service.cpp @@ -5,6 +5,7 @@ #include "sp140/ble.h" #include "sp140/ble/ble_ids.h" #include "sp140/throttle.h" +#include "sp140/ble/ota_service.h" namespace { @@ -62,7 +63,7 @@ void updateControllerPackedTelemetry(float altitude, float baro_temp, reinterpret_cast(&packet), sizeof(BLE_Controller_Telemetry_V1)); - if (deviceConnected) { + if (deviceConnected && !isOtaInProgress()) { pControllerPackedTelemetry->notify(); } } diff --git a/src/sp140/ble/esc_service.cpp b/src/sp140/ble/esc_service.cpp index 74a666e..cbef110 100644 --- a/src/sp140/ble/esc_service.cpp +++ b/src/sp140/ble/esc_service.cpp @@ -4,6 +4,7 @@ #include "sp140/ble.h" #include "sp140/ble/ble_ids.h" +#include "sp140/ble/ota_service.h" namespace { @@ -103,7 +104,7 @@ void updateESCPackedTelemetry(const STR_ESC_TELEMETRY_140& telemetry) { reinterpret_cast(&packet), sizeof(BLE_ESC_Telemetry_V1)); - if (deviceConnected) { + if (deviceConnected && !isOtaInProgress()) { pESCPackedTelemetry->notify(); } } @@ -130,7 +131,7 @@ void updateESCTelemetryBLE(const STR_ESC_TELEMETRY_140& telemetry) { if (pESCRPM) pESCRPM->setValue(rpm); if (pESCTemps) pESCTemps->setValue(reinterpret_cast(&temps), sizeof(temps)); - if (!deviceConnected) { + if (!deviceConnected || isOtaInProgress()) { return; // No notifications needed without a subscriber. } diff --git a/src/sp140/ble/ota_service.cpp b/src/sp140/ble/ota_service.cpp index fa4c3cd..6eaf6c8 100644 --- a/src/sp140/ble/ota_service.cpp +++ b/src/sp140/ble/ota_service.cpp @@ -7,7 +7,8 @@ namespace { -// OTA Commands +// OTA Commands (matching Espressif example constants where applicable) +// Example: 0x01 = Start, 0x02 = End, 0x03 = Abort const uint8_t CMD_START = 0x01; const uint8_t CMD_END = 0x02; const uint8_t CMD_ABORT = 0x03; @@ -24,13 +25,18 @@ esp_ota_handle_t updateHandle = 0; const esp_partition_t* updatePartition = nullptr; size_t receivedBytes = 0; -void sendResponse(NimBLECharacteristic* pChar, uint8_t responseCode) { - pChar->setValue(&responseCode, 1); - pChar->notify(); - USBSerial.printf("OTA: Sent response 0x%02X\n", responseCode); +// Status characteristic for notifications +NimBLECharacteristic* pStatusChar = nullptr; + +void sendResponse(uint8_t responseCode) { + if (pStatusChar) { + pStatusChar->setValue(&responseCode, 1); + pStatusChar->notify(); + USBSerial.printf("OTA: Sent response 0x%02X\n", responseCode); + } } -class OtaControlCallback : public NimBLECharacteristicCallbacks { +class OtaCommandCallback : public NimBLECharacteristicCallbacks { void onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo) override { (void)connInfo; std::string value = pChar->getValue(); @@ -44,37 +50,36 @@ class OtaControlCallback : public NimBLECharacteristicCallbacks { updatePartition = esp_ota_get_next_update_partition(nullptr); if (!updatePartition) { USBSerial.println("OTA Error: No update partition found"); - sendResponse(pChar, RESP_ERROR_BEGIN); + sendResponse(RESP_ERROR_BEGIN); return; } USBSerial.printf("OTA: Writing to partition subtype %d at offset 0x%x\n", updatePartition->subtype, updatePartition->address); - // OTA_SIZE_UNKNOWN allows flashing any size, but requires enough space esp_err_t err = esp_ota_begin(updatePartition, OTA_SIZE_UNKNOWN, &updateHandle); if (err != ESP_OK) { USBSerial.printf("OTA Error: esp_ota_begin failed (0x%x)\n", err); - sendResponse(pChar, RESP_ERROR_BEGIN); + sendResponse(RESP_ERROR_BEGIN); return; } otaInProgress = true; receivedBytes = 0; - sendResponse(pChar, RESP_SUCCESS); + sendResponse(RESP_SUCCESS); } else if (command == CMD_END) { USBSerial.println("OTA: End command received"); if (!otaInProgress) { - sendResponse(pChar, RESP_ERROR_UNKNOWN); + sendResponse(RESP_ERROR_UNKNOWN); return; } esp_err_t err = esp_ota_end(updateHandle); if (err != ESP_OK) { USBSerial.printf("OTA Error: esp_ota_end failed (0x%x)\n", err); - sendResponse(pChar, RESP_ERROR_END); + sendResponse(RESP_ERROR_END); otaInProgress = false; return; } @@ -82,13 +87,13 @@ class OtaControlCallback : public NimBLECharacteristicCallbacks { err = esp_ota_set_boot_partition(updatePartition); if (err != ESP_OK) { USBSerial.printf("OTA Error: set_boot_partition failed (0x%x)\n", err); - sendResponse(pChar, RESP_ERROR_END); + sendResponse(RESP_ERROR_END); otaInProgress = false; return; } USBSerial.println("OTA: Success! Restarting..."); - sendResponse(pChar, RESP_SUCCESS); + sendResponse(RESP_SUCCESS); delay(1000); ESP.restart(); @@ -98,7 +103,7 @@ class OtaControlCallback : public NimBLECharacteristicCallbacks { esp_ota_end(updateHandle); otaInProgress = false; } - sendResponse(pChar, RESP_SUCCESS); + sendResponse(RESP_SUCCESS); } } }; @@ -113,10 +118,10 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { esp_err_t err = esp_ota_write(updateHandle, value.data(), value.length()); if (err != ESP_OK) { USBSerial.printf("OTA Error: Write failed (0x%x)\n", err); - // Optionally notify control char of error, but might be slow + sendResponse(RESP_ERROR_WRITE); + // Abort? } else { receivedBytes += value.length(); - // Verbose logging only every 10KB to avoid spam if (receivedBytes % 10240 < value.length()) { USBSerial.printf("OTA: Received %d bytes\n", receivedBytes); } @@ -130,12 +135,20 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { void initOtaBleService(NimBLEServer* pServer) { NimBLEService* pService = pServer->createService(OTA_SERVICE_UUID); - NimBLECharacteristic* pControlChar = pService->createCharacteristic( - OTA_CONTROL_UUID, - NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY + // Command Characteristic (Write) + NimBLECharacteristic* pCommandChar = pService->createCharacteristic( + OTA_COMMAND_UUID, + NIMBLE_PROPERTY::WRITE ); - pControlChar->setCallbacks(new OtaControlCallback()); + pCommandChar->setCallbacks(new OtaCommandCallback()); + // Status Characteristic (Notify) + pStatusChar = pService->createCharacteristic( + OTA_STATUS_UUID, + NIMBLE_PROPERTY::NOTIFY + ); + + // Data Characteristic (Write No Response) NimBLECharacteristic* pDataChar = pService->createCharacteristic( OTA_DATA_UUID, NIMBLE_PROPERTY::WRITE_NR // Write No Response for speed @@ -147,4 +160,4 @@ void initOtaBleService(NimBLEServer* pServer) { bool isOtaInProgress() { return otaInProgress; -} +} \ No newline at end of file diff --git a/src/sp140/main.cpp b/src/sp140/main.cpp index ab1813f..b6ef27e 100644 --- a/src/sp140/main.cpp +++ b/src/sp140/main.cpp @@ -2,6 +2,7 @@ // OpenPPG #include "Arduino.h" #include "sp140/device_settings.h" +#include "sp140/ble/ota_service.h" #include "../../inc/sp140/esp32s3-config.h" @@ -225,7 +226,7 @@ void bleStateUpdateTask(void* parameter) { pDeviceStateCharacteristic->setValue(&update.state, sizeof(update.state)); // Only notify if requested and connected - if (update.needsNotify && deviceConnected) { + if (update.needsNotify && deviceConnected && !isOtaInProgress()) { vTaskDelay(pdMS_TO_TICKS(10)); // Additional delay before notify pDeviceStateCharacteristic->notify(); } From dd8cc21da96886447ecb1d07aab40155f367b789 Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Mon, 26 Jan 2026 15:13:50 -0600 Subject: [PATCH 03/16] Enable OTA rollback and confirm firmware validity Added CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE to sdkconfig.defaults to support OTA rollback. In main.cpp, added logic to mark the firmware as valid and cancel rollback after successful boot, ensuring OTA updates are confirmed. --- sdkconfig.defaults | 1 + src/sp140/main.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/sdkconfig.defaults b/sdkconfig.defaults index b7682f1..de6dfec 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -4,3 +4,4 @@ CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y CONFIG_BT_ENABLED=y CONFIG_BT_CONTROLLER_ENABLED=y CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y \ No newline at end of file diff --git a/src/sp140/main.cpp b/src/sp140/main.cpp index b6ef27e..b1f8eeb 100644 --- a/src/sp140/main.cpp +++ b/src/sp140/main.cpp @@ -3,6 +3,7 @@ #include "Arduino.h" #include "sp140/device_settings.h" #include "sp140/ble/ota_service.h" +#include "esp_ota_ops.h" #include "../../inc/sp140/esp32s3-config.h" @@ -761,6 +762,11 @@ void setup() { // Simple instrumentation to detect UI/BMS latency USBSerial.println("Init complete. UI + BMS loop running"); + // Confirm successful boot to prevent OTA rollback + if (esp_ota_mark_app_valid_cancel_rollback() == ESP_OK) { + USBSerial.println("OTA: Firmware marked valid - Rollback cancelled"); + } + // Enable sensor monitoring after splash screen and UI setup // This gives BMS/ESC time to initialize and start providing valid data enableMonitoring(); From 4833b13fc6c41235493a27bbc5b38d3d4a07bc33 Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Mon, 26 Jan 2026 15:42:51 -0600 Subject: [PATCH 04/16] Refactor BLE OTA service to Espressif sector/CRC protocol Reworks OTA BLE service to use Espressif's sector-based protocol with CRC16 validation, sector buffering, and explicit ACK/ERR responses. OTA UUIDs are now NimBLEUUID constants for compatibility with official Espressif OTA apps. Improves reliability and error handling, and merges command/status characteristics as per Espressif's protocol. --- inc/sp140/ble/ble_ids.h | 13 +- src/sp140/ble/ota_service.cpp | 267 ++++++++++++++++++++++------------ 2 files changed, 176 insertions(+), 104 deletions(-) diff --git a/inc/sp140/ble/ble_ids.h b/inc/sp140/ble/ble_ids.h index dd5f944..17bb05f 100644 --- a/inc/sp140/ble/ble_ids.h +++ b/inc/sp140/ble/ble_ids.h @@ -67,12 +67,11 @@ #define CONTROLLER_SERVICE_UUID "01C63B60-0891-4655-BBCA-8E745C48A175" #define CONTROLLER_TELEMETRY_UUID "01C63B61-0891-4655-BBCA-8E745C48A176" -// ============================================================================ -// OTA Service (Firmware Update) - Espressif Standard -// ============================================================================ -#define OTA_SERVICE_UUID "00008018-0000-1000-8000-00805F9B34FB" -#define OTA_DATA_UUID "00008019-0000-1000-8000-00805F9B34FB" // RX: Firmware data -#define OTA_STATUS_UUID "0000801A-0000-1000-8000-00805F9B34FB" // TX: Notifications/Status -#define OTA_COMMAND_UUID "0000801B-0000-1000-8000-00805F9B34FB" // RX: Commands (Start/End) +// Espressif Standard OTA Service UUIDs +// Compatible with official Espressif BLE OTA apps (requires Sector/CRC protocol) +static const NimBLEUUID OTA_SERVICE_UUID("00008018-0000-1000-8000-00805f9b34fb"); +static const NimBLEUUID OTA_COMMAND_UUID("0000801a-0000-1000-8000-00805f9b34fb"); // Command (Write/Notify) +static const NimBLEUUID OTA_STATUS_UUID("0000801a-0000-1000-8000-00805f9b34fb"); // Status (Notify) - effectively same as Command in this protocol +static const NimBLEUUID OTA_DATA_UUID("00008019-0000-1000-8000-00805f9b34fb"); // Data (Write) #endif // INC_SP140_BLE_BLE_IDS_H_ diff --git a/src/sp140/ble/ota_service.cpp b/src/sp140/ble/ota_service.cpp index 6eaf6c8..c502a99 100644 --- a/src/sp140/ble/ota_service.cpp +++ b/src/sp140/ble/ota_service.cpp @@ -4,156 +4,229 @@ #include "esp_ota_ops.h" #include "esp_partition.h" #include "sp140/ble/ble_ids.h" +#include namespace { -// OTA Commands (matching Espressif example constants where applicable) -// Example: 0x01 = Start, 0x02 = End, 0x03 = Abort -const uint8_t CMD_START = 0x01; -const uint8_t CMD_END = 0x02; -const uint8_t CMD_ABORT = 0x03; +// Protocol Constants +const uint16_t CMD_START = 0x0001; +const uint16_t CMD_END = 0x0002; +const uint16_t CMD_ACK = 0x0003; -// OTA Responses -const uint8_t RESP_SUCCESS = 0x00; -const uint8_t RESP_ERROR_BEGIN = 0xE1; -const uint8_t RESP_ERROR_WRITE = 0xE2; -const uint8_t RESP_ERROR_END = 0xE3; -const uint8_t RESP_ERROR_UNKNOWN = 0xFF; +const uint16_t ACK_SUCCESS = 0x0000; +const uint16_t ACK_ERR_CRC = 0x0001; +const uint16_t ACK_ERR_SECTOR = 0x0002; +const uint16_t ACK_ERR_LEN = 0x0003; +// State volatile bool otaInProgress = false; esp_ota_handle_t updateHandle = 0; const esp_partition_t* updatePartition = nullptr; -size_t receivedBytes = 0; +volatile unsigned long lastOtaActivity = 0; + +// Buffering +uint8_t sectorBuffer[4096]; +uint16_t sectorBufferLen = 0; +uint16_t currentSectorIndex = 0; + +// Notify Characteristic +NimBLECharacteristic* pCommandChar = nullptr; + +// CRC16 Implementation (Polynomial 0x8005, reversed for LE) +// Matches Espressif's expected CRC16-ARC/Modbus +uint16_t crc16_le(uint16_t crc, const uint8_t *buffer, size_t len) { + while (len--) { + crc ^= *buffer++; + for (int i = 0; i < 8; i++) { + if (crc & 1) crc = (crc >> 1) ^ 0xA001; + else crc = (crc >> 1); + } + } + return crc; +} -// Status characteristic for notifications -NimBLECharacteristic* pStatusChar = nullptr; +void abortOta() { + if (otaInProgress) { + if (updateHandle) esp_ota_end(updateHandle); + otaInProgress = false; + USBSerial.println("OTA: Aborted."); + } + sectorBufferLen = 0; + currentSectorIndex = 0; +} -void sendResponse(uint8_t responseCode) { - if (pStatusChar) { - pStatusChar->setValue(&responseCode, 1); - pStatusChar->notify(); - USBSerial.printf("OTA: Sent response 0x%02X\n", responseCode); +void sendAck(uint16_t sector, uint16_t status) { + if (pCommandChar) { + uint8_t packet[6]; + // Sector (2B LE) + packet[0] = sector & 0xFF; + packet[1] = (sector >> 8) & 0xFF; + // Status (2B LE) + packet[2] = status & 0xFF; + packet[3] = (status >> 8) & 0xFF; + // CRC (2B LE) - CRC of the first 4 bytes + uint16_t crc = crc16_le(0, packet, 4); + packet[4] = crc & 0xFF; + packet[5] = (crc >> 8) & 0xFF; + + pCommandChar->setValue(packet, 6); + pCommandChar->notify(); + USBSerial.printf("OTA: Sent ACK Sector=%d Status=%d\n", sector, status); } } class OtaCommandCallback : public NimBLECharacteristicCallbacks { void onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo) override { - (void)connInfo; std::string value = pChar->getValue(); - if (value.length() == 0) return; + if (value.length() < 4) return; // Min length check - uint8_t command = value[0]; + lastOtaActivity = millis(); + const uint8_t* data = (const uint8_t*)value.data(); + + uint16_t cmdId = data[0] | (data[1] << 8); - if (command == CMD_START) { - USBSerial.println("OTA: Start command received"); - + if (cmdId == CMD_START) { + USBSerial.println("OTA: CMD_START"); updatePartition = esp_ota_get_next_update_partition(nullptr); if (!updatePartition) { - USBSerial.println("OTA Error: No update partition found"); - sendResponse(RESP_ERROR_BEGIN); + USBSerial.println("OTA Error: No partition"); return; } - - USBSerial.printf("OTA: Writing to partition subtype %d at offset 0x%x\n", - updatePartition->subtype, updatePartition->address); - + esp_err_t err = esp_ota_begin(updatePartition, OTA_SIZE_UNKNOWN, &updateHandle); if (err != ESP_OK) { - USBSerial.printf("OTA Error: esp_ota_begin failed (0x%x)\n", err); - sendResponse(RESP_ERROR_BEGIN); - return; + USBSerial.printf("OTA Error: Begin failed 0x%x\n", err); + return; } otaInProgress = true; - receivedBytes = 0; - sendResponse(RESP_SUCCESS); - - } else if (command == CMD_END) { - USBSerial.println("OTA: End command received"); - - if (!otaInProgress) { - sendResponse(RESP_ERROR_UNKNOWN); - return; - } - - esp_err_t err = esp_ota_end(updateHandle); - if (err != ESP_OK) { - USBSerial.printf("OTA Error: esp_ota_end failed (0x%x)\n", err); - sendResponse(RESP_ERROR_END); - otaInProgress = false; - return; - } - - err = esp_ota_set_boot_partition(updatePartition); - if (err != ESP_OK) { - USBSerial.printf("OTA Error: set_boot_partition failed (0x%x)\n", err); - sendResponse(RESP_ERROR_END); - otaInProgress = false; - return; + sectorBufferLen = 0; + currentSectorIndex = 0; + + // Send Command Response (ID=3, Payload=Success) + uint8_t response[6] = { + 0x03, 0x00, // ID = 3 (Response) + 0x00, 0x00, // Payload = 0 (Success) + 0x00, 0x00 // CRC placeholder (TODO: calculate if strictly needed) + }; + pChar->setValue(response, 6); + pChar->notify(); + + } else if (cmdId == CMD_END) { + USBSerial.println("OTA: CMD_END"); + if (otaInProgress) { + if (esp_ota_end(updateHandle) == ESP_OK) { + if (esp_ota_set_boot_partition(updatePartition) == ESP_OK) { + USBSerial.println("OTA Success. Restarting..."); + + uint8_t response[6] = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 }; + pChar->setValue(response, 6); + pChar->notify(); + + delay(500); + ESP.restart(); + } + } + abortOta(); } - - USBSerial.println("OTA: Success! Restarting..."); - sendResponse(RESP_SUCCESS); - delay(1000); - ESP.restart(); - - } else if (command == CMD_ABORT) { - USBSerial.println("OTA: Abort command received"); - if (otaInProgress) { - esp_ota_end(updateHandle); - otaInProgress = false; - } - sendResponse(RESP_SUCCESS); } } }; class OtaDataCallback : public NimBLECharacteristicCallbacks { void onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo) override { - (void)connInfo; if (!otaInProgress) return; + + std::string valStr = pChar->getValue(); + size_t len = valStr.length(); + const uint8_t* data = (const uint8_t*)valStr.data(); + + if (len < 3) return; // Header: Sector(2) + Seq(1) + + lastOtaActivity = millis(); + + uint16_t sector = data[0] | (data[1] << 8); + uint8_t seq = data[2]; + const uint8_t* payload = data + 3; + size_t payloadLen = len - 3; + + if (sector != currentSectorIndex) { + // Silently ignore or warn? Official app might retry if we don't ACK. + // But if we send ACK_ERR_SECTOR, it forces resync. + USBSerial.printf("OTA Warn: Sector mismatch exp %d got %d\n", currentSectorIndex, sector); + sendAck(sector, ACK_ERR_SECTOR); + return; + } - std::string value = pChar->getValue(); - if (value.length() > 0) { - esp_err_t err = esp_ota_write(updateHandle, value.data(), value.length()); - if (err != ESP_OK) { - USBSerial.printf("OTA Error: Write failed (0x%x)\n", err); - sendResponse(RESP_ERROR_WRITE); - // Abort? - } else { - receivedBytes += value.length(); - if (receivedBytes % 10240 < value.length()) { - USBSerial.printf("OTA: Received %d bytes\n", receivedBytes); + if (seq == 0xFF) { // Last packet of sector: Payload contains Data + CRC16(2) + if (payloadLen < 2) return; + + size_t actualDataLen = payloadLen - 2; + + if (sectorBufferLen + actualDataLen > sizeof(sectorBuffer)) { + sendAck(sector, ACK_ERR_LEN); + sectorBufferLen = 0; // Reset buffer + return; + } + + memcpy(sectorBuffer + sectorBufferLen, payload, actualDataLen); + sectorBufferLen += actualDataLen; + + // Verify CRC + // CRC is at the end of the packet payload + uint16_t rxCrc = payload[actualDataLen] | (payload[actualDataLen + 1] << 8); + uint16_t calcCrc = crc16_le(0, sectorBuffer, sectorBufferLen); + + if (rxCrc == calcCrc) { + // Write to flash + esp_err_t err = esp_ota_write(updateHandle, sectorBuffer, sectorBufferLen); + if (err == ESP_OK) { + sendAck(sector, ACK_SUCCESS); + currentSectorIndex++; + sectorBufferLen = 0; + } else { + USBSerial.printf("OTA Error: Write failed 0x%x\n", err); + abortOta(); } + } else { + USBSerial.printf("OTA Error: CRC fail exp 0x%04X got 0x%04X\n", rxCrc, calcCrc); + sendAck(sector, ACK_ERR_CRC); + sectorBufferLen = 0; // Reset for retry } + + } else { // Normal packet + if (sectorBufferLen + payloadLen > sizeof(sectorBuffer)) { + USBSerial.println("OTA Error: Buffer overflow"); + // Don't ACK, let client retry or timeout + return; + } + memcpy(sectorBuffer + sectorBufferLen, payload, payloadLen); + sectorBufferLen += payloadLen; } } }; +static OtaCommandCallback cmdCallback; +static OtaDataCallback dataCallback; + } // namespace void initOtaBleService(NimBLEServer* pServer) { NimBLEService* pService = pServer->createService(OTA_SERVICE_UUID); - // Command Characteristic (Write) - NimBLECharacteristic* pCommandChar = pService->createCharacteristic( + // Command (Write + Notify for ACKs) + pCommandChar = pService->createCharacteristic( OTA_COMMAND_UUID, - NIMBLE_PROPERTY::WRITE - ); - pCommandChar->setCallbacks(new OtaCommandCallback()); - - // Status Characteristic (Notify) - pStatusChar = pService->createCharacteristic( - OTA_STATUS_UUID, - NIMBLE_PROPERTY::NOTIFY + NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY ); + pCommandChar->setCallbacks(&cmdCallback); - // Data Characteristic (Write No Response) + // Data (Write No Response) NimBLECharacteristic* pDataChar = pService->createCharacteristic( OTA_DATA_UUID, - NIMBLE_PROPERTY::WRITE_NR // Write No Response for speed + NIMBLE_PROPERTY::WRITE_NR ); - pDataChar->setCallbacks(new OtaDataCallback()); + pDataChar->setCallbacks(&dataCallback); pService->start(); } From a9a2b10b525b2d46541f3e510165aa0ee3977cc0 Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Mon, 26 Jan 2026 16:39:07 -0600 Subject: [PATCH 05/16] Update ota_service.cpp --- src/sp140/ble/ota_service.cpp | 136 +++++++++++++++++++++++----------- 1 file changed, 93 insertions(+), 43 deletions(-) diff --git a/src/sp140/ble/ota_service.cpp b/src/sp140/ble/ota_service.cpp index c502a99..e827dd4 100644 --- a/src/sp140/ble/ota_service.cpp +++ b/src/sp140/ble/ota_service.cpp @@ -4,8 +4,12 @@ #include "esp_ota_ops.h" #include "esp_partition.h" #include "sp140/ble/ble_ids.h" +#include "sp140/device_state.h" #include +// Access global state to block OTA when ARMED +extern volatile DeviceState currentState; + namespace { // Protocol Constants @@ -22,7 +26,6 @@ const uint16_t ACK_ERR_LEN = 0x0003; volatile bool otaInProgress = false; esp_ota_handle_t updateHandle = 0; const esp_partition_t* updatePartition = nullptr; -volatile unsigned long lastOtaActivity = 0; // Buffering uint8_t sectorBuffer[4096]; @@ -33,7 +36,6 @@ uint16_t currentSectorIndex = 0; NimBLECharacteristic* pCommandChar = nullptr; // CRC16 Implementation (Polynomial 0x8005, reversed for LE) -// Matches Espressif's expected CRC16-ARC/Modbus uint16_t crc16_le(uint16_t crc, const uint8_t *buffer, size_t len) { while (len--) { crc ^= *buffer++; @@ -45,26 +47,14 @@ uint16_t crc16_le(uint16_t crc, const uint8_t *buffer, size_t len) { return crc; } -void abortOta() { - if (otaInProgress) { - if (updateHandle) esp_ota_end(updateHandle); - otaInProgress = false; - USBSerial.println("OTA: Aborted."); - } - sectorBufferLen = 0; - currentSectorIndex = 0; -} - void sendAck(uint16_t sector, uint16_t status) { if (pCommandChar) { uint8_t packet[6]; - // Sector (2B LE) packet[0] = sector & 0xFF; packet[1] = (sector >> 8) & 0xFF; - // Status (2B LE) packet[2] = status & 0xFF; packet[3] = (status >> 8) & 0xFF; - // CRC (2B LE) - CRC of the first 4 bytes + uint16_t crc = crc16_le(0, packet, 4); packet[4] = crc & 0xFF; packet[5] = (crc >> 8) & 0xFF; @@ -75,27 +65,89 @@ void sendAck(uint16_t sector, uint16_t status) { } } +// Send Command Response (ID=3, Payload, CRC) +void sendCommandResponse(uint16_t status) { + if (pCommandChar) { + uint8_t packet[20]; // 2 ID + 16 Payload + 2 CRC + memset(packet, 0, 20); // Fill payload with 0 + + packet[0] = CMD_ACK & 0xFF; // 0x03 + packet[1] = (CMD_ACK >> 8) & 0xFF; // 0x00 + + // Payload (Bytes 2-17): Byte 2-3 = Status + packet[2] = status & 0xFF; + packet[3] = (status >> 8) & 0xFF; + + uint16_t crc = crc16_le(0, packet, 18); + packet[18] = crc & 0xFF; + packet[19] = (crc >> 8) & 0xFF; + + pCommandChar->setValue(packet, 20); + pCommandChar->notify(); + USBSerial.printf("OTA: Sent CMD Response Status=%d\n", status); + } +} + +void abortOta() { + if (otaInProgress) { + if (updateHandle) esp_ota_abort(updateHandle); + otaInProgress = false; + USBSerial.println("OTA: Aborted."); + } + sectorBufferLen = 0; + currentSectorIndex = 0; +} + class OtaCommandCallback : public NimBLECharacteristicCallbacks { void onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo) override { std::string value = pChar->getValue(); - if (value.length() < 4) return; // Min length check + // Command Packet: ID(2) + Payload(16) + CRC(2) = 20 bytes + if (value.length() < 20) { + USBSerial.println("OTA Error: Invalid CMD length"); + return; + } - lastOtaActivity = millis(); const uint8_t* data = (const uint8_t*)value.data(); + // Verify CRC + uint16_t rxCrc = data[18] | (data[19] << 8); + uint16_t calcCrc = crc16_le(0, data, 18); + if (rxCrc != calcCrc) { + USBSerial.printf("OTA Error: CMD CRC Fail Exp %04X Got %04X\n", rxCrc, calcCrc); + return; + } + uint16_t cmdId = data[0] | (data[1] << 8); if (cmdId == CMD_START) { USBSerial.println("OTA: CMD_START"); + + // Safety Check: Block if Armed + if (currentState == ARMED || currentState == ARMED_CRUISING) { + USBSerial.println("OTA Blocked: Device ARMED"); + sendCommandResponse(0x0001); // Reject (Status 1) + return; + } + updatePartition = esp_ota_get_next_update_partition(nullptr); if (!updatePartition) { USBSerial.println("OTA Error: No partition"); + sendCommandResponse(0x0001); // Reject + return; + } + + // Validate image length from payload (Bytes 2-5) + uint32_t imageLen = data[2] | (data[3] << 8) | (data[4] << 16) | (data[5] << 24); + if (imageLen > updatePartition->size) { + USBSerial.printf("OTA Error: Image size %u > partition %u\n", imageLen, updatePartition->size); + sendCommandResponse(0x0001); return; } esp_err_t err = esp_ota_begin(updatePartition, OTA_SIZE_UNKNOWN, &updateHandle); if (err != ESP_OK) { USBSerial.printf("OTA Error: Begin failed 0x%x\n", err); + sendCommandResponse(0x0001); // Reject return; } @@ -103,14 +155,7 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { sectorBufferLen = 0; currentSectorIndex = 0; - // Send Command Response (ID=3, Payload=Success) - uint8_t response[6] = { - 0x03, 0x00, // ID = 3 (Response) - 0x00, 0x00, // Payload = 0 (Success) - 0x00, 0x00 // CRC placeholder (TODO: calculate if strictly needed) - }; - pChar->setValue(response, 6); - pChar->notify(); + sendCommandResponse(0x0000); // Accept (Status 0) } else if (cmdId == CMD_END) { USBSerial.println("OTA: CMD_END"); @@ -118,16 +163,21 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { if (esp_ota_end(updateHandle) == ESP_OK) { if (esp_ota_set_boot_partition(updatePartition) == ESP_OK) { USBSerial.println("OTA Success. Restarting..."); - - uint8_t response[6] = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 }; - pChar->setValue(response, 6); - pChar->notify(); - + sendCommandResponse(0x0000); // Success delay(500); ESP.restart(); + return; + } else { + USBSerial.println("OTA Error: Set Boot Partition Failed"); } + } else { + USBSerial.println("OTA Error: OTA End Failed"); } + // If we get here, something failed + sendCommandResponse(0x0001); // Reject/Fail abortOta(); + } else { + sendCommandResponse(0x0001); // Not in progress } } } @@ -135,7 +185,7 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { class OtaDataCallback : public NimBLECharacteristicCallbacks { void onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo) override { - if (!otaInProgress) return; + if (!otaInProgress) return; std::string valStr = pChar->getValue(); size_t len = valStr.length(); @@ -143,37 +193,34 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { if (len < 3) return; // Header: Sector(2) + Seq(1) - lastOtaActivity = millis(); - uint16_t sector = data[0] | (data[1] << 8); uint8_t seq = data[2]; const uint8_t* payload = data + 3; size_t payloadLen = len - 3; if (sector != currentSectorIndex) { - // Silently ignore or warn? Official app might retry if we don't ACK. - // But if we send ACK_ERR_SECTOR, it forces resync. USBSerial.printf("OTA Warn: Sector mismatch exp %d got %d\n", currentSectorIndex, sector); + sectorBufferLen = 0; // Reset buffer on mismatch sendAck(sector, ACK_ERR_SECTOR); return; } - if (seq == 0xFF) { // Last packet of sector: Payload contains Data + CRC16(2) + if (seq == 0xFF) { + // Last packet of sector: Payload contains Data + CRC16(2) if (payloadLen < 2) return; size_t actualDataLen = payloadLen - 2; if (sectorBufferLen + actualDataLen > sizeof(sectorBuffer)) { sendAck(sector, ACK_ERR_LEN); - sectorBufferLen = 0; // Reset buffer + sectorBufferLen = 0; return; } memcpy(sectorBuffer + sectorBufferLen, payload, actualDataLen); sectorBufferLen += actualDataLen; - // Verify CRC - // CRC is at the end of the packet payload + // Verify CRC (Last 2 bytes of payload) uint16_t rxCrc = payload[actualDataLen] | (payload[actualDataLen + 1] << 8); uint16_t calcCrc = crc16_le(0, sectorBuffer, sectorBufferLen); @@ -186,6 +233,7 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { sectorBufferLen = 0; } else { USBSerial.printf("OTA Error: Write failed 0x%x\n", err); + sendAck(sector, ACK_ERR_CRC); // Force retry abortOta(); } } else { @@ -194,10 +242,12 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { sectorBufferLen = 0; // Reset for retry } - } else { // Normal packet + } else { + // Normal packet if (sectorBufferLen + payloadLen > sizeof(sectorBuffer)) { USBSerial.println("OTA Error: Buffer overflow"); - // Don't ACK, let client retry or timeout + sectorBufferLen = 0; + sendAck(sector, ACK_ERR_LEN); return; } memcpy(sectorBuffer + sectorBufferLen, payload, payloadLen); @@ -214,7 +264,7 @@ static OtaDataCallback dataCallback; void initOtaBleService(NimBLEServer* pServer) { NimBLEService* pService = pServer->createService(OTA_SERVICE_UUID); - // Command (Write + Notify for ACKs) + // Command (Write + Notify) pCommandChar = pService->createCharacteristic( OTA_COMMAND_UUID, NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY @@ -233,4 +283,4 @@ void initOtaBleService(NimBLEServer* pServer) { bool isOtaInProgress() { return otaInProgress; -} \ No newline at end of file +} From cd1304fb92e9de5507b13e062e1f2dfae066b244 Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Mon, 26 Jan 2026 16:42:45 -0600 Subject: [PATCH 06/16] Enhance OTA service with image size tracking and validation Added tracking of total image length and received bytes during OTA updates. The service now validates that the received image size matches the expected size before completing the update, improving reliability and error handling. Also refined CRC and sector error handling to allow client-side retries instead of aborting the OTA process immediately. --- src/sp140/ble/ota_service.cpp | 53 +++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/src/sp140/ble/ota_service.cpp b/src/sp140/ble/ota_service.cpp index e827dd4..43e352c 100644 --- a/src/sp140/ble/ota_service.cpp +++ b/src/sp140/ble/ota_service.cpp @@ -24,6 +24,7 @@ const uint16_t ACK_ERR_LEN = 0x0003; // State volatile bool otaInProgress = false; +volatile size_t imageTotalLen = 0; esp_ota_handle_t updateHandle = 0; const esp_partition_t* updatePartition = nullptr; @@ -31,6 +32,7 @@ const esp_partition_t* updatePartition = nullptr; uint8_t sectorBuffer[4096]; uint16_t sectorBufferLen = 0; uint16_t currentSectorIndex = 0; +size_t receivedBytes = 0; // Notify Characteristic NimBLECharacteristic* pCommandChar = nullptr; @@ -66,10 +68,11 @@ void sendAck(uint16_t sector, uint16_t status) { } // Send Command Response (ID=3, Payload, CRC) +// Matches esp_ble_ota_cmd_t structure: 20 bytes total void sendCommandResponse(uint16_t status) { if (pCommandChar) { uint8_t packet[20]; // 2 ID + 16 Payload + 2 CRC - memset(packet, 0, 20); // Fill payload with 0 + memset(packet, 0, 20); packet[0] = CMD_ACK & 0xFF; // 0x03 packet[1] = (CMD_ACK >> 8) & 0xFF; // 0x00 @@ -96,6 +99,7 @@ void abortOta() { } sectorBufferLen = 0; currentSectorIndex = 0; + receivedBytes = 0; } class OtaCommandCallback : public NimBLECharacteristicCallbacks { @@ -104,6 +108,7 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { // Command Packet: ID(2) + Payload(16) + CRC(2) = 20 bytes if (value.length() < 20) { USBSerial.println("OTA Error: Invalid CMD length"); + // Can't reliably reply if packet structure is broken return; } @@ -114,6 +119,7 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { uint16_t calcCrc = crc16_le(0, data, 18); if (rxCrc != calcCrc) { USBSerial.printf("OTA Error: CMD CRC Fail Exp %04X Got %04X\n", rxCrc, calcCrc); + sendCommandResponse(0x0001); // Reject (Status 1) return; } @@ -122,21 +128,20 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { if (cmdId == CMD_START) { USBSerial.println("OTA: CMD_START"); - // Safety Check: Block if Armed if (currentState == ARMED || currentState == ARMED_CRUISING) { USBSerial.println("OTA Blocked: Device ARMED"); - sendCommandResponse(0x0001); // Reject (Status 1) + sendCommandResponse(0x0001); // Reject return; } updatePartition = esp_ota_get_next_update_partition(nullptr); if (!updatePartition) { USBSerial.println("OTA Error: No partition"); - sendCommandResponse(0x0001); // Reject + sendCommandResponse(0x0001); return; } - // Validate image length from payload (Bytes 2-5) + // Validate image length (Bytes 2-5 of payload -> data[2]..data[5]) uint32_t imageLen = data[2] | (data[3] << 8) | (data[4] << 16) | (data[5] << 24); if (imageLen > updatePartition->size) { USBSerial.printf("OTA Error: Image size %u > partition %u\n", imageLen, updatePartition->size); @@ -147,24 +152,34 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { esp_err_t err = esp_ota_begin(updatePartition, OTA_SIZE_UNKNOWN, &updateHandle); if (err != ESP_OK) { USBSerial.printf("OTA Error: Begin failed 0x%x\n", err); - sendCommandResponse(0x0001); // Reject + sendCommandResponse(0x0001); return; } otaInProgress = true; + imageTotalLen = imageLen; + receivedBytes = 0; sectorBufferLen = 0; currentSectorIndex = 0; - sendCommandResponse(0x0000); // Accept (Status 0) + sendCommandResponse(0x0000); // Accept } else if (cmdId == CMD_END) { USBSerial.println("OTA: CMD_END"); if (otaInProgress) { + // Defensive: Verify total bytes received match manifest + if (receivedBytes != imageTotalLen) { + USBSerial.printf("OTA Error: Size Mismatch Rx:%u Exp:%u\n", receivedBytes, imageTotalLen); + sendCommandResponse(0x0001); // Fail + abortOta(); + return; + } + if (esp_ota_end(updateHandle) == ESP_OK) { if (esp_ota_set_boot_partition(updatePartition) == ESP_OK) { USBSerial.println("OTA Success. Restarting..."); sendCommandResponse(0x0000); // Success - delay(500); + delay(1000); // Allow BLE flush ESP.restart(); return; } else { @@ -173,8 +188,7 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { } else { USBSerial.println("OTA Error: OTA End Failed"); } - // If we get here, something failed - sendCommandResponse(0x0001); // Reject/Fail + sendCommandResponse(0x0001); // Fail abortOta(); } else { sendCommandResponse(0x0001); // Not in progress @@ -185,7 +199,7 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { class OtaDataCallback : public NimBLECharacteristicCallbacks { void onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo) override { - if (!otaInProgress) return; + if (!otaInProgress) return; std::string valStr = pChar->getValue(); size_t len = valStr.length(); @@ -200,13 +214,13 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { if (sector != currentSectorIndex) { USBSerial.printf("OTA Warn: Sector mismatch exp %d got %d\n", currentSectorIndex, sector); - sectorBufferLen = 0; // Reset buffer on mismatch + sectorBufferLen = 0; sendAck(sector, ACK_ERR_SECTOR); return; } if (seq == 0xFF) { - // Last packet of sector: Payload contains Data + CRC16(2) + // Last packet: Payload is Data + CRC16(2) if (payloadLen < 2) return; size_t actualDataLen = payloadLen - 2; @@ -220,26 +234,29 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { memcpy(sectorBuffer + sectorBufferLen, payload, actualDataLen); sectorBufferLen += actualDataLen; - // Verify CRC (Last 2 bytes of payload) + // Verify CRC uint16_t rxCrc = payload[actualDataLen] | (payload[actualDataLen + 1] << 8); uint16_t calcCrc = crc16_le(0, sectorBuffer, sectorBufferLen); if (rxCrc == calcCrc) { - // Write to flash esp_err_t err = esp_ota_write(updateHandle, sectorBuffer, sectorBufferLen); if (err == ESP_OK) { + receivedBytes += sectorBufferLen; sendAck(sector, ACK_SUCCESS); currentSectorIndex++; sectorBufferLen = 0; } else { USBSerial.printf("OTA Error: Write failed 0x%x\n", err); - sendAck(sector, ACK_ERR_CRC); // Force retry - abortOta(); + sendAck(sector, ACK_ERR_SECTOR); // Force retry + sectorBufferLen = 0; + // Don't hard abort yet, allow retry? + // Espressif tools usually retry logic is client side. + // If we return ERR_SECTOR, client re-sends sector. } } else { USBSerial.printf("OTA Error: CRC fail exp 0x%04X got 0x%04X\n", rxCrc, calcCrc); sendAck(sector, ACK_ERR_CRC); - sectorBufferLen = 0; // Reset for retry + sectorBufferLen = 0; } } else { From faeb2ca3cdf0d7a0181fc36011963d61650f2399 Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Mon, 26 Jan 2026 17:12:03 -0600 Subject: [PATCH 07/16] Update BLE OTA service UUIDs and protocol Revised BLE OTA characteristic UUIDs to match Android esp-ble-ota-android app requirements and updated protocol handling in ota_service.cpp. ACK and command response logic now use new characteristics and payload formats. Also added 'rbl' as an alias for the 'reboot' serial command. --- inc/sp140/ble/ble_ids.h | 10 ++-- src/sp140/ble/ota_service.cpp | 93 +++++++++++++++++++++-------------- src/sp140/device_settings.cpp | 2 +- 3 files changed, 61 insertions(+), 44 deletions(-) diff --git a/inc/sp140/ble/ble_ids.h b/inc/sp140/ble/ble_ids.h index 17bb05f..5582af0 100644 --- a/inc/sp140/ble/ble_ids.h +++ b/inc/sp140/ble/ble_ids.h @@ -67,11 +67,11 @@ #define CONTROLLER_SERVICE_UUID "01C63B60-0891-4655-BBCA-8E745C48A175" #define CONTROLLER_TELEMETRY_UUID "01C63B61-0891-4655-BBCA-8E745C48A176" -// Espressif Standard OTA Service UUIDs -// Compatible with official Espressif BLE OTA apps (requires Sector/CRC protocol) +// Espressif Standard OTA Service UUIDs (Android esp-ble-ota-android app) static const NimBLEUUID OTA_SERVICE_UUID("00008018-0000-1000-8000-00805f9b34fb"); -static const NimBLEUUID OTA_COMMAND_UUID("0000801a-0000-1000-8000-00805f9b34fb"); // Command (Write/Notify) -static const NimBLEUUID OTA_STATUS_UUID("0000801a-0000-1000-8000-00805f9b34fb"); // Status (Notify) - effectively same as Command in this protocol -static const NimBLEUUID OTA_DATA_UUID("00008019-0000-1000-8000-00805f9b34fb"); // Data (Write) +static const NimBLEUUID OTA_RECV_FW_UUID("00008020-0000-1000-8000-00805f9b34fb"); // Firmware data (Write/Indicate) +static const NimBLEUUID OTA_PROGRESS_UUID("00008021-0000-1000-8000-00805f9b34fb"); // Progress (Indicate) +static const NimBLEUUID OTA_COMMAND_UUID("00008022-0000-1000-8000-00805f9b34fb"); // Command (Write/Indicate) +static const NimBLEUUID OTA_CUSTOMER_UUID("00008023-0000-1000-8000-00805f9b34fb"); // Customer (Indicate) #endif // INC_SP140_BLE_BLE_IDS_H_ diff --git a/src/sp140/ble/ota_service.cpp b/src/sp140/ble/ota_service.cpp index 43e352c..8518992 100644 --- a/src/sp140/ble/ota_service.cpp +++ b/src/sp140/ble/ota_service.cpp @@ -34,8 +34,11 @@ uint16_t sectorBufferLen = 0; uint16_t currentSectorIndex = 0; size_t receivedBytes = 0; -// Notify Characteristic -NimBLECharacteristic* pCommandChar = nullptr; +// OTA characteristics +NimBLECharacteristic* pRecvFwChar = nullptr; +NimBLECharacteristic* pProgressChar = nullptr; +NimBLECharacteristic* pCommandChar = nullptr; +NimBLECharacteristic* pCustomerChar = nullptr; // CRC16 Implementation (Polynomial 0x8005, reversed for LE) uint16_t crc16_le(uint16_t crc, const uint8_t *buffer, size_t len) { @@ -49,27 +52,27 @@ uint16_t crc16_le(uint16_t crc, const uint8_t *buffer, size_t len) { return crc; } -void sendAck(uint16_t sector, uint16_t status) { - if (pCommandChar) { +void sendAck(uint16_t sector, uint16_t status, uint16_t expectedSector = 0) { + if (pRecvFwChar) { uint8_t packet[6]; packet[0] = sector & 0xFF; packet[1] = (sector >> 8) & 0xFF; packet[2] = status & 0xFF; packet[3] = (status >> 8) & 0xFF; - - uint16_t crc = crc16_le(0, packet, 4); - packet[4] = crc & 0xFF; - packet[5] = (crc >> 8) & 0xFF; - - pCommandChar->setValue(packet, 6); - pCommandChar->notify(); + + // Android app expects expected sector index in bytes 4-5 on sector error. + packet[4] = expectedSector & 0xFF; + packet[5] = (expectedSector >> 8) & 0xFF; + + pRecvFwChar->setValue(packet, 6); + pRecvFwChar->indicate(); USBSerial.printf("OTA: Sent ACK Sector=%d Status=%d\n", sector, status); } } // Send Command Response (ID=3, Payload, CRC) // Matches esp_ble_ota_cmd_t structure: 20 bytes total -void sendCommandResponse(uint16_t status) { +void sendCommandResponse(uint16_t ackId, uint16_t status) { if (pCommandChar) { uint8_t packet[20]; // 2 ID + 16 Payload + 2 CRC memset(packet, 0, 20); @@ -77,17 +80,19 @@ void sendCommandResponse(uint16_t status) { packet[0] = CMD_ACK & 0xFF; // 0x03 packet[1] = (CMD_ACK >> 8) & 0xFF; // 0x00 - // Payload (Bytes 2-17): Byte 2-3 = Status - packet[2] = status & 0xFF; - packet[3] = (status >> 8) & 0xFF; + // Payload (Bytes 2-17): Byte 2-3 = Ack ID, Byte 4-5 = Status + packet[2] = ackId & 0xFF; + packet[3] = (ackId >> 8) & 0xFF; + packet[4] = status & 0xFF; + packet[5] = (status >> 8) & 0xFF; uint16_t crc = crc16_le(0, packet, 18); packet[18] = crc & 0xFF; packet[19] = (crc >> 8) & 0xFF; pCommandChar->setValue(packet, 20); - pCommandChar->notify(); - USBSerial.printf("OTA: Sent CMD Response Status=%d\n", status); + pCommandChar->indicate(); + USBSerial.printf("OTA: Sent CMD Response AckId=%d Status=%d\n", ackId, status); } } @@ -114,30 +119,30 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { const uint8_t* data = (const uint8_t*)value.data(); + uint16_t cmdId = data[0] | (data[1] << 8); + // Verify CRC uint16_t rxCrc = data[18] | (data[19] << 8); uint16_t calcCrc = crc16_le(0, data, 18); if (rxCrc != calcCrc) { USBSerial.printf("OTA Error: CMD CRC Fail Exp %04X Got %04X\n", rxCrc, calcCrc); - sendCommandResponse(0x0001); // Reject (Status 1) + sendCommandResponse(cmdId, 0x0001); // Reject (Status 1) return; } - - uint16_t cmdId = data[0] | (data[1] << 8); if (cmdId == CMD_START) { USBSerial.println("OTA: CMD_START"); if (currentState == ARMED || currentState == ARMED_CRUISING) { USBSerial.println("OTA Blocked: Device ARMED"); - sendCommandResponse(0x0001); // Reject + sendCommandResponse(CMD_START, 0x0001); // Reject return; } updatePartition = esp_ota_get_next_update_partition(nullptr); if (!updatePartition) { USBSerial.println("OTA Error: No partition"); - sendCommandResponse(0x0001); + sendCommandResponse(CMD_START, 0x0001); return; } @@ -145,14 +150,14 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { uint32_t imageLen = data[2] | (data[3] << 8) | (data[4] << 16) | (data[5] << 24); if (imageLen > updatePartition->size) { USBSerial.printf("OTA Error: Image size %u > partition %u\n", imageLen, updatePartition->size); - sendCommandResponse(0x0001); + sendCommandResponse(CMD_START, 0x0001); return; } esp_err_t err = esp_ota_begin(updatePartition, OTA_SIZE_UNKNOWN, &updateHandle); if (err != ESP_OK) { USBSerial.printf("OTA Error: Begin failed 0x%x\n", err); - sendCommandResponse(0x0001); + sendCommandResponse(CMD_START, 0x0001); return; } @@ -162,7 +167,7 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { sectorBufferLen = 0; currentSectorIndex = 0; - sendCommandResponse(0x0000); // Accept + sendCommandResponse(CMD_START, 0x0000); // Accept } else if (cmdId == CMD_END) { USBSerial.println("OTA: CMD_END"); @@ -170,7 +175,7 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { // Defensive: Verify total bytes received match manifest if (receivedBytes != imageTotalLen) { USBSerial.printf("OTA Error: Size Mismatch Rx:%u Exp:%u\n", receivedBytes, imageTotalLen); - sendCommandResponse(0x0001); // Fail + sendCommandResponse(CMD_END, 0x0001); // Fail abortOta(); return; } @@ -178,7 +183,7 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { if (esp_ota_end(updateHandle) == ESP_OK) { if (esp_ota_set_boot_partition(updatePartition) == ESP_OK) { USBSerial.println("OTA Success. Restarting..."); - sendCommandResponse(0x0000); // Success + sendCommandResponse(CMD_END, 0x0000); // Success delay(1000); // Allow BLE flush ESP.restart(); return; @@ -188,10 +193,10 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { } else { USBSerial.println("OTA Error: OTA End Failed"); } - sendCommandResponse(0x0001); // Fail + sendCommandResponse(CMD_END, 0x0001); // Fail abortOta(); } else { - sendCommandResponse(0x0001); // Not in progress + sendCommandResponse(CMD_END, 0x0001); // Not in progress } } } @@ -215,7 +220,7 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { if (sector != currentSectorIndex) { USBSerial.printf("OTA Warn: Sector mismatch exp %d got %d\n", currentSectorIndex, sector); sectorBufferLen = 0; - sendAck(sector, ACK_ERR_SECTOR); + sendAck(sector, ACK_ERR_SECTOR, currentSectorIndex); return; } @@ -247,7 +252,7 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { sectorBufferLen = 0; } else { USBSerial.printf("OTA Error: Write failed 0x%x\n", err); - sendAck(sector, ACK_ERR_SECTOR); // Force retry + sendAck(sector, ACK_ERR_SECTOR, currentSectorIndex); // Force retry sectorBufferLen = 0; // Don't hard abort yet, allow retry? // Espressif tools usually retry logic is client side. @@ -281,19 +286,31 @@ static OtaDataCallback dataCallback; void initOtaBleService(NimBLEServer* pServer) { NimBLEService* pService = pServer->createService(OTA_SERVICE_UUID); - // Command (Write + Notify) + // Firmware data (Write No Response + Indicate for ACKs) + pRecvFwChar = pService->createCharacteristic( + OTA_RECV_FW_UUID, + NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::INDICATE + ); + pRecvFwChar->setCallbacks(&dataCallback); + + // Progress (Indicate only; app subscribes) + pProgressChar = pService->createCharacteristic( + OTA_PROGRESS_UUID, + NIMBLE_PROPERTY::INDICATE + ); + + // Command (Write + Indicate) pCommandChar = pService->createCharacteristic( OTA_COMMAND_UUID, - NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY + NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::INDICATE ); pCommandChar->setCallbacks(&cmdCallback); - // Data (Write No Response) - NimBLECharacteristic* pDataChar = pService->createCharacteristic( - OTA_DATA_UUID, - NIMBLE_PROPERTY::WRITE_NR + // Customer (Indicate only; app subscribes) + pCustomerChar = pService->createCharacteristic( + OTA_CUSTOMER_UUID, + NIMBLE_PROPERTY::INDICATE ); - pDataChar->setCallbacks(&dataCallback); pService->start(); } diff --git a/src/sp140/device_settings.cpp b/src/sp140/device_settings.cpp index 33355e4..139b664 100644 --- a/src/sp140/device_settings.cpp +++ b/src/sp140/device_settings.cpp @@ -214,7 +214,7 @@ void parse_serial_commands() { if (!doc["command"].isNull()) { String command = doc["command"].as(); - if (command == "reboot") { + if (command == "reboot" || command == "rbl") { USBSerial.println("Rebooting"); ESP.restart(); return; From 756d6fb262a9dd421f9ad4c8aba423696790b493 Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Mon, 26 Jan 2026 17:23:12 -0600 Subject: [PATCH 08/16] linting --- inc/sp140/device_settings.h | 2 +- src/sp140/ble/ota_service.cpp | 80 +++++++++++++++++------------------ src/sp140/main.cpp | 21 +++++---- 3 files changed, 49 insertions(+), 54 deletions(-) diff --git a/inc/sp140/device_settings.h b/inc/sp140/device_settings.h index 4fc0acc..988ca95 100644 --- a/inc/sp140/device_settings.h +++ b/inc/sp140/device_settings.h @@ -14,4 +14,4 @@ void send_device_data(); bool sanitizeDeviceData(); void debugHardwareConfig(const HardwareConfig& config); -#endif // INC_SP140_DEVICE_SETTINGS_H_ +#endif // INC_SP140_DEVICE_SETTINGS_H_ diff --git a/src/sp140/ble/ota_service.cpp b/src/sp140/ble/ota_service.cpp index 8518992..7544552 100644 --- a/src/sp140/ble/ota_service.cpp +++ b/src/sp140/ble/ota_service.cpp @@ -74,22 +74,22 @@ void sendAck(uint16_t sector, uint16_t status, uint16_t expectedSector = 0) { // Matches esp_ble_ota_cmd_t structure: 20 bytes total void sendCommandResponse(uint16_t ackId, uint16_t status) { if (pCommandChar) { - uint8_t packet[20]; // 2 ID + 16 Payload + 2 CRC - memset(packet, 0, 20); - - packet[0] = CMD_ACK & 0xFF; // 0x03 - packet[1] = (CMD_ACK >> 8) & 0xFF; // 0x00 - + uint8_t packet[20]; // 2 ID + 16 Payload + 2 CRC + memset(packet, 0, 20); + + packet[0] = CMD_ACK & 0xFF; // 0x03 + packet[1] = (CMD_ACK >> 8) & 0xFF; // 0x00 + // Payload (Bytes 2-17): Byte 2-3 = Ack ID, Byte 4-5 = Status packet[2] = ackId & 0xFF; packet[3] = (ackId >> 8) & 0xFF; packet[4] = status & 0xFF; packet[5] = (status >> 8) & 0xFF; - + uint16_t crc = crc16_le(0, packet, 18); packet[18] = crc & 0xFF; packet[19] = (crc >> 8) & 0xFF; - + pCommandChar->setValue(packet, 20); pCommandChar->indicate(); USBSerial.printf("OTA: Sent CMD Response AckId=%d Status=%d\n", ackId, status); @@ -118,7 +118,7 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { } const uint8_t* data = (const uint8_t*)value.data(); - + uint16_t cmdId = data[0] | (data[1] << 8); // Verify CRC @@ -126,26 +126,26 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { uint16_t calcCrc = crc16_le(0, data, 18); if (rxCrc != calcCrc) { USBSerial.printf("OTA Error: CMD CRC Fail Exp %04X Got %04X\n", rxCrc, calcCrc); - sendCommandResponse(cmdId, 0x0001); // Reject (Status 1) + sendCommandResponse(cmdId, 0x0001); // Reject (Status 1) return; } if (cmdId == CMD_START) { USBSerial.println("OTA: CMD_START"); - + if (currentState == ARMED || currentState == ARMED_CRUISING) { USBSerial.println("OTA Blocked: Device ARMED"); - sendCommandResponse(CMD_START, 0x0001); // Reject + sendCommandResponse(CMD_START, 0x0001); // Reject return; } updatePartition = esp_ota_get_next_update_partition(nullptr); if (!updatePartition) { USBSerial.println("OTA Error: No partition"); - sendCommandResponse(CMD_START, 0x0001); + sendCommandResponse(CMD_START, 0x0001); return; } - + // Validate image length (Bytes 2-5 of payload -> data[2]..data[5]) uint32_t imageLen = data[2] | (data[3] << 8) | (data[4] << 16) | (data[5] << 24); if (imageLen > updatePartition->size) { @@ -153,12 +153,12 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { sendCommandResponse(CMD_START, 0x0001); return; } - + esp_err_t err = esp_ota_begin(updatePartition, OTA_SIZE_UNKNOWN, &updateHandle); if (err != ESP_OK) { USBSerial.printf("OTA Error: Begin failed 0x%x\n", err); - sendCommandResponse(CMD_START, 0x0001); - return; + sendCommandResponse(CMD_START, 0x0001); + return; } otaInProgress = true; @@ -166,8 +166,8 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { receivedBytes = 0; sectorBufferLen = 0; currentSectorIndex = 0; - - sendCommandResponse(CMD_START, 0x0000); // Accept + + sendCommandResponse(CMD_START, 0x0000); // Accept } else if (cmdId == CMD_END) { USBSerial.println("OTA: CMD_END"); @@ -175,7 +175,7 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { // Defensive: Verify total bytes received match manifest if (receivedBytes != imageTotalLen) { USBSerial.printf("OTA Error: Size Mismatch Rx:%u Exp:%u\n", receivedBytes, imageTotalLen); - sendCommandResponse(CMD_END, 0x0001); // Fail + sendCommandResponse(CMD_END, 0x0001); // Fail abortOta(); return; } @@ -183,8 +183,8 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { if (esp_ota_end(updateHandle) == ESP_OK) { if (esp_ota_set_boot_partition(updatePartition) == ESP_OK) { USBSerial.println("OTA Success. Restarting..."); - sendCommandResponse(CMD_END, 0x0000); // Success - delay(1000); // Allow BLE flush + sendCommandResponse(CMD_END, 0x0000); // Success + delay(1000); // Allow BLE flush ESP.restart(); return; } else { @@ -193,10 +193,10 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { } else { USBSerial.println("OTA Error: OTA End Failed"); } - sendCommandResponse(CMD_END, 0x0001); // Fail + sendCommandResponse(CMD_END, 0x0001); // Fail abortOta(); } else { - sendCommandResponse(CMD_END, 0x0001); // Not in progress + sendCommandResponse(CMD_END, 0x0001); // Not in progress } } } @@ -205,12 +205,12 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { class OtaDataCallback : public NimBLECharacteristicCallbacks { void onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo) override { if (!otaInProgress) return; - + std::string valStr = pChar->getValue(); size_t len = valStr.length(); const uint8_t* data = (const uint8_t*)valStr.data(); - if (len < 3) return; // Header: Sector(2) + Seq(1) + if (len < 3) return; // Header: Sector(2) + Seq(1) uint16_t sector = data[0] | (data[1] << 8); uint8_t seq = data[2]; @@ -219,7 +219,7 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { if (sector != currentSectorIndex) { USBSerial.printf("OTA Warn: Sector mismatch exp %d got %d\n", currentSectorIndex, sector); - sectorBufferLen = 0; + sectorBufferLen = 0; sendAck(sector, ACK_ERR_SECTOR, currentSectorIndex); return; } @@ -227,9 +227,9 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { if (seq == 0xFF) { // Last packet: Payload is Data + CRC16(2) if (payloadLen < 2) return; - + size_t actualDataLen = payloadLen - 2; - + if (sectorBufferLen + actualDataLen > sizeof(sectorBuffer)) { sendAck(sector, ACK_ERR_LEN); sectorBufferLen = 0; @@ -252,10 +252,10 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { sectorBufferLen = 0; } else { USBSerial.printf("OTA Error: Write failed 0x%x\n", err); - sendAck(sector, ACK_ERR_SECTOR, currentSectorIndex); // Force retry + sendAck(sector, ACK_ERR_SECTOR, currentSectorIndex); // Force retry sectorBufferLen = 0; - // Don't hard abort yet, allow retry? - // Espressif tools usually retry logic is client side. + // Don't hard abort yet, allow retry? + // Espressif tools usually retry logic is client side. // If we return ERR_SECTOR, client re-sends sector. } } else { @@ -270,7 +270,7 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { USBSerial.println("OTA Error: Buffer overflow"); sectorBufferLen = 0; sendAck(sector, ACK_ERR_LEN); - return; + return; } memcpy(sectorBuffer + sectorBufferLen, payload, payloadLen); sectorBufferLen += payloadLen; @@ -281,7 +281,7 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { static OtaCommandCallback cmdCallback; static OtaDataCallback dataCallback; -} // namespace +} // namespace void initOtaBleService(NimBLEServer* pServer) { NimBLEService* pService = pServer->createService(OTA_SERVICE_UUID); @@ -289,28 +289,24 @@ void initOtaBleService(NimBLEServer* pServer) { // Firmware data (Write No Response + Indicate for ACKs) pRecvFwChar = pService->createCharacteristic( OTA_RECV_FW_UUID, - NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::INDICATE - ); + NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::INDICATE); pRecvFwChar->setCallbacks(&dataCallback); // Progress (Indicate only; app subscribes) pProgressChar = pService->createCharacteristic( OTA_PROGRESS_UUID, - NIMBLE_PROPERTY::INDICATE - ); + NIMBLE_PROPERTY::INDICATE); // Command (Write + Indicate) pCommandChar = pService->createCharacteristic( OTA_COMMAND_UUID, - NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::INDICATE - ); + NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::INDICATE); pCommandChar->setCallbacks(&cmdCallback); // Customer (Indicate only; app subscribes) pCustomerChar = pService->createCharacteristic( OTA_CUSTOMER_UUID, - NIMBLE_PROPERTY::INDICATE - ); + NIMBLE_PROPERTY::INDICATE); pService->start(); } diff --git a/src/sp140/main.cpp b/src/sp140/main.cpp index b1f8eeb..2d05db2 100644 --- a/src/sp140/main.cpp +++ b/src/sp140/main.cpp @@ -539,7 +539,7 @@ void uiTask(void *pvParameters) { // BMS task: ~10 Hz polling and unified battery update void bmsTask(void *pvParameters) { TickType_t lastWake = xTaskGetTickCount(); - const TickType_t bmsTicks = pdMS_TO_TICKS(100); // 10 Hz + const TickType_t bmsTicks = pdMS_TO_TICKS(100); // 10 Hz for (;;) { #ifdef SCREEN_DEBUG float altitude = 0; @@ -618,7 +618,7 @@ void setupWatchdog() { #ifndef OPENPPG_DEBUG // Initialize Task Watchdog ESP_ERROR_CHECK(esp_task_wdt_init(3000, true)); // 3 second timeout, panic on timeout -#endif // OPENPPG_DEBUG +#endif // OPENPPG_DEBUG } #define TAG "OpenPPG" @@ -906,9 +906,7 @@ void buttonHandlerTask(void* parameter) { buttonPressStartTime = currentTime; // Reset to prevent immediate cruise activation } } - } - // Only handle other button actions if we're not in an arm sequence - else if (buttonPressed) { + } else if (buttonPressed) { // Only handle other button actions if we're not in an arm sequence uint32_t currentHoldTime = currentTime - buttonPressStartTime; // Handle performance mode (only when disarmed and held long enough) @@ -917,9 +915,8 @@ void buttonHandlerTask(void* parameter) { perfModeSwitch(); buttonPressed = false; buttonPressStartTime = currentTime; - } - // Handle cruise control (when armed or cruising and held long enough) - else if ((currentState == ARMED || currentState == ARMED_CRUISING) && currentHoldTime >= CRUISE_HOLD_TIME_MS) { + } else if ((currentState == ARMED || currentState == ARMED_CRUISING) && currentHoldTime >= CRUISE_HOLD_TIME_MS) { + // Handle cruise control (when armed or cruising and held long enough) USBSerial.println("Cruise control button activated"); toggleCruise(); buttonPressed = false; @@ -1195,7 +1192,7 @@ void afterCruiseStart() { USBSerial.println("Failed to queue initial cruise throttle PWM"); } - //pulseVibeMotor(); + // pulseVibeMotor(); } void afterCruiseEnd() { @@ -1208,7 +1205,7 @@ void afterCruiseEnd() { throttleFilterReset(currentPwmVal); cruisedPotVal = 0; - //pulseVibeMotor(); + // pulseVibeMotor(); } void playCruiseSound() { @@ -1229,7 +1226,9 @@ void audioTask(void* parameter) { for (int i = 0; i < request.size; i++) { startTone(request.notes[i]); TickType_t delayTicks = pdMS_TO_TICKS(request.duration); - if (delayTicks == 0) { delayTicks = 1; } // Ensure non-zero delay + if (delayTicks == 0) { + delayTicks = 1; + } // Ensure non-zero delay vTaskDelayUntil(&nextWakeTime, delayTicks); } stopTone(); From 17f3d0026a31d8c29eea2c512d9586343a4f5956 Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Tue, 27 Jan 2026 10:42:59 -0600 Subject: [PATCH 09/16] Remove extra internal logging --- sdkconfig.OpenPPG-CESP32S3-CAN-SP140 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sdkconfig.OpenPPG-CESP32S3-CAN-SP140 b/sdkconfig.OpenPPG-CESP32S3-CAN-SP140 index 16e3198..6e121b6 100644 --- a/sdkconfig.OpenPPG-CESP32S3-CAN-SP140 +++ b/sdkconfig.OpenPPG-CESP32S3-CAN-SP140 @@ -1118,16 +1118,16 @@ CONFIG_HEAP_TRACING_OFF=y # Log output # # CONFIG_LOG_DEFAULT_LEVEL_NONE is not set -# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +CONFIG_LOG_DEFAULT_LEVEL_ERROR=y # CONFIG_LOG_DEFAULT_LEVEL_WARN is not set -CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_INFO is not set # CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set # CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set -CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_DEFAULT_LEVEL=1 CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y # CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set # CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set -CONFIG_LOG_MAXIMUM_LEVEL=3 +CONFIG_LOG_MAXIMUM_LEVEL=1 CONFIG_LOG_COLORS=y CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y # CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set From d2fbb5be7298b872598dd7b681566d18b7515730 Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Tue, 27 Jan 2026 20:29:21 -0600 Subject: [PATCH 10/16] Switch OTA CRC to CRC16-CCITT for compatibility Replaces the previous CRC16 implementation with CRC16-CCITT (poly 0x1021, init 0) in ota_service.cpp to match the Espressif Android app. Updates all relevant CRC checks and calculations to use the new function. --- sdkconfig.OpenPPG-CESP32S3-CAN-SP140 | 2 ++ src/sp140/ble/ota_service.cpp | 26 +++++++++++++++----------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/sdkconfig.OpenPPG-CESP32S3-CAN-SP140 b/sdkconfig.OpenPPG-CESP32S3-CAN-SP140 index 6e121b6..dec50b0 100644 --- a/sdkconfig.OpenPPG-CESP32S3-CAN-SP140 +++ b/sdkconfig.OpenPPG-CESP32S3-CAN-SP140 @@ -1125,6 +1125,8 @@ CONFIG_LOG_DEFAULT_LEVEL_ERROR=y # CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set CONFIG_LOG_DEFAULT_LEVEL=1 CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +# CONFIG_LOG_MAXIMUM_LEVEL_WARN is not set +# CONFIG_LOG_MAXIMUM_LEVEL_INFO is not set # CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set # CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set CONFIG_LOG_MAXIMUM_LEVEL=1 diff --git a/src/sp140/ble/ota_service.cpp b/src/sp140/ble/ota_service.cpp index 7544552..f54f82c 100644 --- a/src/sp140/ble/ota_service.cpp +++ b/src/sp140/ble/ota_service.cpp @@ -40,16 +40,20 @@ NimBLECharacteristic* pProgressChar = nullptr; NimBLECharacteristic* pCommandChar = nullptr; NimBLECharacteristic* pCustomerChar = nullptr; -// CRC16 Implementation (Polynomial 0x8005, reversed for LE) -uint16_t crc16_le(uint16_t crc, const uint8_t *buffer, size_t len) { - while (len--) { - crc ^= *buffer++; - for (int i = 0; i < 8; i++) { - if (crc & 1) crc = (crc >> 1) ^ 0xA001; - else crc = (crc >> 1); +// CRC16-CCITT (poly 0x1021, init 0) to match Espressif Android app +uint16_t crc16_ccitt(const uint8_t* buffer, size_t len) { + uint16_t crc16 = 0; + for (size_t i = 0; i < len; ++i) { + crc16 ^= static_cast(buffer[i]) << 8; + for (int bit = 0; bit < 8; ++bit) { + if (crc16 & 0x8000) { + crc16 = static_cast((crc16 << 1) ^ 0x1021); + } else { + crc16 = static_cast(crc16 << 1); + } } } - return crc; + return crc16; } void sendAck(uint16_t sector, uint16_t status, uint16_t expectedSector = 0) { @@ -86,7 +90,7 @@ void sendCommandResponse(uint16_t ackId, uint16_t status) { packet[4] = status & 0xFF; packet[5] = (status >> 8) & 0xFF; - uint16_t crc = crc16_le(0, packet, 18); + uint16_t crc = crc16_ccitt(packet, 18); packet[18] = crc & 0xFF; packet[19] = (crc >> 8) & 0xFF; @@ -123,7 +127,7 @@ class OtaCommandCallback : public NimBLECharacteristicCallbacks { // Verify CRC uint16_t rxCrc = data[18] | (data[19] << 8); - uint16_t calcCrc = crc16_le(0, data, 18); + uint16_t calcCrc = crc16_ccitt(data, 18); if (rxCrc != calcCrc) { USBSerial.printf("OTA Error: CMD CRC Fail Exp %04X Got %04X\n", rxCrc, calcCrc); sendCommandResponse(cmdId, 0x0001); // Reject (Status 1) @@ -241,7 +245,7 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { // Verify CRC uint16_t rxCrc = payload[actualDataLen] | (payload[actualDataLen + 1] << 8); - uint16_t calcCrc = crc16_le(0, sectorBuffer, sectorBufferLen); + uint16_t calcCrc = crc16_ccitt(sectorBuffer, sectorBufferLen); if (rxCrc == calcCrc) { esp_err_t err = esp_ota_write(updateHandle, sectorBuffer, sectorBufferLen); From 8dcd3f51887312ed20771ce29b67e03c6b9b8627 Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Wed, 28 Jan 2026 07:54:08 -0600 Subject: [PATCH 11/16] Improve OTA BLE service and LVGL display handling Switched OTA BLE characteristics to use notify instead of indicate for ACKs and command responses, and added NOTIFY property to relevant characteristics. Added packet count logging and sector write progress in OTA service. In LVGL flush callback, ensured flush completion is signaled on SPI timeout to prevent deadlock, and moved CS pin selection after SPI bus acquisition. Added boot and running partition info logging during setup. --- src/sp140/ble/ota_service.cpp | 26 ++++++++++++++++++++++---- src/sp140/lvgl/lvgl_core.cpp | 10 ++++++---- src/sp140/main.cpp | 7 +++++++ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/sp140/ble/ota_service.cpp b/src/sp140/ble/ota_service.cpp index f54f82c..9e70e44 100644 --- a/src/sp140/ble/ota_service.cpp +++ b/src/sp140/ble/ota_service.cpp @@ -33,6 +33,7 @@ uint8_t sectorBuffer[4096]; uint16_t sectorBufferLen = 0; uint16_t currentSectorIndex = 0; size_t receivedBytes = 0; +uint32_t packetCount = 0; // OTA characteristics NimBLECharacteristic* pRecvFwChar = nullptr; @@ -69,7 +70,7 @@ void sendAck(uint16_t sector, uint16_t status, uint16_t expectedSector = 0) { packet[5] = (expectedSector >> 8) & 0xFF; pRecvFwChar->setValue(packet, 6); - pRecvFwChar->indicate(); + pRecvFwChar->notify(); USBSerial.printf("OTA: Sent ACK Sector=%d Status=%d\n", sector, status); } } @@ -95,7 +96,7 @@ void sendCommandResponse(uint16_t ackId, uint16_t status) { packet[19] = (crc >> 8) & 0xFF; pCommandChar->setValue(packet, 20); - pCommandChar->indicate(); + pCommandChar->notify(); USBSerial.printf("OTA: Sent CMD Response AckId=%d Status=%d\n", ackId, status); } } @@ -216,6 +217,13 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { if (len < 3) return; // Header: Sector(2) + Seq(1) + packetCount++; + if (packetCount % 100 == 0) { + USBSerial.printf("OTA: Received %lu packets (sector %u)\n", + static_cast(packetCount), + static_cast(currentSectorIndex)); + } + uint16_t sector = data[0] | (data[1] << 8); uint8_t seq = data[2]; const uint8_t* payload = data + 3; @@ -252,6 +260,9 @@ class OtaDataCallback : public NimBLECharacteristicCallbacks { if (err == ESP_OK) { receivedBytes += sectorBufferLen; sendAck(sector, ACK_SUCCESS); + USBSerial.printf("OTA: Sector %u written (%u bytes total)\n", + static_cast(currentSectorIndex), + static_cast(receivedBytes)); currentSectorIndex++; sectorBufferLen = 0; } else { @@ -293,23 +304,30 @@ void initOtaBleService(NimBLEServer* pServer) { // Firmware data (Write No Response + Indicate for ACKs) pRecvFwChar = pService->createCharacteristic( OTA_RECV_FW_UUID, - NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::INDICATE); + NIMBLE_PROPERTY::WRITE | + NIMBLE_PROPERTY::WRITE_NR | + NIMBLE_PROPERTY::NOTIFY | + NIMBLE_PROPERTY::INDICATE); pRecvFwChar->setCallbacks(&dataCallback); // Progress (Indicate only; app subscribes) pProgressChar = pService->createCharacteristic( OTA_PROGRESS_UUID, + NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::INDICATE); // Command (Write + Indicate) pCommandChar = pService->createCharacteristic( OTA_COMMAND_UUID, - NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::INDICATE); + NIMBLE_PROPERTY::WRITE | + NIMBLE_PROPERTY::NOTIFY | + NIMBLE_PROPERTY::INDICATE); pCommandChar->setCallbacks(&cmdCallback); // Customer (Indicate only; app subscribes) pCustomerChar = pService->createCharacteristic( OTA_CUSTOMER_UUID, + NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::INDICATE); pService->start(); diff --git a/src/sp140/lvgl/lvgl_core.cpp b/src/sp140/lvgl/lvgl_core.cpp index 9c713d4..24f927f 100644 --- a/src/sp140/lvgl/lvgl_core.cpp +++ b/src/sp140/lvgl/lvgl_core.cpp @@ -77,9 +77,6 @@ void setupLvglDisplay( // Optimize the flush callback to minimize SPI transfers // CS pin management is handled here where actual SPI communication occurs void lvgl_flush_cb(lv_disp_drv_t* disp, const lv_area_t* area, lv_color_t* color_p) { - // Make sure display CS is selected - digitalWrite(displayCS, LOW); - uint32_t w = (area->x2 - area->x1 + 1); uint32_t h = (area->y2 - area->y1 + 1); @@ -89,9 +86,14 @@ void lvgl_flush_cb(lv_disp_drv_t* disp, const lv_area_t* area, lv_color_t* color if (xSemaphoreTake(spiBusMutex, pdMS_TO_TICKS(200)) != pdTRUE) { // SPI bus timeout - BMS might be doing long operation, skip display flush USBSerial.println("[DISPLAY] SPI bus timeout - skipping display flush"); - return; // Skip this display update rather than hang + // Must still signal LVGL that flush is done to avoid deadlock + lv_disp_flush_ready(disp); + return; } } + + // Make sure display CS is selected only after SPI bus is acquired + digitalWrite(displayCS, LOW); tft_driver->startWrite(); tft_driver->setAddrWindow(area->x1, area->y1, w, h); diff --git a/src/sp140/main.cpp b/src/sp140/main.cpp index 2d05db2..911cbd5 100644 --- a/src/sp140/main.cpp +++ b/src/sp140/main.cpp @@ -647,6 +647,13 @@ void setup() { refreshDeviceData(); printBootMessage(); + const esp_partition_t* running = esp_ota_get_running_partition(); + const esp_partition_t* boot = esp_ota_get_boot_partition(); + if (running != nullptr && boot != nullptr) { + USBSerial.printf("OTA: Running partition %s @ 0x%06lx, boot %s @ 0x%06lx\n", + running->label, (unsigned long)running->address, + boot->label, (unsigned long)boot->address); + } setupBarometer(); loadHardwareConfig(); From 266f5ec15f687c6fc951183e0211eaef6d434695 Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Wed, 28 Jan 2026 12:18:35 -0600 Subject: [PATCH 12/16] Update main.cpp --- src/sp140/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sp140/main.cpp b/src/sp140/main.cpp index 911cbd5..bf4ca3e 100644 --- a/src/sp140/main.cpp +++ b/src/sp140/main.cpp @@ -725,6 +725,7 @@ void setup() { initSimpleMonitor(); setupTasks(); // Create all tasks after queues and BLE are initialized + vTaskDelay(pdMS_TO_TICKS(50)); // Let tasks settle before splash screen pulseVibeMotor(); if (digitalRead(board_config.button_top) == LOW) { // LOW means pressed since it's INPUT_PULLUP From fa65b02b9f44b9f927d68765ed867df58bdad3b7 Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Wed, 28 Jan 2026 12:24:57 -0600 Subject: [PATCH 13/16] Remove unused alt_wire parameter from setupAltimeter The setupAltimeter function no longer requires the alt_wire parameter, so it has been removed from the function signature and all call sites. This simplifies the interface and eliminates unused code. --- inc/sp140/altimeter.h | 4 ++-- src/sp140/altimeter.cpp | 8 +++----- src/sp140/main.cpp | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/inc/sp140/altimeter.h b/inc/sp140/altimeter.h index aee7c86..b78ea0d 100644 --- a/inc/sp140/altimeter.h +++ b/inc/sp140/altimeter.h @@ -10,8 +10,8 @@ #define VARIO_BUFFER_SIZE 25 // Number of samples to average for vertical speed #define MAX_VERTICAL_SPEED 250.0f // Maximum vertical speed to display (m/s) -// Set up the barometer -bool setupAltimeter(bool alt_wire = false); +// Set up the barometer +bool setupAltimeter(); // Get the altitude (in meters) float getAltitude(const STR_DEVICE_DATA_140_V1& deviceData); diff --git a/src/sp140/altimeter.cpp b/src/sp140/altimeter.cpp index 5fa7f2a..fd2e33d 100644 --- a/src/sp140/altimeter.cpp +++ b/src/sp140/altimeter.cpp @@ -75,11 +75,9 @@ float getBaroPressure() { return __FLT_MIN__; // Return a very small number if BMP is not present } -// Start the bmp3XX sensor -bool setupAltimeter(bool altWire) { - TwoWire* wire = &Wire; - - // pull down pin 40 to high to set the address +// Start the bmp3XX sensor +bool setupAltimeter() { + // pull down pin 40 to high to set the address pinMode(40, OUTPUT); digitalWrite(40, HIGH); if (!bmp.begin_I2C(BMP3XX_DEFAULT_ADDRESS, &Wire)) return false; diff --git a/src/sp140/main.cpp b/src/sp140/main.cpp index bf4ca3e..acec6fc 100644 --- a/src/sp140/main.cpp +++ b/src/sp140/main.cpp @@ -831,7 +831,7 @@ void setup140() { const int SDA_PIN = 44; const int SCL_PIN = 41; Wire.setPins(SDA_PIN, SCL_PIN); - if (!setupAltimeter(board_config.alt_wire)) { + if (!setupAltimeter()) { USBSerial.println("Error initializing BMP3xx barometer"); } if (ENABLE_VIBE) { From f0b0b5a4240923cbf96a6a279c5087427f3e338a Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Wed, 28 Jan 2026 12:50:58 -0600 Subject: [PATCH 14/16] Defer BLE advertising until after splash screen BLE advertising is now started after the splash screen completes, rather than during BLE setup. This change ensures the device does not advertise until the UI is ready, improving startup flow and user experience. Added log messages to clarify advertising state. --- src/sp140/ble/ble_core.cpp | 5 ++--- src/sp140/main.cpp | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/sp140/ble/ble_core.cpp b/src/sp140/ble/ble_core.cpp index 4c108e8..4da449d 100644 --- a/src/sp140/ble/ble_core.cpp +++ b/src/sp140/ble/ble_core.cpp @@ -66,10 +66,9 @@ void setupBLE() { advertising->addServiceUUID(NimBLEUUID(CONTROLLER_SERVICE_UUID)); advertising->addServiceUUID(NimBLEUUID(OTA_SERVICE_UUID)); advertising->enableScanResponse(true); - advertising->start(); + // Note: Advertising is deferred until after splash screen - USBSerial.println("BLE device ready"); - USBSerial.println("Waiting for a client connection..."); + USBSerial.println("BLE device ready (advertising deferred)"); } void restartBLEAdvertising() { diff --git a/src/sp140/main.cpp b/src/sp140/main.cpp index acec6fc..9e15c3d 100644 --- a/src/sp140/main.cpp +++ b/src/sp140/main.cpp @@ -116,6 +116,9 @@ SemaphoreHandle_t eepromSemaphore; SemaphoreHandle_t stateMutex; SemaphoreHandle_t lvglMutex; +// Startup synchronization - tasks wait for this before starting main loops +SemaphoreHandle_t startupSyncSemaphore = NULL; + // BLE state propagation struct BLEStateUpdate { uint8_t state; @@ -526,6 +529,13 @@ void monitoringTask(void *pvParameters) { // UI task: fixed 25 Hz refresh and snapshot publish void uiTask(void *pvParameters) { + // Wait for setup to complete before starting + if (startupSyncSemaphore != NULL) { + xSemaphoreTake(startupSyncSemaphore, portMAX_DELAY); + // Give it back so other tasks can also take it + xSemaphoreGive(startupSyncSemaphore); + } + TickType_t lastWake = xTaskGetTickCount(); const TickType_t uiTicks = pdMS_TO_TICKS(50); // 20 Hz for (;;) { @@ -645,6 +655,12 @@ void setup() { USBSerial.println("Error creating LVGL mutex"); } + // Create startup sync semaphore - tasks wait for this before running + startupSyncSemaphore = xSemaphoreCreateBinary(); + if (startupSyncSemaphore == NULL) { + USBSerial.println("Error creating startup sync semaphore"); + } + refreshDeviceData(); printBootMessage(); const esp_partition_t* running = esp_ota_get_running_partition(); @@ -725,7 +741,6 @@ void setup() { initSimpleMonitor(); setupTasks(); // Create all tasks after queues and BLE are initialized - vTaskDelay(pdMS_TO_TICKS(50)); // Let tasks settle before splash screen pulseVibeMotor(); if (digitalRead(board_config.button_top) == LOW) { // LOW means pressed since it's INPUT_PULLUP @@ -766,6 +781,14 @@ void setup() { send_device_data(); // Signal that the UI is ready for updates from tasks uiReady = true; + // Signal all tasks that setup is complete - they can now start their main loops + if (startupSyncSemaphore != NULL) { + xSemaphoreGive(startupSyncSemaphore); + USBSerial.println("Tasks released - startup complete"); + } + // Start BLE advertising now that splash is complete + restartBLEAdvertising(); + USBSerial.println("BLE advertising started"); // Simple instrumentation to detect UI/BMS latency USBSerial.println("Init complete. UI + BMS loop running"); From e77322eece8545aee416c8745e972af44602a0c9 Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Wed, 28 Jan 2026 13:19:32 -0600 Subject: [PATCH 15/16] Refactor boot sequence and RTOS setup for clarity Reorganize the main setup() into explicit boot phases, separating RTOS primitive creation, hardware initialization, UI setup, and task creation. Remove startup synchronization semaphores and flags in favor of a deterministic, phased boot. Move all queue and mutex creation to dedicated functions called before any tasks are started. Simplify UI task startup and ensure all dependencies are initialized before tasks run. --- src/sp140/main.cpp | 390 +++++++++++++++++++++++++-------------------- 1 file changed, 215 insertions(+), 175 deletions(-) diff --git a/src/sp140/main.cpp b/src/sp140/main.cpp index 9e15c3d..9f564df 100644 --- a/src/sp140/main.cpp +++ b/src/sp140/main.cpp @@ -54,9 +54,9 @@ bool armSystem(); void afterCruiseEnd(); void afterCruiseStart(); void pushTelemetrySnapshot(); -void initButtons(); -void setup140(); void setupTasks(); +void createAllSyncPrimitives(); +void createAllQueues(); void audioTask(void* parameter); void updateESCBLETask(void* parameter); void webSerialTask(void* parameter); @@ -109,16 +109,10 @@ uint32_t led_color = LED_RED; // current LED color // Global variable for device state volatile DeviceState currentState = DISARMED; -// Add volatile bool flag to control UI drawing start -volatile bool uiReady = false; - SemaphoreHandle_t eepromSemaphore; SemaphoreHandle_t stateMutex; SemaphoreHandle_t lvglMutex; -// Startup synchronization - tasks wait for this before starting main loops -SemaphoreHandle_t startupSyncSemaphore = NULL; - // BLE state propagation struct BLEStateUpdate { uint8_t state; @@ -433,8 +427,8 @@ void updateBLETask(void *pvParameters) { } void refreshDisplay() { - // Prevent drawing until setup() signals UI is ready - if (!uiReady || main_screen == NULL) { + // Guard against calls before main_screen is set up + if (main_screen == NULL) { return; } @@ -527,15 +521,8 @@ void monitoringTask(void *pvParameters) { } } -// UI task: fixed 25 Hz refresh and snapshot publish +// UI task: fixed 20 Hz refresh and snapshot publish void uiTask(void *pvParameters) { - // Wait for setup to complete before starting - if (startupSyncSemaphore != NULL) { - xSemaphoreTake(startupSyncSemaphore, portMAX_DELAY); - // Give it back so other tasks can also take it - xSemaphoreGive(startupSyncSemaphore); - } - TickType_t lastWake = xTaskGetTickCount(); const TickType_t uiTicks = pdMS_TO_TICKS(50); // 20 Hz for (;;) { @@ -633,247 +620,300 @@ void setupWatchdog() { #define TAG "OpenPPG" +// ============================================================================= +// BOOT PHASE HELPER FUNCTIONS +// ============================================================================= /** - * Initializes the necessary components and configurations for the device setup. - * This function is called once at the beginning of the program execution. + * Phase 2a: Create all RTOS mutexes and semaphores + * Must be called before any tasks are created */ +void createAllSyncPrimitives() { + USBSerial.println("Creating sync primitives..."); -void setup() { - USBSerial.begin(115200); // This is for debug output and WebSerial - USBSerial.print("Build date/time: "); - USBSerial.println(buildDate); - - // Pull CSB (pin 42) high to activate I2C mode - // temporary fix TODO remove - digitalWrite(42, HIGH); - pinMode(42, OUTPUT); - - // Initialize LVGL mutex before anything else + // LVGL display mutex - protects all LVGL operations lvglMutex = xSemaphoreCreateMutex(); if (lvglMutex == NULL) { USBSerial.println("Error creating LVGL mutex"); } - // Create startup sync semaphore - tasks wait for this before running - startupSyncSemaphore = xSemaphoreCreateBinary(); - if (startupSyncSemaphore == NULL) { - USBSerial.println("Error creating startup sync semaphore"); + // State mutex - protects device state transitions + stateMutex = xSemaphoreCreateMutex(); + if (stateMutex == NULL) { + USBSerial.println("Error creating state mutex"); } - refreshDeviceData(); - printBootMessage(); - const esp_partition_t* running = esp_ota_get_running_partition(); - const esp_partition_t* boot = esp_ota_get_boot_partition(); - if (running != nullptr && boot != nullptr) { - USBSerial.printf("OTA: Running partition %s @ 0x%06lx, boot %s @ 0x%06lx\n", - running->label, (unsigned long)running->address, - boot->label, (unsigned long)boot->address); + // EEPROM semaphore - guards Preferences writes + eepromSemaphore = xSemaphoreCreateBinary(); + if (eepromSemaphore == NULL) { + USBSerial.println("Error creating EEPROM semaphore"); + } else { + xSemaphoreGive(eepromSemaphore); // Start in "available" state } - setupBarometer(); - - loadHardwareConfig(); - setupLED(); // Defaults to RED - setupAnalogRead(); - initButtons(); - setupWatchdog(); - setup140(); - - setLEDColor(LED_YELLOW); // Booting up - - // First initialize the shared SPI bus - setupSPI(board_config); - - // Then setup the display - use LVGL display instead of the old one - // Pass hardcoded pin values for DC and RST - setupLvglDisplay(deviceData, board_config.tft_dc, board_config.tft_rst, hardwareSPI); - - // Initialise alert display aggregation & UI - initAlertDisplay(); - - #ifndef SCREEN_DEBUG - // Pass the hardware SPI instance to the BMS_CAN initialization - initBMSCAN(hardwareSPI); - #endif +} - initESC(); - eepromSemaphore = xSemaphoreCreateBinary(); - xSemaphoreGive(eepromSemaphore); - stateMutex = xSemaphoreCreateMutex(); - setESCThrottle(ESC_DISARMED_PWM); - initVibeMotor(); +/** + * Phase 2b: Create all RTOS queues + * Must be called before any tasks are created + */ +void createAllQueues() { + USBSerial.println("Creating queues..."); - // Create all queues first + // BMS telemetry queue (size 1, overwrite semantics) bmsTelemetryQueue = xQueueCreate(1, sizeof(STR_BMS_TELEMETRY_140)); if (bmsTelemetryQueue == NULL) { USBSerial.println("Error creating BMS telemetry queue"); } + // Throttle update queue throttleUpdateQueue = xQueueCreate(1, sizeof(uint16_t)); if (throttleUpdateQueue == NULL) { USBSerial.println("Error creating throttle update queue"); } + // ESC telemetry queue escTelemetryQueue = xQueueCreate(1, sizeof(STR_ESC_TELEMETRY_140)); if (escTelemetryQueue == NULL) { USBSerial.println("Error creating ESC telemetry queue"); } + // BLE state queue bleStateQueue = xQueueCreate(5, sizeof(BLEStateUpdate)); if (bleStateQueue == NULL) { USBSerial.println("Error creating BLE state queue"); } + // Device state queue deviceStateQueue = xQueueCreate(1, sizeof(uint8_t)); if (deviceStateQueue == NULL) { USBSerial.println("Error creating device state queue"); } - // Snapshot queue for monitoring (size 1) + // Telemetry snapshot queue for monitoring telemetrySnapshotQueue = xQueueCreate(1, sizeof(TelemetrySnapshot)); if (telemetrySnapshotQueue == NULL) { USBSerial.println("Error creating telemetry snapshot queue"); } - setupBLE(); + // Melody queue for audio task - MUST be created before audioTask + melodyQueue = xQueueCreate(5, sizeof(MelodyRequest)); + if (melodyQueue == NULL) { + USBSerial.println("Error creating melody queue"); + } +} - // Initialize the simple monitoring system (but keep it disabled initially) - initSimpleMonitor(); +/** + * Phase 6: Create all FreeRTOS tasks + * Called AFTER all hardware, UI, and services are initialized + * Tasks can start running immediately - no sync semaphores needed + */ +void setupTasks() { + USBSerial.println("Creating tasks..."); + + // Core 0 tasks (safety-critical, real-time) + xTaskCreatePinnedToCore(throttleTask, "throttle", 4352, NULL, 3, &throttleTaskHandle, 0); + xTaskCreatePinnedToCore(watchdogTask, "watchdog", 1536, NULL, 3, &watchdogTaskHandle, 0); + xTaskCreatePinnedToCore(buttonHandlerTask, "ButtonHandler", 4096, NULL, 2, &buttonTaskHandle, 0); + + // Core 1 tasks (UI, communications) + xTaskCreatePinnedToCore(uiTask, "UI", 5888, NULL, 2, &uiTaskHandle, 1); + xTaskCreatePinnedToCore(bmsTask, "BMS", 2304, NULL, 2, &bmsTaskHandle, 1); + xTaskCreatePinnedToCore(bleStateUpdateTask, "BLEStateUpdate", 8192, NULL, 1, &bleStateUpdateTaskHandle, 1); + xTaskCreatePinnedToCore(audioTask, "Audio", 1536, NULL, 1, &audioTaskHandle, 1); + xTaskCreatePinnedToCore(vibeTask, "Vibration", 1536, NULL, 2, &vibeTaskHandle, 1); + + // Unpinned tasks (can run on either core) + xTaskCreate(blinkLEDTask, "blinkLed", 2560, NULL, 1, &blinkLEDTaskHandle); + xTaskCreate(updateBLETask, "BLE Update Task", 8192, NULL, 1, NULL); + xTaskCreate(deviceStateUpdateTask, "State Update Task", 2048, NULL, 1, &deviceStateUpdateTaskHandle); + xTaskCreate(updateESCBLETask, "ESC BLE Update Task", 8192, NULL, 1, NULL); + xTaskCreate(webSerialTask, "WebSerial", 3072, NULL, 1, &webSerialTaskHandle); + xTaskCreate(monitoringTask, "Monitoring", 4864, NULL, 1, &monitoringTaskHandle); + + #ifdef OPENPPG_DEBUG + // Create periodic stack watermark logger (low priority) + xTaskCreatePinnedToCore(stackWatermarkLoggerTask, "StackLogger", 3072, NULL, 1, &stackLoggerTaskHandle, 1); + #endif + + USBSerial.println("All tasks created"); +} + +// ============================================================================= +// MAIN SETUP FUNCTION - PHASED BOOT SEQUENCE +// ============================================================================= + +/** + * Initializes the device in deterministic phases. + * No tasks are created until all their dependencies exist. + */ +void setup() { + // ========================================================================= + // PHASE 1: Serial and Early Config + // ========================================================================= + USBSerial.begin(115200); + USBSerial.print("Build date/time: "); + USBSerial.println(buildDate); + + // Load device config from EEPROM first - may contain pin mappings + refreshDeviceData(); + printBootMessage(); + + // Log OTA partition info + const esp_partition_t* running = esp_ota_get_running_partition(); + const esp_partition_t* boot = esp_ota_get_boot_partition(); + if (running != nullptr && boot != nullptr) { + USBSerial.printf("OTA: Running partition %s @ 0x%06lx, boot %s @ 0x%06lx\n", + running->label, (unsigned long)running->address, + boot->label, (unsigned long)boot->address); + } - setupTasks(); // Create all tasks after queues and BLE are initialized + // ========================================================================= + // PHASE 2: Create ALL RTOS Primitives (before any tasks) + // ========================================================================= + createAllSyncPrimitives(); + createAllQueues(); + // ========================================================================= + // PHASE 3: Hardware Initialization + // ========================================================================= + USBSerial.println("Initializing hardware..."); + + // Temporary fix for BMP3xx I2C mode - TODO remove + digitalWrite(42, HIGH); + pinMode(42, OUTPUT); + + // Load board-specific hardware config + loadHardwareConfig(); + + // I2C bus setup for altimeter + const int SDA_PIN = 44; + const int SCL_PIN = 41; + Wire.setPins(SDA_PIN, SCL_PIN); + + // Initialize peripherals + setupBarometer(); + if (!setupAltimeter()) { + USBSerial.println("Error initializing BMP3xx barometer"); + } + + setupLED(); // Defaults to RED + setupAnalogRead(); + pinMode(board_config.button_top, INPUT_PULLUP); // Button GPIO only, task created later + setupWatchdog(); + + // Buzzer and vibration motor + if (ENABLE_BUZZ) { + initBuzz(); + } + if (ENABLE_VIBE) { + initVibeMotor(); + } + + setLEDColor(LED_YELLOW); // Indicate boot in progress + + // SPI bus (shared between display and BMS CAN) + setupSPI(board_config); + + // Display initialization + setupLvglDisplay(deviceData, board_config.tft_dc, board_config.tft_rst, hardwareSPI); + initAlertDisplay(); + + // BMS CAN interface + #ifndef SCREEN_DEBUG + initBMSCAN(hardwareSPI); + #endif + + // ESC interface + initESC(); + setESCThrottle(ESC_DISARMED_PWM); + + // ========================================================================= + // PHASE 4: UI Startup (blocking - no tasks running yet) + // ========================================================================= + USBSerial.println("Starting UI..."); + + // Haptic feedback that boot is progressing pulseVibeMotor(); - if (digitalRead(board_config.button_top) == LOW) { // LOW means pressed since it's INPUT_PULLUP + + // Check for performance mode activation (button held during boot) + if (digitalRead(board_config.button_top) == LOW) { perfModeSwitch(); } + setLEDColor(LED_GREEN); - // Show LVGL splash screen + // Show splash screen (blocking) if (xSemaphoreTake(lvglMutex, portMAX_DELAY) == pdTRUE) { displayLvglSplash(deviceData, 2000); - // Don't release mutex here yet + // Keep mutex held through main screen setup } else { USBSerial.println("Failed to acquire LVGL mutex for splash"); - // If we failed mutex, maybe skip main screen setup? Or attempt anyway? - // Let's assume splash failed but we try to proceed. } - // Setup the main screen UI elements AFTER the splash - USBSerial.println("Setting up main screen after splash"); - if (main_screen == NULL) { // Check if it wasn't somehow created already + // Setup main screen after splash + USBSerial.println("Setting up main screen..."); + if (main_screen == NULL) { setupMainScreen(deviceData.theme == 1); } - // Explicitly load the main screen to make it active + // Load main screen if (main_screen != NULL) { - lv_scr_load(main_screen); - USBSerial.println("Main screen loaded"); + lv_scr_load(main_screen); + USBSerial.println("Main screen loaded"); } else { - USBSerial.println("Error: Main screen object is NULL after setup attempt."); + USBSerial.println("Error: Main screen object is NULL after setup attempt"); } - // Release the mutex if it was taken for the splash + // Release LVGL mutex if (lvglMutex != NULL && xSemaphoreGetMutexHolder(lvglMutex) == xTaskGetCurrentTaskHandle()) { - xSemaphoreGive(lvglMutex); + xSemaphoreGive(lvglMutex); } - // Send initial device data after setup + // ========================================================================= + // PHASE 5: Services Initialization + // ========================================================================= + USBSerial.println("Initializing services..."); + + // BLE stack (services created, advertising NOT started yet) + setupBLE(); + + // Monitoring system (disabled initially) + initSimpleMonitor(); + + // Send initial device data send_device_data(); - // Signal that the UI is ready for updates from tasks - uiReady = true; - // Signal all tasks that setup is complete - they can now start their main loops - if (startupSyncSemaphore != NULL) { - xSemaphoreGive(startupSyncSemaphore); - USBSerial.println("Tasks released - startup complete"); - } - // Start BLE advertising now that splash is complete + + // ========================================================================= + // PHASE 6: Create ALL Tasks + // Tasks can start immediately - all dependencies exist + // ========================================================================= + setupTasks(); + + // ========================================================================= + // PHASE 7: Start External Interfaces + // ========================================================================= + USBSerial.println("Starting external interfaces..."); + + // Start BLE advertising (now safe - UI is ready, tasks are running) restartBLEAdvertising(); USBSerial.println("BLE advertising started"); - // Simple instrumentation to detect UI/BMS latency - USBSerial.println("Init complete. UI + BMS loop running"); + // Enable sensor monitoring + enableMonitoring(); // Confirm successful boot to prevent OTA rollback if (esp_ota_mark_app_valid_cancel_rollback() == ESP_OK) { USBSerial.println("OTA: Firmware marked valid - Rollback cancelled"); } - // Enable sensor monitoring after splash screen and UI setup - // This gives BMS/ESC time to initialize and start providing valid data - enableMonitoring(); -} - -// set up all the main threads/tasks with core 0 affinity -void setupTasks() { - xTaskCreate(blinkLEDTask, "blinkLed", 2560, NULL, 1, &blinkLEDTaskHandle); - xTaskCreatePinnedToCore(throttleTask, "throttle", 4352, NULL, 3, &throttleTaskHandle, 0); - // Split UI and BMS into dedicated tasks - xTaskCreatePinnedToCore(uiTask, "UI", 5888, NULL, 2, &uiTaskHandle, 1); - xTaskCreatePinnedToCore(bmsTask, "BMS", 2304, NULL, 2, &bmsTaskHandle, 1); - xTaskCreate(updateBLETask, "BLE Update Task", 8192, NULL, 1, NULL); - xTaskCreate(deviceStateUpdateTask, "State Update Task", 2048, NULL, 1, &deviceStateUpdateTaskHandle); - // Create BLE update task with high priority but on core 1 - xTaskCreatePinnedToCore(bleStateUpdateTask, "BLEStateUpdate", 8192, NULL, 1, &bleStateUpdateTaskHandle, 1); - - // Create melody queue - melodyQueue = xQueueCreate(5, sizeof(MelodyRequest)); - - // Create audio task - pin to core 1 to avoid interference with throttle - xTaskCreatePinnedToCore(audioTask, "Audio", 1536, NULL, 1, &audioTaskHandle, 1); - - // Add hardware watchdog task on core 0 (highest priority among low-prio group) - xTaskCreatePinnedToCore(watchdogTask, "watchdog", 1536, NULL, 3, &watchdogTaskHandle, 0); - - xTaskCreate(updateESCBLETask, "ESC BLE Update Task", 8192, NULL, 1, NULL); - - // Create WebSerial task - xTaskCreate( - webSerialTask, - "WebSerial", - 3072, // Larger stack for ArduinoJson parsing & CDC handling - NULL, - 1, - &webSerialTaskHandle); - - // Create monitoring task - xTaskCreate(monitoringTask, "Monitoring", 4864, NULL, 1, &monitoringTaskHandle); - - // Create vibration task (centralized here after initVibeMotor) - xTaskCreatePinnedToCore(vibeTask, "Vibration", 1536, NULL, 2, &vibeTaskHandle, 1); - - #ifdef OPENPPG_DEBUG - // Create periodic stack watermark logger (low priority) - xTaskCreatePinnedToCore(stackWatermarkLoggerTask, "StackLogger", 3072, NULL, 1, &stackLoggerTaskHandle, 1); - #endif -} - -void setup140() { - if (ENABLE_BUZZ) { - initBuzz(); - } - const int SDA_PIN = 44; - const int SCL_PIN = 41; - Wire.setPins(SDA_PIN, SCL_PIN); - if (!setupAltimeter()) { - USBSerial.println("Error initializing BMP3xx barometer"); - } - if (ENABLE_VIBE) { - initVibeMotor(); - } + USBSerial.println("=== Boot complete ==="); } -// main loop all work is done in tasks +// main loop - all work is done in tasks void loop() { vTaskDelay(pdMS_TO_TICKS(25)); } -void initButtons() { - pinMode(board_config.button_top, INPUT_PULLUP); - - // Create button handling task - xTaskCreatePinnedToCore(buttonHandlerTask, "ButtonHandler", 4096, NULL, 2, &buttonTaskHandle, 0); -} - // Add new button handler task void buttonHandlerTask(void* parameter) { uint32_t lastDebounceTime = 0; From 5638fc02c208de1e5e3be051f51360373feafea7 Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Thu, 29 Jan 2026 09:10:42 -0600 Subject: [PATCH 16/16] linting and cleanup --- inc/sp140/altimeter.h | 58 ++++++------- src/sp140/altimeter.cpp | 178 ++++++++++++++++++++-------------------- src/sp140/main.cpp | 5 +- 3 files changed, 121 insertions(+), 120 deletions(-) diff --git a/inc/sp140/altimeter.h b/inc/sp140/altimeter.h index b78ea0d..f6d6485 100644 --- a/inc/sp140/altimeter.h +++ b/inc/sp140/altimeter.h @@ -1,31 +1,31 @@ -#ifndef INC_SP140_ALTIMETER_H_ -#define INC_SP140_ALTIMETER_H_ - -#include -#include -#include "sp140/structs.h" -#include "sp140/shared-config.h" - -// Constants -#define VARIO_BUFFER_SIZE 25 // Number of samples to average for vertical speed -#define MAX_VERTICAL_SPEED 250.0f // Maximum vertical speed to display (m/s) - +#ifndef INC_SP140_ALTIMETER_H_ +#define INC_SP140_ALTIMETER_H_ + +#include +#include +#include "sp140/structs.h" +#include "sp140/shared-config.h" + +// Constants +#define VARIO_BUFFER_SIZE 25 // Number of samples to average for vertical speed +#define MAX_VERTICAL_SPEED 250.0f // Maximum vertical speed to display (m/s) + // Set up the barometer bool setupAltimeter(); - -// Get the altitude (in meters) -float getAltitude(const STR_DEVICE_DATA_140_V1& deviceData); - -// Get the vertical speed in meters per second -float getVerticalSpeed(); - -// Set the ground altitude to the current altitude to compute AGL -void setGroundAltitude(const STR_DEVICE_DATA_140_V1& deviceData); - -// Get the temperature in degrees Celsius -float getBaroTemperature(); - -// Get the pressure in hPa -float getBaroPressure(); - -#endif // INC_SP140_ALTIMETER_H_ + +// Get the altitude (in meters) +float getAltitude(const STR_DEVICE_DATA_140_V1& deviceData); + +// Get the vertical speed in meters per second +float getVerticalSpeed(); + +// Set the ground altitude to the current altitude to compute AGL +void setGroundAltitude(const STR_DEVICE_DATA_140_V1& deviceData); + +// Get the temperature in degrees Celsius +float getBaroTemperature(); + +// Get the pressure in hPa +float getBaroPressure(); + +#endif // INC_SP140_ALTIMETER_H_ diff --git a/src/sp140/altimeter.cpp b/src/sp140/altimeter.cpp index fd2e33d..67af3b6 100644 --- a/src/sp140/altimeter.cpp +++ b/src/sp140/altimeter.cpp @@ -1,92 +1,92 @@ -#include "sp140/altimeter.h" -#include "sp140/structs.h" - -#include - -Adafruit_BMP3XX bmp; -bool bmpPresent = false; -float groundAltitude = 0; - -struct AltitudeReading { - float altitude; - unsigned long timestamp; -}; - -// Buffer to store altitude readings with timestamps -CircularBuffer altitudeBuffer; - -float getAltitude(const STR_DEVICE_DATA_140_V1& deviceData) { - if (bmpPresent) { - const float altitude = bmp.readAltitude(deviceData.sea_pressure); - float relativeAltitude = altitude - groundAltitude; - - // Add new reading to buffer with timestamp - AltitudeReading reading = {relativeAltitude, millis()}; - altitudeBuffer.push(reading); - - return relativeAltitude; - } - return __FLT_MIN__; -} - -float getVerticalSpeed() { - if (altitudeBuffer.size() < 2) { - return 0.0f; // Not enough readings yet - } - - // Get oldest and newest readings - const AltitudeReading& oldest = altitudeBuffer.first(); - const AltitudeReading& newest = altitudeBuffer.last(); - - // Calculate time difference in seconds - float timeDiff = (newest.timestamp - oldest.timestamp) / 1000.0f; - if (timeDiff <= 0) { - return 0.0f; // Avoid division by zero - } - - // Calculate vertical speed in meters per second - float verticalSpeed = (newest.altitude - oldest.altitude) / timeDiff; - - // Constrain to max vertical speed - return constrain(verticalSpeed, -MAX_VERTICAL_SPEED, MAX_VERTICAL_SPEED); -} - -// set the ground altitude to the current altitude -void setGroundAltitude(const STR_DEVICE_DATA_140_V1& deviceData) { - if (bmpPresent) { - groundAltitude = bmp.readAltitude(deviceData.sea_pressure); - altitudeBuffer.clear(); // Clear the buffer when resetting ground altitude - } -} - -// Get the temperature in degrees Celsius -float getBaroTemperature() { - if (bmpPresent) { - return bmp.readTemperature(); - } - return __FLT_MIN__; // Return a very small number if BMP is not present -} - -// Get the pressure in hPa -float getBaroPressure() { - if (bmpPresent) { - return bmp.readPressure() / 100.0f; // Convert Pa to hPa - } - return __FLT_MIN__; // Return a very small number if BMP is not present -} - +#include "sp140/altimeter.h" +#include "sp140/structs.h" + +#include + +Adafruit_BMP3XX bmp; +bool bmpPresent = false; +float groundAltitude = 0; + +struct AltitudeReading { + float altitude; + unsigned long timestamp; +}; + +// Buffer to store altitude readings with timestamps +CircularBuffer altitudeBuffer; + +float getAltitude(const STR_DEVICE_DATA_140_V1& deviceData) { + if (bmpPresent) { + const float altitude = bmp.readAltitude(deviceData.sea_pressure); + float relativeAltitude = altitude - groundAltitude; + + // Add new reading to buffer with timestamp + AltitudeReading reading = {relativeAltitude, millis()}; + altitudeBuffer.push(reading); + + return relativeAltitude; + } + return __FLT_MIN__; +} + +float getVerticalSpeed() { + if (altitudeBuffer.size() < 2) { + return 0.0f; // Not enough readings yet + } + + // Get oldest and newest readings + const AltitudeReading& oldest = altitudeBuffer.first(); + const AltitudeReading& newest = altitudeBuffer.last(); + + // Calculate time difference in seconds + float timeDiff = (newest.timestamp - oldest.timestamp) / 1000.0f; + if (timeDiff <= 0) { + return 0.0f; // Avoid division by zero + } + + // Calculate vertical speed in meters per second + float verticalSpeed = (newest.altitude - oldest.altitude) / timeDiff; + + // Constrain to max vertical speed + return constrain(verticalSpeed, -MAX_VERTICAL_SPEED, MAX_VERTICAL_SPEED); +} + +// set the ground altitude to the current altitude +void setGroundAltitude(const STR_DEVICE_DATA_140_V1& deviceData) { + if (bmpPresent) { + groundAltitude = bmp.readAltitude(deviceData.sea_pressure); + altitudeBuffer.clear(); // Clear the buffer when resetting ground altitude + } +} + +// Get the temperature in degrees Celsius +float getBaroTemperature() { + if (bmpPresent) { + return bmp.readTemperature(); + } + return __FLT_MIN__; // Return a very small number if BMP is not present +} + +// Get the pressure in hPa +float getBaroPressure() { + if (bmpPresent) { + return bmp.readPressure() / 100.0f; // Convert Pa to hPa + } + return __FLT_MIN__; // Return a very small number if BMP is not present +} + // Start the bmp3XX sensor bool setupAltimeter() { // pull down pin 40 to high to set the address - pinMode(40, OUTPUT); - digitalWrite(40, HIGH); - if (!bmp.begin_I2C(BMP3XX_DEFAULT_ADDRESS, &Wire)) return false; - - bmp.setOutputDataRate(BMP3_ODR_25_HZ); - bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_2X); - bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X); - bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_15); - bmp.readPressure(); // throw away first reading - bmpPresent = true; - return true; -} + pinMode(40, OUTPUT); + digitalWrite(40, HIGH); + if (!bmp.begin_I2C(BMP3XX_DEFAULT_ADDRESS, &Wire)) return false; + + bmp.setOutputDataRate(BMP3_ODR_25_HZ); + bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_2X); + bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X); + bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_15); + bmp.readPressure(); // throw away first reading + bmpPresent = true; + return true; +} diff --git a/src/sp140/main.cpp b/src/sp140/main.cpp index 9f564df..d380e35 100644 --- a/src/sp140/main.cpp +++ b/src/sp140/main.cpp @@ -99,7 +99,7 @@ bool bmsCanInitialized = false; bool escTwaiInitialized = false; -UnifiedBatteryData unifiedBatteryData = {0.0f, 0.0f, 0.0f}; +UnifiedBatteryData unifiedBatteryData = {0.0f, 0.0f, 0.0f, 0.0f}; // volts, amps, power, soc // Throttle PWM smoothing buffer is managed in throttle.cpp @@ -159,6 +159,7 @@ extern TaskHandle_t deviceStateUpdateTaskHandle; extern TaskHandle_t buttonTaskHandle; extern TaskHandle_t vibeTaskHandle; +#ifdef OPENPPG_DEBUG static TaskHandle_t stackLoggerTaskHandle = NULL; static const uint32_t STACK_LOGGER_INTERVAL_MS = 5000; // Log every 5 seconds @@ -205,6 +206,7 @@ static void stackWatermarkLoggerTask(void* parameter) { vTaskDelay(pdMS_TO_TICKS(STACK_LOGGER_INTERVAL_MS)); } } +#endif // OPENPPG_DEBUG // Forward declarations for tasks defined in other compilation units extern void vibeTask(void* parameter); @@ -1210,7 +1212,6 @@ void handleThrottle() { // extern unsigned long lastEscTimeUpdateMillis; // REMOVED - Using struct member now void syncESCTelemetry() { - unsigned long currentTime = millis(); // Update ESC state based first on TWAI init, then on time since last update received if (!escTwaiInitialized) { escTelemetryData.escState = TelemetryState::NOT_CONNECTED;