Arduino core 3.2.1
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
name: CI Examples
|
||||
name: CI Examples Arduino IDF 5.4.x based
|
||||
|
||||
on:
|
||||
workflow_dispatch: # Manually start a workflow
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-24.04, windows-2022, macos-15]
|
||||
os: [ubuntu-latest, windows-latest, macos-15]
|
||||
example:
|
||||
- "examples/arduino-blink"
|
||||
- "examples/arduino-rmt-blink"
|
||||
@@ -20,10 +20,10 @@ jobs:
|
||||
- "examples/arduino-wifiscan"
|
||||
- "examples/arduino-zigbee-light"
|
||||
- "examples/arduino-zigbee-switch"
|
||||
- "examples/tasmota"
|
||||
- "examples/espidf-arduino-h2zero-BLE_scan"
|
||||
#- "examples/espidf-arduino-matter-light"
|
||||
- "examples/arduino-NimBLE-ext_client"
|
||||
- "examples/arduino-matter-light"
|
||||
- "examples/tasmota"
|
||||
- "examples/espidf-arduino-matter-light"
|
||||
- "examples/espidf-arduino-blink"
|
||||
- "examples/espidf-arduino-littlefs"
|
||||
- "examples/espidf-blink"
|
||||
@@ -37,6 +37,15 @@ jobs:
|
||||
- "examples/espidf-ulp"
|
||||
- "examples/espidf-ulp-riscv"
|
||||
- "examples/espidf-ulp-lp"
|
||||
exclude:
|
||||
- os: windows-latest
|
||||
example: "examples/espidf-ulp"
|
||||
- os: windows-latest
|
||||
example: "examples/espidf-ulp-lp"
|
||||
- os: windows-latest
|
||||
example: "examples/espidf-ulp-riscv"
|
||||
- os: windows-latest
|
||||
example: "examples/espidf-arduino-matter-light"
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -48,13 +57,16 @@ jobs:
|
||||
python-version: "3.13"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install wheel
|
||||
pip install -U https://github.com/pioarduino/platformio-core/archive/refs/tags/v6.1.18.zip
|
||||
pip install uv
|
||||
uv pip install --system -U https://github.com/pioarduino/platformio-core/archive/refs/tags/v6.1.18.zip
|
||||
pio pkg install --global --platform file://.
|
||||
- name: git clone Tasmota and add to examples
|
||||
if: "matrix.example == 'examples/tasmota'"
|
||||
run: |
|
||||
git clone -b development --depth 1 https://github.com/arendst/Tasmota.git examples/tasmota
|
||||
cp examples/tasmota_platformio_override.ini examples/tasmota/platformio_override.ini
|
||||
- name: Build examples
|
||||
env:
|
||||
PYTHONIOENCODING: utf-8
|
||||
PYTHONUTF8: '1'
|
||||
run: pio run -d ${{ matrix.example }}
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
[](https://discord.gg/Nutz9crnZr)
|
||||
[](https://github.com/pioarduino/platform-espressif32/releases/latest)
|
||||
|
||||
ESP32 is a series of low-cost, low-power system on a chip microcontrollers with integrated Wi-Fi and Bluetooth. ESP32 integrates an antenna switch, RF balun, power amplifier, low-noise receive amplifier, filters, and power management modules.
|
||||
Espressif Systems is a privately held, fabless semiconductor company renowned for delivering cost-effective wireless communication microcontrollers. Their innovative solutions are widely adopted in mobile devices and Internet of Things (IoT) applications around the globe.
|
||||
|
||||
## General
|
||||
* Issues with boards (wrong / missing). All issues caused from boards will not be fixed from the maintainer(s). A PR needs to be provided against branch `develop` to solve.
|
||||
* No support for the Arduino Nora Nano board, issues needs to be solved by the community
|
||||
|
||||
## IDE Preparation
|
||||
|
||||
- [Download and install Microsoft Visual Studio Code](https://code.visualstudio.com/). pioarduino IDE is on top of it.
|
||||
- Open the extension manager.
|
||||
- Search for the `pioarduino ide` extension.
|
||||
@@ -24,7 +25,7 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with
|
||||
The Wiki is AI generated and insane detailed and accurate.
|
||||
|
||||
### Stable Arduino
|
||||
currently espressif Arduino 3.2.0 and IDF 5.4.1
|
||||
currently espressif Arduino 3.2.1 and IDF 5.4.2
|
||||
|
||||
```ini
|
||||
[env:stable]
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"platforms": [
|
||||
"espressif32"
|
||||
],
|
||||
"name": "Espressif ESP32-S3-DevKitC-1-N16R8V (16 MB Flash Quad, 16 MB PSRAM Octal)",
|
||||
"name": "Espressif ESP32-S3-DevKitC-1-N16R16V (16 MB Flash Quad, 16 MB PSRAM Octal)",
|
||||
"upload": {
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"platforms": [
|
||||
"espressif32"
|
||||
],
|
||||
"name": "Espressif ESP32-S3-DevKitC-1-N8R8 (16 MB Flash Quad, 2 MB PSRAM Quad)",
|
||||
"name": "Espressif ESP32-S3-DevKitC-1-N16R2 (16 MB Flash Quad, 2 MB PSRAM Quad)",
|
||||
"upload": {
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"platforms": [
|
||||
"espressif32"
|
||||
],
|
||||
"name": "Espressif ESP32-S3-DevKitC-1-N8R8 (4 MB Flash Quad, 2 MB PSRAM Quad)",
|
||||
"name": "Espressif ESP32-S3-DevKitC-1-N4R2 (4 MB Flash Quad, 2 MB PSRAM Quad)",
|
||||
"upload": {
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"platforms": [
|
||||
"espressif32"
|
||||
],
|
||||
"name": "Espressif ESP32-S3-DevKitC-1-N8R8 (4 MB Flash Quad, 8 MB PSRAM Octal)",
|
||||
"name": "Espressif ESP32-S3-DevKitC-1-N4R8 (4 MB Flash Quad, 8 MB PSRAM Octal)",
|
||||
"upload": {
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"platforms": [
|
||||
"espressif32"
|
||||
],
|
||||
"name": "Espressif ESP32-S3-DevKitC-1-N8R8 (8 MB Flash Quad, 2 MB PSRAM quad)",
|
||||
"name": "Espressif ESP32-S3-DevKitC-1-N8R2 (8 MB Flash Quad, 2 MB PSRAM quad)",
|
||||
"upload": {
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"memory_type": "qio_opi",
|
||||
"partitions": "default_8MB.csv"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DARDUINO_M5Stack_ATOMS3U",
|
||||
"-DARDUINO_USB_MODE=1",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "dio",
|
||||
"mcu": "esp32s3",
|
||||
"variant": "m5stack_atoms3"
|
||||
},
|
||||
"connectivity": [
|
||||
"bluetooth",
|
||||
"wifi"
|
||||
],
|
||||
"debug": {
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino",
|
||||
"espidf"
|
||||
],
|
||||
"name": "M5Stack AtomS3U",
|
||||
"upload": {
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
"url": "https://docs.m5stack.com/en/core/AtomS3U",
|
||||
"vendor": "M5Stack"
|
||||
}
|
||||
@@ -41,8 +41,6 @@
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino":{
|
||||
"partitions": "default_8MB.csv",
|
||||
"memory_type": "qio_qspi"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DARDUINO_EDGES3[D]",
|
||||
"-DBOARD_HAS_PSRAM",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MODE=1",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"hwids": [
|
||||
[
|
||||
"0X303A",
|
||||
"0x82DC"
|
||||
]
|
||||
],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "um_edges3_d"
|
||||
},
|
||||
"connectivity": [
|
||||
"bluetooth",
|
||||
"wifi"
|
||||
],
|
||||
"debug": {
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino",
|
||||
"espidf"
|
||||
],
|
||||
"name": "Unexpected Maker EDGES3[D]",
|
||||
"upload": {
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
"url": "https://unexpectedmaker.com/",
|
||||
"vendor": "Unexpected Maker"
|
||||
}
|
||||
@@ -36,8 +36,6 @@
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 16777216,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
|
||||
@@ -36,8 +36,6 @@
|
||||
"flash_size": "4MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 4194304,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
|
||||
@@ -41,8 +41,6 @@
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 16777216,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
|
||||
@@ -41,8 +41,6 @@
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
|
||||
@@ -41,8 +41,6 @@
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
|
||||
@@ -41,8 +41,6 @@
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
|
||||
@@ -41,8 +41,6 @@
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 16777216,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
|
||||
@@ -36,8 +36,6 @@
|
||||
"flash_size": "4MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 4194304,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"partitions": "default_16MB.csv",
|
||||
"memory_type": "qio_opi"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DBOARD_HAS_PSRAM",
|
||||
"-DARDUINO_SQUIXL",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MODE=1",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"hwids": [
|
||||
[
|
||||
"0x303A",
|
||||
"0x82DF"
|
||||
]
|
||||
],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "um_squixl"
|
||||
},
|
||||
"connectivity": [
|
||||
"bluetooth",
|
||||
"wifi"
|
||||
],
|
||||
"debug": {
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino",
|
||||
"espidf"
|
||||
],
|
||||
"name": "Unexpected Maker SQUiXL",
|
||||
"upload": {
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
"url": "https://unexpectedmaker.com/shop/squixl",
|
||||
"vendor": "Unexpected Maker"
|
||||
}
|
||||
@@ -37,8 +37,6 @@
|
||||
"flash_size": "4MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 4194304,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
|
||||
@@ -41,8 +41,6 @@
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
|
||||
@@ -110,14 +110,14 @@ env.Append(
|
||||
" ".join(
|
||||
[
|
||||
"riscv32-esp-elf-objcopy"
|
||||
if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2","esp32p4")
|
||||
if mcu in ("esp32c2","esp32c3","esp32c5","esp32c6","esp32h2","esp32p4")
|
||||
else "xtensa-%s-elf-objcopy" % mcu,
|
||||
"--input-target",
|
||||
"binary",
|
||||
"--output-target",
|
||||
"elf32-littleriscv" if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2","esp32p4") else "elf32-xtensa-le",
|
||||
"elf32-littleriscv" if mcu in ("esp32c2","esp32c3","esp32c5","esp32c6","esp32h2","esp32p4") else "elf32-xtensa-le",
|
||||
"--binary-architecture",
|
||||
"riscv" if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2","esp32p4") else "xtensa",
|
||||
"riscv" if mcu in ("esp32c2","esp32c3","esp32c5","esp32c6","esp32h2","esp32p4") else "xtensa",
|
||||
"--rename-section",
|
||||
".data=.rodata.embedded",
|
||||
"$SOURCE",
|
||||
|
||||
+854
-146
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+269
-183
@@ -40,22 +40,22 @@ from SCons.Script import (
|
||||
DefaultEnvironment,
|
||||
)
|
||||
|
||||
from platformio import fs, __version__
|
||||
from platformio import fs
|
||||
from platformio.compat import IS_WINDOWS
|
||||
from platformio.proc import exec_command
|
||||
from platformio.builder.tools.piolib import ProjectAsLibBuilder
|
||||
from platformio.project.config import ProjectConfig
|
||||
from platformio.package.version import get_original_version, pepver_to_semver
|
||||
|
||||
# Added to avoid conflicts between installed Python packages from
|
||||
# the IDF virtual environment and PlatformIO Core
|
||||
# Note: This workaround can be safely deleted when PlatformIO 6.1.7 is released
|
||||
if os.environ.get("PYTHONPATH"):
|
||||
del os.environ["PYTHONPATH"]
|
||||
|
||||
env = DefaultEnvironment()
|
||||
env.SConscript("_embed_files.py", exports="env")
|
||||
|
||||
# remove maybe existing old map file in project root
|
||||
map_file = os.path.join(env.subst("$PROJECT_DIR"), env.subst("$PROGNAME") + ".map")
|
||||
if os.path.exists(map_file):
|
||||
os.remove(map_file)
|
||||
|
||||
def install_standard_python_deps():
|
||||
def _get_installed_standard_pip_packages():
|
||||
result = {}
|
||||
@@ -83,7 +83,10 @@ def install_standard_python_deps():
|
||||
deps = {
|
||||
"wheel": ">=0.35.1",
|
||||
"rich-click": ">=1.8.6",
|
||||
"PyYAML": ">=6.0.2"
|
||||
"PyYAML": ">=6.0.2",
|
||||
"intelhex": ">=2.3.0",
|
||||
"rich": ">=14.0.0",
|
||||
"esp-idf-size": ">=1.6.1"
|
||||
}
|
||||
|
||||
installed_packages = _get_installed_standard_pip_packages()
|
||||
@@ -100,7 +103,7 @@ def install_standard_python_deps():
|
||||
env.Execute(
|
||||
env.VerboseAction(
|
||||
(
|
||||
'"$PYTHONEXE" -m pip install -U '
|
||||
'"$PYTHONEXE" -m pip install -U -q -q -q '
|
||||
+ " ".join(
|
||||
[
|
||||
'"%s%s"' % (p, deps[p])
|
||||
@@ -147,18 +150,20 @@ TOOLCHAIN_DIR = platform.get_package_dir(
|
||||
assert os.path.isdir(FRAMEWORK_DIR)
|
||||
assert os.path.isdir(TOOLCHAIN_DIR)
|
||||
|
||||
if (
|
||||
["espidf"] == env.get("PIOFRAMEWORK")
|
||||
and semantic_version.Version.coerce(__version__)
|
||||
<= semantic_version.Version("6.1.10")
|
||||
and "__debug" in COMMAND_LINE_TARGETS
|
||||
):
|
||||
print("Warning! Debugging an IDF project requires PlatformIO Core >= 6.1.11!")
|
||||
def create_silent_action(action_func):
|
||||
"""Create a silent SCons action that suppresses output"""
|
||||
silent_action = env.Action(action_func)
|
||||
silent_action.strfunction = lambda target, source, env: ''
|
||||
return silent_action
|
||||
|
||||
# Arduino framework as a component is not compatible with ESP-IDF >5.3
|
||||
if "arduino" in env.subst("$PIOFRAMEWORK"):
|
||||
ARDUINO_FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32")
|
||||
ARDUINO_FRMWRK_LIB_DIR = platform.get_package_dir("framework-arduinoespressif32-libs")
|
||||
if mcu == "esp32c2":
|
||||
ARDUINO_FRMWRK_C2_LIB_DIR = join(ARDUINO_FRMWRK_LIB_DIR, mcu)
|
||||
if not os.path.exists(ARDUINO_FRMWRK_C2_LIB_DIR):
|
||||
ARDUINO_C2_DIR = join(platform.get_package_dir("framework-arduino-c2-skeleton-lib"),mcu)
|
||||
shutil.copytree(ARDUINO_C2_DIR, ARDUINO_FRMWRK_C2_LIB_DIR, dirs_exist_ok=True)
|
||||
# Possible package names in 'package@version' format is not compatible with CMake
|
||||
if "@" in os.path.basename(ARDUINO_FRAMEWORK_DIR):
|
||||
new_path = os.path.join(
|
||||
@@ -168,6 +173,7 @@ if "arduino" in env.subst("$PIOFRAMEWORK"):
|
||||
os.rename(ARDUINO_FRAMEWORK_DIR, new_path)
|
||||
ARDUINO_FRAMEWORK_DIR = new_path
|
||||
assert ARDUINO_FRAMEWORK_DIR and os.path.isdir(ARDUINO_FRAMEWORK_DIR)
|
||||
arduino_libs_mcu = join(platform.get_package_dir("framework-arduinoespressif32-libs"),mcu)
|
||||
|
||||
BUILD_DIR = env.subst("$BUILD_DIR")
|
||||
PROJECT_DIR = env.subst("$PROJECT_DIR")
|
||||
@@ -178,6 +184,18 @@ SDKCONFIG_PATH = os.path.expandvars(board.get(
|
||||
os.path.join(PROJECT_DIR, "sdkconfig.%s" % env.subst("$PIOENV")),
|
||||
))
|
||||
|
||||
def contains_path_traversal(url):
|
||||
"""Check for Path Traversal patterns"""
|
||||
dangerous_patterns = [
|
||||
'../', '..\\', # Standard Path Traversal
|
||||
'%2e%2e%2f', '%2e%2e%5c', # URL-encoded
|
||||
'..%2f', '..%5c', # Mixed
|
||||
'%252e%252e%252f', # Double encoded
|
||||
]
|
||||
|
||||
url_lower = url.lower()
|
||||
return any(pattern in url_lower for pattern in dangerous_patterns)
|
||||
|
||||
#
|
||||
# generate modified Arduino IDF sdkconfig, applying settings from "custom_sdkconfig"
|
||||
#
|
||||
@@ -192,180 +210,208 @@ if "espidf.custom_sdkconfig" in board:
|
||||
flag_custom_sdkonfig = True
|
||||
|
||||
def HandleArduinoIDFsettings(env):
|
||||
def get_MD5_hash(phrase):
|
||||
import hashlib
|
||||
return hashlib.md5((phrase).encode('utf-8')).hexdigest()[:16]
|
||||
"""
|
||||
Handles Arduino IDF settings configuration with custom sdkconfig support.
|
||||
"""
|
||||
|
||||
def custom_sdkconfig_file(string):
|
||||
def get_MD5_hash(phrase):
|
||||
"""Generate MD5 hash for checksum validation."""
|
||||
import hashlib
|
||||
return hashlib.md5(phrase.encode('utf-8')).hexdigest()[:16]
|
||||
|
||||
def load_custom_sdkconfig_file():
|
||||
"""Load custom sdkconfig from file or URL if specified."""
|
||||
if not config.has_option("env:" + env["PIOENV"], "custom_sdkconfig"):
|
||||
return ""
|
||||
sdkconfig_entrys = env.GetProjectOption("custom_sdkconfig").splitlines()
|
||||
for file in sdkconfig_entrys:
|
||||
if "http" in file and "://" in file:
|
||||
response = requests.get(file.split(" ")[0])
|
||||
|
||||
sdkconfig_entries = env.GetProjectOption("custom_sdkconfig").splitlines()
|
||||
|
||||
for file_entry in sdkconfig_entries:
|
||||
# Handle HTTP/HTTPS URLs
|
||||
if "http" in file_entry and "://" in file_entry:
|
||||
url = file_entry.split(" ")[0]
|
||||
# Path Traversal protection
|
||||
if contains_path_traversal(url):
|
||||
print(f"Path Traversal detected: {url} check your URL path")
|
||||
else:
|
||||
try:
|
||||
response = requests.get(file_entry.split(" ")[0], timeout=10)
|
||||
if response.ok:
|
||||
target = str(response.content.decode('utf-8'))
|
||||
else:
|
||||
print("Failed to download:", file)
|
||||
return response.content.decode('utf-8')
|
||||
except requests.RequestException as e:
|
||||
print(f"Error downloading {file_entry}: {e}")
|
||||
except UnicodeDecodeError as e:
|
||||
print(f"Error decoding response from {file_entry}: {e}")
|
||||
return ""
|
||||
return target
|
||||
if "file://" in file:
|
||||
file_path = join(PROJECT_DIR,file.lstrip("file://").split(os.path.sep)[-1])
|
||||
|
||||
# Handle local files
|
||||
if "file://" in file_entry:
|
||||
file_ref = file_entry[7:] if file_entry.startswith("file://") else file_entry
|
||||
filename = os.path.basename(file_ref)
|
||||
file_path = join(PROJECT_DIR, filename)
|
||||
if os.path.exists(file_path):
|
||||
with open(file_path, 'r') as file:
|
||||
target = file.read()
|
||||
try:
|
||||
with open(file_path, 'r') as f:
|
||||
return f.read()
|
||||
except IOError as e:
|
||||
print(f"Error reading file {file_path}: {e}")
|
||||
return ""
|
||||
else:
|
||||
print("File not found:", file_path)
|
||||
return ""
|
||||
return target
|
||||
print("File not found, check path:", file_path)
|
||||
return ""
|
||||
|
||||
return ""
|
||||
|
||||
custom_sdk_config_flags = ""
|
||||
board_idf_config_flags = ""
|
||||
sdkconfig_file_flags = ""
|
||||
custom_sdkconfig_file_str = ""
|
||||
|
||||
if config.has_option("env:"+env["PIOENV"], "custom_sdkconfig"):
|
||||
flag_custom_sdkonfig = True
|
||||
custom_sdk_config_flags = (env.GetProjectOption("custom_sdkconfig").rstrip("\n")) + "\n"
|
||||
custom_sdkconfig_file_str = custom_sdkconfig_file(sdkconfig_file_flags)
|
||||
|
||||
if "espidf.custom_sdkconfig" in board:
|
||||
board_idf_config_flags = ('\n'.join([element for element in board.get("espidf.custom_sdkconfig", "")])).rstrip("\n") + "\n"
|
||||
flag_custom_sdkonfig = True
|
||||
|
||||
if flag_custom_sdkonfig == True: # TDOO duplicated
|
||||
print("*** Add \"custom_sdkconfig\" settings to IDF sdkconfig.defaults ***")
|
||||
idf_config_flags = custom_sdk_config_flags
|
||||
if custom_sdkconfig_file_str != "":
|
||||
sdkconfig_file_flags = custom_sdkconfig_file_str + "\n"
|
||||
idf_config_flags = sdkconfig_file_flags + idf_config_flags
|
||||
idf_config_flags = board_idf_config_flags + idf_config_flags
|
||||
if flash_frequency != "80m":
|
||||
idf_config_flags = idf_config_flags + "# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set\n"
|
||||
esptool_flashfreq_y = "CONFIG_ESPTOOLPY_FLASHFREQ_%s=y\n" % flash_frequency.upper()
|
||||
esptool_flashfreq_M = "CONFIG_ESPTOOLPY_FLASHFREQ=\"%s\"\n" % flash_frequency
|
||||
idf_config_flags = idf_config_flags + esptool_flashfreq_y + esptool_flashfreq_M
|
||||
if flash_mode != "qio":
|
||||
idf_config_flags = idf_config_flags + "# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set\n"
|
||||
esptool_flashmode = "CONFIG_ESPTOOLPY_FLASHMODE_%s=y\n" % flash_mode.upper()
|
||||
if esptool_flashmode not in idf_config_flags:
|
||||
idf_config_flags = idf_config_flags + esptool_flashmode
|
||||
if mcu in ("esp32") and "CONFIG_FREERTOS_UNICORE=y" in idf_config_flags:
|
||||
idf_config_flags = idf_config_flags + "# CONFIG_SPIRAM is not set\n"
|
||||
|
||||
idf_config_flags = idf_config_flags.splitlines()
|
||||
sdkconfig_src = join(ARDUINO_FRMWRK_LIB_DIR,mcu,"sdkconfig")
|
||||
|
||||
def get_flag(line):
|
||||
def extract_flag_name(line):
|
||||
"""Extract flag name from sdkconfig line."""
|
||||
line = line.strip()
|
||||
if line.startswith("#") and "is not set" in line:
|
||||
return line.split(" ")[1]
|
||||
elif not line.startswith("#") and len(line.split("=")) > 1:
|
||||
elif not line.startswith("#") and "=" in line:
|
||||
return line.split("=")[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
with open(sdkconfig_src) as src:
|
||||
sdkconfig_dst = os.path.join(PROJECT_DIR, "sdkconfig.defaults")
|
||||
dst = open(sdkconfig_dst,"w")
|
||||
dst.write("# TASMOTA__"+ get_MD5_hash(''.join(custom_sdk_config_flags).strip() + mcu) +"\n")
|
||||
while line := src.readline():
|
||||
flag = get_flag(line)
|
||||
if flag is None:
|
||||
dst.write(line)
|
||||
else:
|
||||
no_match = True
|
||||
for item in idf_config_flags:
|
||||
if flag == get_flag(item.replace("\'", "")):
|
||||
dst.write(item.replace("\'", "")+"\n")
|
||||
no_match = False
|
||||
print("Replace:",line,"with:",item.replace("\'", ""))
|
||||
idf_config_flags.remove(item)
|
||||
if no_match:
|
||||
dst.write(line)
|
||||
for item in idf_config_flags: # are there new flags?
|
||||
print("Add:",item.replace("\'", ""))
|
||||
dst.write(item.replace("\'", "")+"\n")
|
||||
dst.close()
|
||||
def build_idf_config_flags():
|
||||
"""Build complete IDF configuration flags from all sources."""
|
||||
flags = []
|
||||
|
||||
# Add board-specific flags first
|
||||
if "espidf.custom_sdkconfig" in board:
|
||||
board_flags = board.get("espidf.custom_sdkconfig", [])
|
||||
if board_flags:
|
||||
flags.extend(board_flags)
|
||||
|
||||
# Add custom sdkconfig file content
|
||||
custom_file_content = load_custom_sdkconfig_file()
|
||||
if custom_file_content:
|
||||
flags.append(custom_file_content)
|
||||
|
||||
# Add project-level custom sdkconfig
|
||||
if config.has_option("env:" + env["PIOENV"], "custom_sdkconfig"):
|
||||
custom_flags = env.GetProjectOption("custom_sdkconfig").rstrip("\n")
|
||||
if custom_flags:
|
||||
flags.append(custom_flags)
|
||||
|
||||
return "\n".join(flags) + "\n" if flags else ""
|
||||
|
||||
def add_flash_configuration(config_flags):
|
||||
"""Add flash frequency and mode configuration."""
|
||||
if flash_frequency != "80m":
|
||||
config_flags += "# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set\n"
|
||||
config_flags += f"CONFIG_ESPTOOLPY_FLASHFREQ_{flash_frequency.upper()}=y\n"
|
||||
config_flags += f"CONFIG_ESPTOOLPY_FLASHFREQ=\"{flash_frequency}\"\n"
|
||||
|
||||
if flash_mode != "qio":
|
||||
config_flags += "# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set\n"
|
||||
|
||||
flash_mode_flag = f"CONFIG_ESPTOOLPY_FLASHMODE_{flash_mode.upper()}=y\n"
|
||||
if flash_mode_flag not in config_flags:
|
||||
config_flags += flash_mode_flag
|
||||
|
||||
# ESP32 specific SPIRAM configuration
|
||||
if mcu == "esp32" and "CONFIG_FREERTOS_UNICORE=y" in config_flags:
|
||||
config_flags += "# CONFIG_SPIRAM is not set\n"
|
||||
|
||||
return config_flags
|
||||
|
||||
def write_sdkconfig_file(idf_config_flags, checksum_source):
|
||||
if "arduino" not in env.subst("$PIOFRAMEWORK"):
|
||||
print("Error: Arduino framework required for sdkconfig processing")
|
||||
return
|
||||
else:
|
||||
"""Write the final sdkconfig.defaults file with checksum."""
|
||||
sdkconfig_src = join(arduino_libs_mcu, "sdkconfig")
|
||||
sdkconfig_dst = join(PROJECT_DIR, "sdkconfig.defaults")
|
||||
|
||||
# Generate checksum for validation (maintains original logic)
|
||||
checksum = get_MD5_hash(checksum_source.strip() + mcu)
|
||||
|
||||
with open(sdkconfig_src, 'r', encoding='utf-8') as src, open(sdkconfig_dst, 'w', encoding='utf-8') as dst:
|
||||
# Write checksum header (critical for compilation decision logic)
|
||||
dst.write(f"# TASMOTA__{checksum}\n")
|
||||
|
||||
processed_flags = set()
|
||||
|
||||
# Process each line from source sdkconfig
|
||||
for line in src:
|
||||
flag_name = extract_flag_name(line)
|
||||
|
||||
if flag_name is None:
|
||||
dst.write(line)
|
||||
continue
|
||||
|
||||
# Check if we have a custom replacement for this flag
|
||||
flag_replaced = False
|
||||
for custom_flag in idf_config_flags[:]: # Create copy for safe removal
|
||||
custom_flag_name = extract_flag_name(custom_flag.replace("'", ""))
|
||||
|
||||
if flag_name == custom_flag_name:
|
||||
cleaned_flag = custom_flag.replace("'", "")
|
||||
dst.write(cleaned_flag + "\n")
|
||||
print(f"Replace: {line.strip()} with: {cleaned_flag}")
|
||||
idf_config_flags.remove(custom_flag)
|
||||
processed_flags.add(custom_flag_name)
|
||||
flag_replaced = True
|
||||
break
|
||||
|
||||
if not flag_replaced:
|
||||
dst.write(line)
|
||||
|
||||
# Add any remaining new flags
|
||||
for remaining_flag in idf_config_flags:
|
||||
cleaned_flag = remaining_flag.replace("'", "")
|
||||
print(f"Add: {cleaned_flag}")
|
||||
dst.write(cleaned_flag + "\n")
|
||||
|
||||
# Main execution logic
|
||||
has_custom_config = (
|
||||
config.has_option("env:" + env["PIOENV"], "custom_sdkconfig") or
|
||||
"espidf.custom_sdkconfig" in board
|
||||
)
|
||||
|
||||
if not has_custom_config:
|
||||
return
|
||||
|
||||
print("*** Add \"custom_sdkconfig\" settings to IDF sdkconfig.defaults ***")
|
||||
|
||||
# Build complete configuration
|
||||
idf_config_flags = build_idf_config_flags()
|
||||
idf_config_flags = add_flash_configuration(idf_config_flags)
|
||||
|
||||
# Convert to list for processing
|
||||
idf_config_list = [line for line in idf_config_flags.splitlines() if line.strip()]
|
||||
|
||||
# Write final configuration file with checksum
|
||||
custom_sdk_config_flags = ""
|
||||
if config.has_option("env:" + env["PIOENV"], "custom_sdkconfig"):
|
||||
custom_sdk_config_flags = env.GetProjectOption("custom_sdkconfig").rstrip("\n") + "\n"
|
||||
|
||||
write_sdkconfig_file(idf_config_list, custom_sdk_config_flags)
|
||||
|
||||
|
||||
|
||||
def HandleCOMPONENTsettings(env):
|
||||
if flag_custom_component_add == True or flag_custom_component_remove == True: # todo remove duplicated
|
||||
import yaml
|
||||
from yaml import SafeLoader
|
||||
print("*** \"custom_component\" is used to select managed idf components ***")
|
||||
if flag_custom_component_remove == True:
|
||||
idf_custom_component_remove = env.GetProjectOption("custom_component_remove").splitlines()
|
||||
else:
|
||||
idf_custom_component_remove = ""
|
||||
if flag_custom_component_add == True:
|
||||
idf_custom_component_add = env.GetProjectOption("custom_component_add").splitlines()
|
||||
else:
|
||||
idf_custom_component_add = ""
|
||||
from component_manager import ComponentManager
|
||||
component_manager = ComponentManager(env)
|
||||
|
||||
# search "idf_component.yml" file
|
||||
try: # 1.st in Arduino framework
|
||||
idf_component_yml_src = os.path.join(ARDUINO_FRAMEWORK_DIR, "idf_component.yml")
|
||||
shutil.copy(join(ARDUINO_FRAMEWORK_DIR,"idf_component.yml"),join(ARDUINO_FRAMEWORK_DIR,"idf_component.yml.orig"))
|
||||
yml_file_dir = idf_component_yml_src
|
||||
except: # 2.nd Project source
|
||||
try:
|
||||
idf_component_yml_src = os.path.join(PROJECT_SRC_DIR, "idf_component.yml")
|
||||
shutil.copy(join(PROJECT_SRC_DIR,"idf_component.yml"),join(PROJECT_SRC_DIR,"idf_component.yml.orig"))
|
||||
yml_file_dir = idf_component_yml_src
|
||||
except: # no idf_component.yml in Project source -> create
|
||||
idf_component_yml_src = os.path.join(PROJECT_SRC_DIR, "idf_component.yml")
|
||||
yml_file_dir = idf_component_yml_src
|
||||
idf_component_yml_str = """
|
||||
dependencies:
|
||||
idf: \">=5.1\"
|
||||
"""
|
||||
idf_component_yml = yaml.safe_load(idf_component_yml_str)
|
||||
with open(idf_component_yml_src, 'w',) as f :
|
||||
yaml.dump(idf_component_yml,f)
|
||||
if flag_custom_component_add or flag_custom_component_remove:
|
||||
actions = [action for flag, action in [
|
||||
(flag_custom_component_add, "select"),
|
||||
(flag_custom_component_remove, "deselect")
|
||||
] if flag]
|
||||
action_text = " and ".join(actions)
|
||||
print(f"*** \"custom_component\" is used to {action_text} managed idf components ***")
|
||||
|
||||
yaml_file=open(idf_component_yml_src,"r")
|
||||
idf_component=yaml.load(yaml_file, Loader=SafeLoader)
|
||||
idf_component_str=json.dumps(idf_component) # convert to json string
|
||||
idf_component_json=json.loads(idf_component_str) # convert string to json dict
|
||||
|
||||
if idf_custom_component_remove != "":
|
||||
for entry in idf_custom_component_remove:
|
||||
# checking if the entry exists before removing
|
||||
if entry in idf_component_json["dependencies"]:
|
||||
print("*** Removing component:",entry)
|
||||
del idf_component_json["dependencies"][entry]
|
||||
|
||||
if idf_custom_component_add != "":
|
||||
for entry in idf_custom_component_add:
|
||||
if len(str(entry)) > 4: # too short or empty entry
|
||||
# add new entrys to json
|
||||
if "@" in entry:
|
||||
idf_comp_entry = str(entry.split("@")[0]).replace(" ", "")
|
||||
idf_comp_vers = str(entry.split("@")[1]).replace(" ", "")
|
||||
else:
|
||||
idf_comp_entry = str(entry).replace(" ", "")
|
||||
idf_comp_vers = "*"
|
||||
if idf_comp_entry not in idf_component_json["dependencies"]:
|
||||
print("*** Adding component:", idf_comp_entry, idf_comp_vers)
|
||||
new_entry = {idf_comp_entry: {"version": idf_comp_vers}}
|
||||
idf_component_json["dependencies"].update(new_entry)
|
||||
|
||||
idf_component_yml_file = open(yml_file_dir,"w")
|
||||
yaml.dump(idf_component_json, idf_component_yml_file)
|
||||
idf_component_yml_file.close()
|
||||
# print("JSON from modified idf_component.yml:")
|
||||
# print(json.dumps(idf_component_json))
|
||||
component_manager.handle_component_settings(
|
||||
add_components=flag_custom_component_add,
|
||||
remove_components=flag_custom_component_remove
|
||||
)
|
||||
return
|
||||
return
|
||||
|
||||
if flag_custom_component_add == True or flag_custom_component_remove == True:
|
||||
if "arduino" in env.subst("$PIOFRAMEWORK"):
|
||||
HandleCOMPONENTsettings(env)
|
||||
|
||||
if flag_custom_sdkonfig == True and "arduino" in env.subst("$PIOFRAMEWORK"):
|
||||
if flag_custom_sdkonfig == True and "arduino" in env.subst("$PIOFRAMEWORK") and "espidf" not in env.subst("$PIOFRAMEWORK"):
|
||||
HandleArduinoIDFsettings(env)
|
||||
LIB_SOURCE = os.path.join(ProjectConfig.get_instance().get("platformio", "platforms_dir"), "espressif32", "builder", "build_lib")
|
||||
if not bool(os.path.exists(os.path.join(PROJECT_DIR, ".dummy"))):
|
||||
@@ -397,7 +443,6 @@ def get_project_lib_includes(env):
|
||||
|
||||
return paths
|
||||
|
||||
|
||||
def is_cmake_reconfigure_required(cmake_api_reply_dir):
|
||||
cmake_cache_file = os.path.join(BUILD_DIR, "CMakeCache.txt")
|
||||
cmake_txt_files = [
|
||||
@@ -536,6 +581,8 @@ def populate_idf_env_vars(idf_env):
|
||||
if "IDF_TOOLS_PATH" in idf_env:
|
||||
del idf_env["IDF_TOOLS_PATH"]
|
||||
|
||||
idf_env["ESP_ROM_ELF_DIR"] = platform.get_package_dir("tool-esp-rom-elfs")
|
||||
|
||||
|
||||
def get_target_config(project_configs, target_index, cmake_api_reply_dir):
|
||||
target_json = project_configs.get("targets")[target_index].get("jsonFile", "")
|
||||
@@ -595,6 +642,8 @@ def extract_defines(compile_group):
|
||||
define_string = define_string.strip()
|
||||
if "=" in define_string:
|
||||
define, value = define_string.split("=", maxsplit=1)
|
||||
if define == "OPENTHREAD_BUILD_DATETIME":
|
||||
return None
|
||||
if any(char in value for char in (' ', '<', '>')):
|
||||
value = f'"{value}"'
|
||||
elif '"' in value and not value.startswith("\\"):
|
||||
@@ -1531,11 +1580,10 @@ def install_python_deps():
|
||||
# https://github.com/platformio/platformio-core/issues/4614
|
||||
"urllib3": "<2",
|
||||
# https://github.com/platformio/platform-espressif32/issues/635
|
||||
"cryptography": "~=41.0.1",
|
||||
"future": ">=0.18.3",
|
||||
"cryptography": "~=44.0.0",
|
||||
"pyparsing": ">=3.1.0,<4",
|
||||
"idf-component-manager": "~=2.0.1",
|
||||
"esp-idf-kconfig": ">=2.5.0"
|
||||
"esp-idf-kconfig": "~=2.5.0"
|
||||
}
|
||||
|
||||
if sys_platform.system() == "Darwin" and "arm" in sys_platform.machine().lower():
|
||||
@@ -1556,7 +1604,7 @@ def install_python_deps():
|
||||
env.Execute(
|
||||
env.VerboseAction(
|
||||
(
|
||||
'"%s" -m pip install -U ' % python_exe_path
|
||||
'"%s" -m pip install -U -q -q -q ' % python_exe_path
|
||||
+ " ".join(['"%s%s"' % (p, deps[p]) for p in packages_to_install])
|
||||
),
|
||||
"Installing ESP-IDF's Python dependencies",
|
||||
@@ -1566,7 +1614,7 @@ def install_python_deps():
|
||||
if IS_WINDOWS and "windows-curses" not in installed_packages:
|
||||
env.Execute(
|
||||
env.VerboseAction(
|
||||
'"%s" -m pip install windows-curses' % python_exe_path,
|
||||
'"%s" -m pip install -q -q -q windows-curses' % python_exe_path,
|
||||
"Installing windows-curses package",
|
||||
)
|
||||
)
|
||||
@@ -1786,18 +1834,36 @@ if "arduino" in env.subst("$PIOFRAMEWORK"):
|
||||
LIBSOURCE_DIRS=[os.path.join(ARDUINO_FRAMEWORK_DIR, "libraries")]
|
||||
)
|
||||
|
||||
print("Reading CMake configuration...")
|
||||
project_codemodel = get_cmake_code_model(
|
||||
PROJECT_DIR,
|
||||
BUILD_DIR,
|
||||
[
|
||||
# Set ESP-IDF version environment variables (needed for proper Kconfig processing)
|
||||
framework_version = get_framework_version()
|
||||
major_version = framework_version.split('.')[0] + '.' + framework_version.split('.')[1]
|
||||
os.environ["ESP_IDF_VERSION"] = major_version
|
||||
|
||||
# Configure CMake arguments with ESP-IDF version
|
||||
extra_cmake_args = [
|
||||
"-DIDF_TARGET=" + idf_variant,
|
||||
"-DPYTHON_DEPS_CHECKED=1",
|
||||
"-DEXTRA_COMPONENT_DIRS:PATH=" + ";".join(extra_components),
|
||||
"-DPYTHON=" + get_python_exe(),
|
||||
"-DSDKCONFIG=" + SDKCONFIG_PATH,
|
||||
f"-DESP_IDF_VERSION={major_version}",
|
||||
f"-DESP_IDF_VERSION_MAJOR={framework_version.split('.')[0]}",
|
||||
f"-DESP_IDF_VERSION_MINOR={framework_version.split('.')[1]}",
|
||||
]
|
||||
+ click.parser.split_arg_string(board.get("build.cmake_extra_args", "")),
|
||||
|
||||
# This will add the linker flag for the map file
|
||||
extra_cmake_args.append(
|
||||
f'-DCMAKE_EXE_LINKER_FLAGS=-Wl,-Map={os.path.join(BUILD_DIR, env.subst("$PROGNAME") + ".map")}'
|
||||
)
|
||||
|
||||
# Add any extra args from board config
|
||||
extra_cmake_args += click.parser.split_arg_string(board.get("build.cmake_extra_args", ""))
|
||||
|
||||
print("Reading CMake configuration...")
|
||||
project_codemodel = get_cmake_code_model(
|
||||
PROJECT_DIR,
|
||||
BUILD_DIR,
|
||||
extra_cmake_args
|
||||
)
|
||||
|
||||
# At this point the sdkconfig file should be generated by the underlying build system
|
||||
@@ -1973,7 +2039,7 @@ env.Prepend(
|
||||
(
|
||||
board.get(
|
||||
"upload.bootloader_offset",
|
||||
"0x1000" if mcu in ["esp32", "esp32s2"] else ("0x2000" if mcu in ["esp32p4"] else "0x0"),
|
||||
"0x1000" if mcu in ["esp32", "esp32s2"] else ("0x2000" if mcu in ["esp32c5", "esp32p4"] else "0x0"),
|
||||
),
|
||||
os.path.join("$BUILD_DIR", "bootloader.bin"),
|
||||
),
|
||||
@@ -2063,6 +2129,15 @@ extra_elf2bin_flags = "--elf-sha256-offset 0xb0"
|
||||
# For chips that support configurable MMU page size feature
|
||||
# If page size is configured to values other than the default "64KB" in menuconfig,
|
||||
mmu_page_size = "64KB"
|
||||
if sdk_config.get("MMU_PAGE_SIZE_8KB", False):
|
||||
mmu_page_size = "8KB"
|
||||
elif sdk_config.get("MMU_PAGE_SIZE_16KB", False):
|
||||
mmu_page_size = "16KB"
|
||||
elif sdk_config.get("MMU_PAGE_SIZE_32KB", False):
|
||||
mmu_page_size = "32KB"
|
||||
else:
|
||||
mmu_page_size = "64KB"
|
||||
|
||||
if sdk_config.get("SOC_MMU_PAGE_SIZE_CONFIGURABLE", False):
|
||||
if board_flash_size == "2MB":
|
||||
mmu_page_size = "32KB"
|
||||
@@ -2091,7 +2166,7 @@ if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c2", "es
|
||||
# Compile Arduino IDF sources
|
||||
#
|
||||
|
||||
if "arduino" in env.get("PIOFRAMEWORK") and "espidf" not in env.get("PIOFRAMEWORK"):
|
||||
if ("arduino" in env.subst("$PIOFRAMEWORK")) and ("espidf" not in env.subst("$PIOFRAMEWORK")):
|
||||
def idf_lib_copy(source, target, env):
|
||||
env_build = join(env["PROJECT_BUILD_DIR"],env["PIOENV"])
|
||||
sdkconfig_h_path = join(env_build,"config","sdkconfig.h")
|
||||
@@ -2147,9 +2222,14 @@ if "arduino" in env.get("PIOFRAMEWORK") and "espidf" not in env.get("PIOFRAMEWOR
|
||||
print("*** Original Arduino \"idf_component.yml\" restored ***")
|
||||
except:
|
||||
print("*** Original Arduino \"idf_component.yml\" couldnt be restored ***")
|
||||
env.AddPostAction("checkprogsize", idf_lib_copy)
|
||||
# Restore original pioarduino-build.py
|
||||
from component_manager import ComponentManager
|
||||
component_manager = ComponentManager(env)
|
||||
component_manager.restore_pioarduino_build_py()
|
||||
silent_action = create_silent_action(idf_lib_copy)
|
||||
env.AddPostAction("checkprogsize", silent_action)
|
||||
|
||||
if "espidf" in env.get("PIOFRAMEWORK") and (flag_custom_component_add == True or flag_custom_component_remove == True):
|
||||
if "espidf" in env.subst("$PIOFRAMEWORK") and (flag_custom_component_add == True or flag_custom_component_remove == True):
|
||||
def idf_custom_component(source, target, env):
|
||||
try:
|
||||
shutil.copy(join(ARDUINO_FRAMEWORK_DIR,"idf_component.yml.orig"),join(ARDUINO_FRAMEWORK_DIR,"idf_component.yml"))
|
||||
@@ -2163,8 +2243,14 @@ if "espidf" in env.get("PIOFRAMEWORK") and (flag_custom_component_add == True or
|
||||
os.remove(join(PROJECT_SRC_DIR,"idf_component.yml"))
|
||||
print("*** pioarduino generated \"idf_component.yml\" removed ***")
|
||||
except:
|
||||
print("*** \"idf_component.yml\" couldnt be removed ***")
|
||||
env.AddPostAction("checkprogsize", idf_custom_component)
|
||||
print("*** no custom \"idf_component.yml\" found for removing ***")
|
||||
if "arduino" in env.subst("$PIOFRAMEWORK"):
|
||||
# Restore original pioarduino-build.py, only used with Arduino
|
||||
from component_manager import ComponentManager
|
||||
component_manager = ComponentManager(env)
|
||||
component_manager.restore_pioarduino_build_py()
|
||||
silent_action = create_silent_action(idf_custom_component)
|
||||
env.AddPostAction("checkprogsize", silent_action)
|
||||
#
|
||||
# Process OTA partition and image
|
||||
#
|
||||
@@ -2219,7 +2305,7 @@ def _parse_size(value):
|
||||
partitions_csv = env.subst("$PARTITIONS_TABLE_CSV")
|
||||
result = []
|
||||
next_offset = 0
|
||||
bound = int(board.get("upload.offset_address", "0x10000"), 16) # default 0x10000
|
||||
bound = 0x10000
|
||||
with open(partitions_csv) as fp:
|
||||
for line in fp.readlines():
|
||||
line = line.strip()
|
||||
|
||||
@@ -37,7 +37,7 @@ def prepare_ulp_env_vars(env):
|
||||
|
||||
toolchain_path = platform.get_package_dir(
|
||||
"toolchain-xtensa-esp-elf"
|
||||
if idf_variant not in ("esp32c6", "esp32p4")
|
||||
if idf_variant not in ("esp32c5","esp32c6", "esp32p4")
|
||||
else "toolchain-riscv32-esp"
|
||||
)
|
||||
|
||||
|
||||
+330
-124
@@ -12,30 +12,46 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import locale
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
from os.path import isfile, join
|
||||
|
||||
from SCons.Script import (
|
||||
ARGUMENTS, COMMAND_LINE_TARGETS, AlwaysBuild, Builder, Default,
|
||||
DefaultEnvironment)
|
||||
ARGUMENTS,
|
||||
COMMAND_LINE_TARGETS,
|
||||
AlwaysBuild,
|
||||
Builder,
|
||||
Default,
|
||||
DefaultEnvironment,
|
||||
)
|
||||
|
||||
from platformio.project.helpers import get_project_dir
|
||||
from platformio.util import get_serial_ports
|
||||
|
||||
# Initialize environment and configuration
|
||||
env = DefaultEnvironment()
|
||||
platform = env.PioPlatform()
|
||||
projectconfig = env.GetProjectConfig()
|
||||
terminal_cp = locale.getpreferredencoding().lower()
|
||||
|
||||
#
|
||||
# Helpers
|
||||
#
|
||||
|
||||
# Framework directory path
|
||||
FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32")
|
||||
|
||||
|
||||
def BeforeUpload(target, source, env):
|
||||
"""
|
||||
Prepare the environment before uploading firmware.
|
||||
Handles port detection and special upload configurations.
|
||||
"""
|
||||
upload_options = {}
|
||||
if "BOARD" in env:
|
||||
upload_options = env.BoardConfig().get("upload", {})
|
||||
|
||||
if not env.subst("$UPLOAD_PORT"):
|
||||
env.AutodetectUploadPort()
|
||||
|
||||
before_ports = get_serial_ports()
|
||||
@@ -47,6 +63,10 @@ def BeforeUpload(target, source, env):
|
||||
|
||||
|
||||
def _get_board_memory_type(env):
|
||||
"""
|
||||
Determine the memory type configuration for the board.
|
||||
Returns the appropriate memory type string based on board configuration.
|
||||
"""
|
||||
board_config = env.BoardConfig()
|
||||
default_type = "%s_%s" % (
|
||||
board_config.get("build.flash_mode", "dio"),
|
||||
@@ -62,24 +82,33 @@ def _get_board_memory_type(env):
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def _normalize_frequency(frequency):
|
||||
"""
|
||||
Convert frequency value to normalized string format (e.g., "40m").
|
||||
Removes 'L' suffix and converts to MHz format.
|
||||
"""
|
||||
frequency = str(frequency).replace("L", "")
|
||||
return str(int(int(frequency) / 1000000)) + "m"
|
||||
|
||||
|
||||
def _get_board_f_flash(env):
|
||||
"""Get the flash frequency for the board."""
|
||||
frequency = env.subst("$BOARD_F_FLASH")
|
||||
return _normalize_frequency(frequency)
|
||||
|
||||
|
||||
def _get_board_f_image(env):
|
||||
"""Get the image frequency for the board, fallback to flash frequency."""
|
||||
board_config = env.BoardConfig()
|
||||
if "build.f_image" in board_config:
|
||||
return _normalize_frequency(board_config.get("build.f_image"))
|
||||
|
||||
return _get_board_f_flash(env)
|
||||
|
||||
|
||||
def _get_board_f_boot(env):
|
||||
"""Get the boot frequency for the board, fallback to flash frequency."""
|
||||
board_config = env.BoardConfig()
|
||||
if "build.f_boot" in board_config:
|
||||
return _normalize_frequency(board_config.get("build.f_boot"))
|
||||
@@ -88,10 +117,11 @@ def _get_board_f_boot(env):
|
||||
|
||||
|
||||
def _get_board_flash_mode(env):
|
||||
if _get_board_memory_type(env) in (
|
||||
"opi_opi",
|
||||
"opi_qspi",
|
||||
):
|
||||
"""
|
||||
Determine the appropriate flash mode for the board.
|
||||
Handles special cases for OPI memory types.
|
||||
"""
|
||||
if _get_board_memory_type(env) in ("opi_opi", "opi_qspi"):
|
||||
return "dout"
|
||||
|
||||
mode = env.subst("$BOARD_FLASH_MODE")
|
||||
@@ -101,6 +131,10 @@ def _get_board_flash_mode(env):
|
||||
|
||||
|
||||
def _get_board_boot_mode(env):
|
||||
"""
|
||||
Determine the boot mode for the board.
|
||||
Handles special cases for OPI memory types.
|
||||
"""
|
||||
memory_type = env.BoardConfig().get("build.arduino.memory_type", "")
|
||||
build_boot = env.BoardConfig().get("build.boot", "$BOARD_FLASH_MODE")
|
||||
if memory_type in ("opi_opi", "opi_qspi"):
|
||||
@@ -109,6 +143,10 @@ def _get_board_boot_mode(env):
|
||||
|
||||
|
||||
def _parse_size(value):
|
||||
"""
|
||||
Parse size values from various formats (int, hex, K/M suffixes).
|
||||
Returns the size in bytes as an integer.
|
||||
"""
|
||||
if isinstance(value, int):
|
||||
return value
|
||||
elif value.isdigit():
|
||||
@@ -122,16 +160,23 @@ def _parse_size(value):
|
||||
|
||||
|
||||
def _parse_partitions(env):
|
||||
"""
|
||||
Parse the partition table CSV file and return partition information.
|
||||
Also sets the application offset for the environment.
|
||||
"""
|
||||
partitions_csv = env.subst("$PARTITIONS_TABLE_CSV")
|
||||
if not isfile(partitions_csv):
|
||||
sys.stderr.write("Could not find the file %s with partitions "
|
||||
"table.\n" % partitions_csv)
|
||||
sys.stderr.write(
|
||||
"Could not find the file %s with partitions table.\n"
|
||||
% partitions_csv
|
||||
)
|
||||
env.Exit(1)
|
||||
return
|
||||
|
||||
result = []
|
||||
next_offset = 0
|
||||
app_offset = int(board.get("upload.offset_address", "0x10000"), 16) # default 0x10000
|
||||
app_offset = 0x10000 # Default address for firmware
|
||||
|
||||
with open(partitions_csv) as fp:
|
||||
for line in fp.readlines():
|
||||
line = line.strip()
|
||||
@@ -148,25 +193,34 @@ def _parse_partitions(env):
|
||||
"subtype": tokens[2],
|
||||
"offset": tokens[3] or calculated_offset,
|
||||
"size": tokens[4],
|
||||
"flags": tokens[5] if len(tokens) > 5 else None
|
||||
"flags": tokens[5] if len(tokens) > 5 else None,
|
||||
}
|
||||
result.append(partition)
|
||||
next_offset = _parse_size(partition["offset"])
|
||||
if (partition["subtype"] == "ota_0"):
|
||||
if partition["subtype"] == "ota_0":
|
||||
app_offset = next_offset
|
||||
next_offset = next_offset + _parse_size(partition["size"])
|
||||
|
||||
# Configure application partition offset
|
||||
env.Replace(ESP32_APP_OFFSET=str(hex(app_offset)))
|
||||
# Propagate application offset to debug configurations
|
||||
env["INTEGRATION_EXTRA_DATA"].update({"application_offset": str(hex(app_offset))})
|
||||
env["INTEGRATION_EXTRA_DATA"].update(
|
||||
{"application_offset": str(hex(app_offset))}
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
def _update_max_upload_size(env):
|
||||
"""
|
||||
Update the maximum upload size based on partition table configuration.
|
||||
Prioritizes user-specified partition names.
|
||||
"""
|
||||
if not env.get("PARTITIONS_TABLE_CSV"):
|
||||
return
|
||||
|
||||
sizes = {
|
||||
p["subtype"]: _parse_size(p["size"]) for p in _parse_partitions(env)
|
||||
p["subtype"]: _parse_size(p["size"])
|
||||
for p in _parse_partitions(env)
|
||||
if p["type"] in ("0", "app")
|
||||
}
|
||||
|
||||
@@ -177,12 +231,15 @@ def _update_max_upload_size(env):
|
||||
if custom_app_partition_name:
|
||||
selected_partition = partitions.get(custom_app_partition_name, {})
|
||||
if selected_partition:
|
||||
board.update("upload.maximum_size", _parse_size(selected_partition["size"]))
|
||||
board.update(
|
||||
"upload.maximum_size", _parse_size(selected_partition["size"])
|
||||
)
|
||||
return
|
||||
else:
|
||||
print(
|
||||
"Warning! Selected partition `%s` is not available in the partition " \
|
||||
"table! Default partition will be used!" % custom_app_partition_name
|
||||
"Warning! Selected partition `%s` is not available in the "
|
||||
"partition table! Default partition will be used!"
|
||||
% custom_app_partition_name
|
||||
)
|
||||
|
||||
for p in partitions.values():
|
||||
@@ -191,20 +248,23 @@ def _update_max_upload_size(env):
|
||||
break
|
||||
|
||||
|
||||
|
||||
def _to_unix_slashes(path):
|
||||
"""Convert Windows-style backslashes to Unix-style forward slashes."""
|
||||
return path.replace("\\", "/")
|
||||
|
||||
|
||||
#
|
||||
# Filesystem helpers
|
||||
#
|
||||
|
||||
|
||||
def fetch_fs_size(env):
|
||||
"""
|
||||
Extract filesystem size and offset information from partition table.
|
||||
Sets FS_START, FS_SIZE, FS_PAGE, and FS_BLOCK environment variables.
|
||||
"""
|
||||
fs = None
|
||||
for p in _parse_partitions(env):
|
||||
if p["type"] == "data" and p["subtype"] in ("spiffs", "fat", "littlefs"):
|
||||
if p["type"] == "data" and p["subtype"] in (
|
||||
"spiffs",
|
||||
"fat",
|
||||
"littlefs",
|
||||
):
|
||||
fs = p
|
||||
if not fs:
|
||||
sys.stderr.write(
|
||||
@@ -213,6 +273,7 @@ def fetch_fs_size(env):
|
||||
)
|
||||
env.Exit(1)
|
||||
return
|
||||
|
||||
env["FS_START"] = _parse_size(fs["offset"])
|
||||
env["FS_SIZE"] = _parse_size(fs["size"])
|
||||
env["FS_PAGE"] = int("0x100", 16)
|
||||
@@ -226,20 +287,37 @@ def fetch_fs_size(env):
|
||||
|
||||
|
||||
def __fetch_fs_size(target, source, env):
|
||||
"""Wrapper function for fetch_fs_size to be used as SCons emitter."""
|
||||
fetch_fs_size(env)
|
||||
return (target, source)
|
||||
|
||||
|
||||
def check_lib_archive_exists():
|
||||
"""
|
||||
Check if lib_archive is set in platformio.ini configuration.
|
||||
Returns True if found, False otherwise.
|
||||
"""
|
||||
for section in projectconfig.sections():
|
||||
if "lib_archive" in projectconfig.options(section):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# Initialize board configuration and MCU settings
|
||||
board = env.BoardConfig()
|
||||
mcu = board.get("build.mcu", "esp32")
|
||||
toolchain_arch = "xtensa-%s" % mcu
|
||||
filesystem = board.get("build.filesystem", "spiffs")
|
||||
if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"):
|
||||
filesystem = board.get("build.filesystem", "littlefs")
|
||||
|
||||
# Set toolchain architecture for RISC-V based ESP32 variants
|
||||
if mcu in ("esp32c2", "esp32c3", "esp32c5", "esp32c6", "esp32h2", "esp32p4"):
|
||||
toolchain_arch = "riscv32-esp"
|
||||
|
||||
# Initialize integration extra data if not present
|
||||
if "INTEGRATION_EXTRA_DATA" not in env:
|
||||
env["INTEGRATION_EXTRA_DATA"] = {}
|
||||
|
||||
# Configure build tools and environment variables
|
||||
env.Replace(
|
||||
__get_board_boot_mode=_get_board_boot_mode,
|
||||
__get_board_f_flash=_get_board_f_flash,
|
||||
@@ -247,7 +325,6 @@ env.Replace(
|
||||
__get_board_f_boot=_get_board_f_boot,
|
||||
__get_board_flash_mode=_get_board_flash_mode,
|
||||
__get_board_memory_type=_get_board_memory_type,
|
||||
|
||||
AR="%s-elf-gcc-ar" % toolchain_arch,
|
||||
AS="%s-elf-as" % toolchain_arch,
|
||||
CC="%s-elf-gcc" % toolchain_arch,
|
||||
@@ -255,7 +332,14 @@ env.Replace(
|
||||
GDB=join(
|
||||
platform.get_package_dir(
|
||||
"tool-riscv32-esp-elf-gdb"
|
||||
if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4")
|
||||
if mcu in (
|
||||
"esp32c2",
|
||||
"esp32c3",
|
||||
"esp32c5",
|
||||
"esp32c6",
|
||||
"esp32h2",
|
||||
"esp32p4",
|
||||
)
|
||||
else "tool-xtensa-esp-elf-gdb"
|
||||
)
|
||||
or "",
|
||||
@@ -265,20 +349,14 @@ env.Replace(
|
||||
OBJCOPY=join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"),
|
||||
RANLIB="%s-elf-gcc-ranlib" % toolchain_arch,
|
||||
SIZETOOL="%s-elf-size" % toolchain_arch,
|
||||
|
||||
ARFLAGS=["rc"],
|
||||
|
||||
SIZEPROGREGEXP=r"^(?:\.iram0\.text|\.iram0\.vectors|\.dram0\.data|\.flash\.text|\.flash\.rodata|)\s+([0-9]+).*",
|
||||
SIZEPROGREGEXP=r"^(?:\.iram0\.text|\.iram0\.vectors|\.dram0\.data|"
|
||||
r"\.flash\.text|\.flash\.rodata|)\s+([0-9]+).*",
|
||||
SIZEDATAREGEXP=r"^(?:\.dram0\.data|\.dram0\.bss|\.noinit)\s+([0-9]+).*",
|
||||
SIZECHECKCMD="$SIZETOOL -A -d $SOURCES",
|
||||
SIZEPRINTCMD="$SIZETOOL -B -d $SOURCES",
|
||||
|
||||
ERASEFLAGS=[
|
||||
"--chip", mcu,
|
||||
"--port", '"$UPLOAD_PORT"'
|
||||
],
|
||||
ERASECMD='"$PYTHONEXE" "$OBJCOPY" $ERASEFLAGS erase_flash',
|
||||
|
||||
ERASEFLAGS=["--chip", mcu, "--port", '"$UPLOAD_PORT"'],
|
||||
ERASECMD='"$PYTHONEXE" "$OBJCOPY" $ERASEFLAGS erase-flash',
|
||||
# mkspiffs package contains two different binaries for IDF and Arduino
|
||||
MKFSTOOL="mk%s" % filesystem
|
||||
+ (
|
||||
@@ -293,46 +371,61 @@ env.Replace(
|
||||
if filesystem == "spiffs"
|
||||
else ""
|
||||
),
|
||||
# Legacy `ESP32_SPIFFS_IMAGE_NAME` is used as the second fallback value for
|
||||
# backward compatibility
|
||||
# Legacy `ESP32_SPIFFS_IMAGE_NAME` is used as the second fallback value
|
||||
# for backward compatibility
|
||||
ESP32_FS_IMAGE_NAME=env.get(
|
||||
"ESP32_FS_IMAGE_NAME", env.get("ESP32_SPIFFS_IMAGE_NAME", filesystem)
|
||||
"ESP32_FS_IMAGE_NAME",
|
||||
env.get("ESP32_SPIFFS_IMAGE_NAME", filesystem),
|
||||
),
|
||||
ESP32_APP_OFFSET=env.get("INTEGRATION_EXTRA_DATA").get(
|
||||
"application_offset"
|
||||
),
|
||||
|
||||
ESP32_APP_OFFSET=env.get("INTEGRATION_EXTRA_DATA").get("application_offset"),
|
||||
ARDUINO_LIB_COMPILE_FLAG="Inactive",
|
||||
|
||||
PROGSUFFIX=".elf"
|
||||
PROGSUFFIX=".elf",
|
||||
)
|
||||
|
||||
# Check if lib_archive is set in platformio.ini and set it to False
|
||||
# if not found. This makes weak defs in framework and libs possible.
|
||||
if not check_lib_archive_exists():
|
||||
env_section = "env:" + env["PIOENV"]
|
||||
projectconfig.set(env_section, "lib_archive", "False")
|
||||
|
||||
# Allow user to override via pre:script
|
||||
if env.get("PROGNAME", "program") == "program":
|
||||
env.Replace(PROGNAME="firmware")
|
||||
|
||||
# Configure build actions and builders
|
||||
env.Append(
|
||||
BUILDERS=dict(
|
||||
ElfToBin=Builder(
|
||||
action=env.VerboseAction(" ".join([
|
||||
action=env.VerboseAction(
|
||||
" ".join(
|
||||
[
|
||||
'"$PYTHONEXE" "$OBJCOPY"',
|
||||
"--chip", mcu, "elf2image",
|
||||
"--flash_mode", "${__get_board_flash_mode(__env__)}",
|
||||
"--flash_freq", "${__get_board_f_image(__env__)}",
|
||||
"--flash_size", board.get("upload.flash_size", "4MB"),
|
||||
"-o", "$TARGET", "$SOURCES"
|
||||
]), "Building $TARGET"),
|
||||
suffix=".bin"
|
||||
"--chip",
|
||||
mcu,
|
||||
"elf2image",
|
||||
"--flash-mode",
|
||||
"${__get_board_flash_mode(__env__)}",
|
||||
"--flash-freq",
|
||||
"${__get_board_f_image(__env__)}",
|
||||
"--flash-size",
|
||||
board.get("upload.flash_size", "4MB"),
|
||||
"-o",
|
||||
"$TARGET",
|
||||
"$SOURCES",
|
||||
]
|
||||
),
|
||||
"Building $TARGET",
|
||||
),
|
||||
suffix=".bin",
|
||||
),
|
||||
DataToBin=Builder(
|
||||
action=env.VerboseAction(
|
||||
" ".join(
|
||||
['"$MKFSTOOL"', "-c", "$SOURCES", "-s", "$FS_SIZE"]
|
||||
+ (
|
||||
[
|
||||
"-p",
|
||||
"$FS_PAGE",
|
||||
"-b",
|
||||
"$FS_BLOCK",
|
||||
]
|
||||
["-p", "$FS_PAGE", "-b", "$FS_BLOCK"]
|
||||
if filesystem in ("littlefs", "spiffs")
|
||||
else []
|
||||
)
|
||||
@@ -347,9 +440,76 @@ env.Append(
|
||||
)
|
||||
)
|
||||
|
||||
# Load framework-specific configuration
|
||||
if not env.get("PIOFRAMEWORK"):
|
||||
env.SConscript("frameworks/_bare.py", exports="env")
|
||||
|
||||
def firmware_metrics(target, source, env):
|
||||
"""
|
||||
Custom target to run esp-idf-size with support for command line parameters
|
||||
Usage: pio run -t metrics -- [esp-idf-size arguments]
|
||||
"""
|
||||
if terminal_cp != "utf-8":
|
||||
print("Firmware metrics can not be shown. Set the terminal codepage to \"utf-8\"")
|
||||
return
|
||||
|
||||
map_file = os.path.join(env.subst("$BUILD_DIR"), env.subst("$PROGNAME") + ".map")
|
||||
if not os.path.isfile(map_file):
|
||||
# map file can be in project dir
|
||||
map_file = os.path.join(get_project_dir(), env.subst("$PROGNAME") + ".map")
|
||||
|
||||
if not os.path.isfile(map_file):
|
||||
print(f"Error: Map file not found: {map_file}")
|
||||
print("Make sure the project is built first with 'pio run'")
|
||||
return
|
||||
|
||||
try:
|
||||
import subprocess
|
||||
import sys
|
||||
import shlex
|
||||
|
||||
cmd = [env.subst("$PYTHONEXE"), "-m", "esp_idf_size", "--ng"]
|
||||
|
||||
# Parameters from platformio.ini
|
||||
extra_args = env.GetProjectOption("custom_esp_idf_size_args", "")
|
||||
if extra_args:
|
||||
cmd.extend(shlex.split(extra_args))
|
||||
|
||||
# Command Line Parameter, after --
|
||||
cli_args = []
|
||||
if "--" in sys.argv:
|
||||
dash_index = sys.argv.index("--")
|
||||
if dash_index + 1 < len(sys.argv):
|
||||
cli_args = sys.argv[dash_index + 1:]
|
||||
cmd.extend(cli_args)
|
||||
|
||||
# Add CLI arguments before the map file
|
||||
if cli_args:
|
||||
cmd.extend(cli_args)
|
||||
|
||||
# Map-file as last argument
|
||||
cmd.append(map_file)
|
||||
|
||||
# Debug-Info if wanted
|
||||
if env.GetProjectOption("custom_esp_idf_size_verbose", False):
|
||||
print(f"Running command: {' '.join(cmd)}")
|
||||
|
||||
# Call esp-idf-size
|
||||
result = subprocess.run(cmd, check=False, capture_output=False)
|
||||
|
||||
if result.returncode != 0:
|
||||
print(f"Warning: esp-idf-size exited with code {result.returncode}")
|
||||
|
||||
except ImportError:
|
||||
print("Error: esp-idf-size module not found.")
|
||||
print("Install with: pip install esp-idf-size")
|
||||
except FileNotFoundError:
|
||||
print("Error: Python executable not found.")
|
||||
print("Check your Python installation.")
|
||||
except Exception as e:
|
||||
print(f"Error: Failed to run firmware metrics: {e}")
|
||||
print("Make sure esp-idf-size is installed: pip install esp-idf-size")
|
||||
|
||||
#
|
||||
# Target: Build executable and linkable firmware or FS image
|
||||
#
|
||||
@@ -364,6 +524,10 @@ if "nobuild" in COMMAND_LINE_TARGETS:
|
||||
target_firm = join("$BUILD_DIR", "${PROGNAME}.bin")
|
||||
else:
|
||||
target_elf = env.BuildProgram()
|
||||
silent_action = env.Action(firmware_metrics)
|
||||
# Hack to silence scons command output
|
||||
silent_action.strfunction = lambda target, source, env: ""
|
||||
env.AddPostAction(target_elf, silent_action)
|
||||
if set(["buildfs", "uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS):
|
||||
target_firm = env.DataToBin(
|
||||
join("$BUILD_DIR", "${ESP32_FS_IMAGE_NAME}"), "$PROJECT_DATA_DIR"
|
||||
@@ -371,26 +535,27 @@ else:
|
||||
env.NoCache(target_firm)
|
||||
AlwaysBuild(target_firm)
|
||||
else:
|
||||
target_firm = env.ElfToBin(
|
||||
join("$BUILD_DIR", "${PROGNAME}"), target_elf)
|
||||
target_firm = env.ElfToBin(join("$BUILD_DIR", "${PROGNAME}"), target_elf)
|
||||
env.Depends(target_firm, "checkprogsize")
|
||||
|
||||
env.AddPlatformTarget("buildfs", target_firm, target_firm, "Build Filesystem Image")
|
||||
# Configure platform targets
|
||||
env.AddPlatformTarget(
|
||||
"buildfs", target_firm, target_firm, "Build Filesystem Image"
|
||||
)
|
||||
AlwaysBuild(env.Alias("nobuild", target_firm))
|
||||
target_buildprog = env.Alias("buildprog", target_firm, target_firm)
|
||||
|
||||
# update max upload size based on CSV file
|
||||
# Update max upload size based on CSV file
|
||||
if env.get("PIOMAINPROG"):
|
||||
env.AddPreAction(
|
||||
"checkprogsize",
|
||||
env.VerboseAction(
|
||||
lambda source, target, env: _update_max_upload_size(env),
|
||||
"Retrieving maximum program size $SOURCES"))
|
||||
"Retrieving maximum program size $SOURCES",
|
||||
),
|
||||
)
|
||||
|
||||
#
|
||||
# Target: Print binary size
|
||||
#
|
||||
|
||||
target_size = env.AddPlatformTarget(
|
||||
"size",
|
||||
target_elf,
|
||||
@@ -399,25 +564,25 @@ target_size = env.AddPlatformTarget(
|
||||
"Calculate program size",
|
||||
)
|
||||
|
||||
#
|
||||
# Target: Upload firmware or FS image
|
||||
#
|
||||
|
||||
upload_protocol = env.subst("$UPLOAD_PROTOCOL")
|
||||
debug_tools = board.get("debug.tools", {})
|
||||
upload_actions = []
|
||||
|
||||
# Compatibility with old OTA configurations
|
||||
if (upload_protocol != "espota"
|
||||
and re.match(r"\"?((([0-9]{1,3}\.){3}[0-9]{1,3})|[^\\/]+\.local)\"?$",
|
||||
env.get("UPLOAD_PORT", ""))):
|
||||
if upload_protocol != "espota" and re.match(
|
||||
r"\"?((([0-9]{1,3}\.){3}[0-9]{1,3})|[^\\/]+\.local)\"?$",
|
||||
env.get("UPLOAD_PORT", ""),
|
||||
):
|
||||
upload_protocol = "espota"
|
||||
sys.stderr.write(
|
||||
"Warning! We have just detected `upload_port` as IP address or host "
|
||||
"name of ESP device. `upload_protocol` is switched to `espota`.\n"
|
||||
"Please specify `upload_protocol = espota` in `platformio.ini` "
|
||||
"project configuration file.\n")
|
||||
"project configuration file.\n"
|
||||
)
|
||||
|
||||
# Configure upload protocol: ESP OTA
|
||||
if upload_protocol == "espota":
|
||||
if not env.subst("$UPLOAD_PORT"):
|
||||
sys.stderr.write(
|
||||
@@ -425,32 +590,45 @@ if upload_protocol == "espota":
|
||||
"using `upload_port` for build environment or use "
|
||||
"global `--upload-port` option.\n"
|
||||
"See https://docs.platformio.org/page/platforms/"
|
||||
"espressif32.html#over-the-air-ota-update\n")
|
||||
"espressif32.html#over-the-air-ota-update\n"
|
||||
)
|
||||
env.Replace(
|
||||
UPLOADER=join(FRAMEWORK_DIR, "tools", "espota.py"),
|
||||
UPLOADERFLAGS=["--debug", "--progress", "-i", "$UPLOAD_PORT"],
|
||||
UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS -f $SOURCE'
|
||||
UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS -f $SOURCE',
|
||||
)
|
||||
if set(["uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS):
|
||||
env.Append(UPLOADERFLAGS=["--spiffs"])
|
||||
upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")]
|
||||
|
||||
# Configure upload protocol: esptool
|
||||
elif upload_protocol == "esptool":
|
||||
env.Replace(
|
||||
UPLOADER=join(
|
||||
platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"),
|
||||
platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"
|
||||
),
|
||||
UPLOADERFLAGS=[
|
||||
"--chip", mcu,
|
||||
"--port", '"$UPLOAD_PORT"',
|
||||
"--baud", "$UPLOAD_SPEED",
|
||||
"--before", board.get("upload.before_reset", "default_reset"),
|
||||
"--after", board.get("upload.after_reset", "hard_reset"),
|
||||
"write_flash", "-z",
|
||||
"--flash_mode", "${__get_board_flash_mode(__env__)}",
|
||||
"--flash_freq", "${__get_board_f_image(__env__)}",
|
||||
"--flash_size", "detect"
|
||||
"--chip",
|
||||
mcu,
|
||||
"--port",
|
||||
'"$UPLOAD_PORT"',
|
||||
"--baud",
|
||||
"$UPLOAD_SPEED",
|
||||
"--before",
|
||||
board.get("upload.before_reset", "default-reset"),
|
||||
"--after",
|
||||
board.get("upload.after_reset", "hard-reset"),
|
||||
"write-flash",
|
||||
"-z",
|
||||
"--flash-mode",
|
||||
"${__get_board_flash_mode(__env__)}",
|
||||
"--flash-freq",
|
||||
"${__get_board_f_image(__env__)}",
|
||||
"--flash-size",
|
||||
"detect",
|
||||
],
|
||||
UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $ESP32_APP_OFFSET $SOURCE'
|
||||
UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS '
|
||||
"$ESP32_APP_OFFSET $SOURCE",
|
||||
)
|
||||
for image in env.get("FLASH_EXTRA_IMAGES", []):
|
||||
env.Append(UPLOADERFLAGS=[image[0], env.subst(image[1])])
|
||||
@@ -458,27 +636,36 @@ elif upload_protocol == "esptool":
|
||||
if "uploadfs" in COMMAND_LINE_TARGETS:
|
||||
env.Replace(
|
||||
UPLOADERFLAGS=[
|
||||
"--chip", mcu,
|
||||
"--port", '"$UPLOAD_PORT"',
|
||||
"--baud", "$UPLOAD_SPEED",
|
||||
"--before", board.get("upload.before_reset", "default_reset"),
|
||||
"--after", board.get("upload.after_reset", "hard_reset"),
|
||||
"write_flash", "-z",
|
||||
"--flash_mode", "${__get_board_flash_mode(__env__)}",
|
||||
"--flash_freq", "${__get_board_f_image(__env__)}",
|
||||
"--flash_size", "detect",
|
||||
"$FS_START"
|
||||
"--chip",
|
||||
mcu,
|
||||
"--port",
|
||||
'"$UPLOAD_PORT"',
|
||||
"--baud",
|
||||
"$UPLOAD_SPEED",
|
||||
"--before",
|
||||
board.get("upload.before_reset", "default-reset"),
|
||||
"--after",
|
||||
board.get("upload.after_reset", "hard-reset"),
|
||||
"write-flash",
|
||||
"-z",
|
||||
"--flash-mode",
|
||||
"${__get_board_flash_mode(__env__)}",
|
||||
"--flash-freq",
|
||||
"${__get_board_f_image(__env__)}",
|
||||
"--flash-size",
|
||||
"detect",
|
||||
"$FS_START",
|
||||
],
|
||||
UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $SOURCE',
|
||||
)
|
||||
|
||||
upload_actions = [
|
||||
env.VerboseAction(BeforeUpload, "Looking for upload port..."),
|
||||
env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")
|
||||
env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE"),
|
||||
]
|
||||
|
||||
# Configure upload protocol: DFU
|
||||
elif upload_protocol == "dfu":
|
||||
|
||||
hwids = board.get("build.hwids", [["0x2341", "0x0070"]])
|
||||
vid = hwids[0][0]
|
||||
pid = hwids[0][1]
|
||||
@@ -493,17 +680,18 @@ elif upload_protocol == "dfu":
|
||||
"-d",
|
||||
",".join(["%s:%s" % (hwid[0], hwid[1]) for hwid in hwids]),
|
||||
"-Q",
|
||||
"-D"
|
||||
"-D",
|
||||
],
|
||||
UPLOADCMD='"$UPLOADER" $UPLOADERFLAGS "$SOURCE"',
|
||||
)
|
||||
|
||||
|
||||
# Configure upload protocol: Debug tools (OpenOCD)
|
||||
elif upload_protocol in debug_tools:
|
||||
_parse_partitions(env)
|
||||
openocd_args = ["-d%d" % (2 if int(ARGUMENTS.get("PIOVERBOSE", 0)) else 1)]
|
||||
openocd_args.extend(
|
||||
debug_tools.get(upload_protocol).get("server").get("arguments", []))
|
||||
debug_tools.get(upload_protocol).get("server").get("arguments", [])
|
||||
)
|
||||
openocd_args.extend(
|
||||
[
|
||||
"-c",
|
||||
@@ -531,7 +719,9 @@ elif upload_protocol in debug_tools:
|
||||
f.replace(
|
||||
"$PACKAGE_DIR",
|
||||
_to_unix_slashes(
|
||||
platform.get_package_dir("tool-openocd-esp32") or ""))
|
||||
platform.get_package_dir("tool-openocd-esp32") or ""
|
||||
),
|
||||
)
|
||||
for f in openocd_args
|
||||
]
|
||||
env.Replace(
|
||||
@@ -541,55 +731,71 @@ elif upload_protocol in debug_tools:
|
||||
)
|
||||
upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")]
|
||||
|
||||
# custom upload tool
|
||||
# Configure upload protocol: Custom
|
||||
elif upload_protocol == "custom":
|
||||
upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")]
|
||||
|
||||
else:
|
||||
sys.stderr.write("Warning! Unknown upload protocol %s\n" % upload_protocol)
|
||||
|
||||
# Register upload targets
|
||||
env.AddPlatformTarget("upload", target_firm, upload_actions, "Upload")
|
||||
env.AddPlatformTarget("uploadfs", target_firm, upload_actions, "Upload Filesystem Image")
|
||||
env.AddPlatformTarget(
|
||||
"uploadfsota", target_firm, upload_actions, "Upload Filesystem Image OTA")
|
||||
"uploadfs", target_firm, upload_actions, "Upload Filesystem Image"
|
||||
)
|
||||
env.AddPlatformTarget(
|
||||
"uploadfsota",
|
||||
target_firm,
|
||||
upload_actions,
|
||||
"Upload Filesystem Image OTA",
|
||||
)
|
||||
|
||||
#
|
||||
# Target: Erase Flash and Upload
|
||||
#
|
||||
|
||||
env.AddPlatformTarget(
|
||||
"erase_upload",
|
||||
target_firm,
|
||||
[
|
||||
env.VerboseAction(BeforeUpload, "Looking for upload port..."),
|
||||
env.VerboseAction("$ERASECMD", "Erasing..."),
|
||||
env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")
|
||||
env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE"),
|
||||
],
|
||||
"Erase Flash and Upload",
|
||||
)
|
||||
|
||||
#
|
||||
# Target: Erase Flash
|
||||
#
|
||||
|
||||
env.AddPlatformTarget(
|
||||
"erase",
|
||||
None,
|
||||
[
|
||||
env.VerboseAction(BeforeUpload, "Looking for upload port..."),
|
||||
env.VerboseAction("$ERASECMD", "Erasing...")
|
||||
env.VerboseAction("$ERASECMD", "Erasing..."),
|
||||
],
|
||||
"Erase Flash",
|
||||
)
|
||||
|
||||
#
|
||||
# Override memory inspection behavior
|
||||
#
|
||||
# Register Custom Target for firmware metrics
|
||||
env.AddCustomTarget(
|
||||
name="metrics",
|
||||
dependencies="$BUILD_DIR/${PROGNAME}.elf",
|
||||
actions=firmware_metrics,
|
||||
title="Firmware Size Metrics",
|
||||
description="Analyze firmware size using esp-idf-size "
|
||||
"(supports CLI args after --)",
|
||||
always_build=True,
|
||||
)
|
||||
|
||||
# Additional Target without Build-Dependency when already compiled
|
||||
env.AddCustomTarget(
|
||||
name="metrics-only",
|
||||
dependencies=None,
|
||||
actions=firmware_metrics,
|
||||
title="Firmware Size Metrics (No Build)",
|
||||
description="Analyze firmware size without building first",
|
||||
always_build=True,
|
||||
)
|
||||
|
||||
# Override memory inspection behavior
|
||||
env.SConscript("sizedata.py", exports="env")
|
||||
|
||||
#
|
||||
# Default targets
|
||||
#
|
||||
|
||||
# Set default targets
|
||||
Default([target_buildprog, target_size])
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# NimBLE_extended_client example using h2zero Arduino NimBLE stack
|
||||
|
||||
BLE 5 client example, using the great [h2zero NimBLE](https://github.com/h2zero/NimBLE-Arduino) implementation.
|
||||
|
||||
Thx @h2zero for the great BLE library.
|
||||
@@ -0,0 +1,53 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env]
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
monitor_speed = 115200
|
||||
build_flags =
|
||||
'-DCONFIG_BT_NIMBLE_EXT_ADV=1'
|
||||
lib_deps =
|
||||
https://github.com/h2zero/NimBLE-Arduino
|
||||
lib_ignore =
|
||||
BLE
|
||||
BluetoothSerial
|
||||
SimpleBLE
|
||||
WiFiProv
|
||||
custom_component_remove =
|
||||
espressif/esp_hosted
|
||||
espressif/esp_wifi_remote
|
||||
espressif/esp-dsp
|
||||
espressif/network_provisioning
|
||||
espressif/esp_rainmaker
|
||||
espressif/rmaker_common
|
||||
espressif/esp_insights
|
||||
espressif/esp_diag_data_store
|
||||
espressif/esp_diagnostics
|
||||
espressif/libsodium
|
||||
espressif/esp-modbus
|
||||
espressif/esp-cbor
|
||||
espressif/esp-sr
|
||||
espressif/esp32-camera
|
||||
|
||||
[env:esp32s3]
|
||||
board = esp32-s3-devkitc-1
|
||||
|
||||
[env:esp32c2]
|
||||
board = esp32-c2-devkitm-1
|
||||
|
||||
[env:esp32c3]
|
||||
board = esp32-c3-devkitm-1
|
||||
|
||||
[env:esp32c6]
|
||||
board = esp32-c6-devkitm-1
|
||||
|
||||
[env:esp32h2]
|
||||
board = esp32-h2-devkitm-1
|
||||
@@ -0,0 +1,150 @@
|
||||
|
||||
/** NimBLE Extended Client Demo:
|
||||
*
|
||||
* Demonstrates the Bluetooth 5.x client capabilities.
|
||||
*
|
||||
* Created: on April 2 2022
|
||||
* Author: H2zero
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <NimBLEDevice.h>
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
# error Must enable extended advertising, see nimconfig.h file.
|
||||
#endif
|
||||
|
||||
#define SERVICE_UUID "ABCD"
|
||||
#define CHARACTERISTIC_UUID "1234"
|
||||
|
||||
static const NimBLEAdvertisedDevice* advDevice;
|
||||
static bool doConnect = false;
|
||||
static uint32_t scanTime = 10 * 1000; // In milliseconds, 0 = scan forever
|
||||
|
||||
/** Define the PHY's to use when connecting to peer devices, can be 1, 2, or all 3 (default).*/
|
||||
static uint8_t connectPhys = BLE_GAP_LE_PHY_CODED_MASK | BLE_GAP_LE_PHY_1M_MASK /*| BLE_GAP_LE_PHY_2M_MASK */;
|
||||
|
||||
/** Define a class to handle the callbacks for client connection events */
|
||||
class ClientCallbacks : public NimBLEClientCallbacks {
|
||||
void onConnect(NimBLEClient* pClient) override { Serial.printf("Connected\n"); };
|
||||
|
||||
void onDisconnect(NimBLEClient* pClient, int reason) override {
|
||||
Serial.printf("%s Disconnected, reason = %d - Starting scan\n", pClient->getPeerAddress().toString().c_str(), reason);
|
||||
NimBLEDevice::getScan()->start(scanTime);
|
||||
}
|
||||
} clientCallbacks;
|
||||
|
||||
/** Define a class to handle the callbacks when advertisements are received */
|
||||
class scanCallbacks : public NimBLEScanCallbacks {
|
||||
void onResult(const NimBLEAdvertisedDevice* advertisedDevice) override {
|
||||
Serial.printf("Advertised Device found: %s\n", advertisedDevice->toString().c_str());
|
||||
if (advertisedDevice->isAdvertisingService(NimBLEUUID("ABCD"))) {
|
||||
Serial.printf("Found Our Service\n");
|
||||
doConnect = true;
|
||||
/** Save the device reference in a global for the client to use*/
|
||||
advDevice = advertisedDevice;
|
||||
/** stop scan before connecting */
|
||||
NimBLEDevice::getScan()->stop();
|
||||
}
|
||||
}
|
||||
|
||||
/** Callback to process the results of the completed scan or restart it */
|
||||
void onScanEnd(const NimBLEScanResults& results, int rc) override { Serial.printf("Scan Ended\n"); }
|
||||
} scanCallbacks;
|
||||
|
||||
/** Handles the provisioning of clients and connects / interfaces with the server */
|
||||
bool connectToServer() {
|
||||
NimBLEClient* pClient = nullptr;
|
||||
|
||||
pClient = NimBLEDevice::createClient();
|
||||
pClient->setClientCallbacks(&clientCallbacks, false);
|
||||
|
||||
/**
|
||||
* Set the PHY's to use for this connection. This is a bitmask that represents the PHY's:
|
||||
* * 0x01 BLE_GAP_LE_PHY_1M_MASK
|
||||
* * 0x02 BLE_GAP_LE_PHY_2M_MASK
|
||||
* * 0x04 BLE_GAP_LE_PHY_CODED_MASK
|
||||
* Combine these with OR ("|"), eg BLE_GAP_LE_PHY_1M_MASK | BLE_GAP_LE_PHY_2M_MASK | BLE_GAP_LE_PHY_CODED_MASK;
|
||||
*/
|
||||
pClient->setConnectPhy(connectPhys);
|
||||
|
||||
/** Set how long we are willing to wait for the connection to complete (milliseconds), default is 30000. */
|
||||
pClient->setConnectTimeout(10 * 1000);
|
||||
|
||||
if (!pClient->connect(advDevice)) {
|
||||
/** Created a client but failed to connect, don't need to keep it as it has no data */
|
||||
NimBLEDevice::deleteClient(pClient);
|
||||
Serial.printf("Failed to connect, deleted client\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
Serial.printf("Connected to: %s RSSI: %d\n", pClient->getPeerAddress().toString().c_str(), pClient->getRssi());
|
||||
|
||||
/** Now we can read/write/subscribe the characteristics of the services we are interested in */
|
||||
NimBLERemoteService* pSvc = nullptr;
|
||||
NimBLERemoteCharacteristic* pChr = nullptr;
|
||||
|
||||
pSvc = pClient->getService(SERVICE_UUID);
|
||||
if (pSvc) {
|
||||
pChr = pSvc->getCharacteristic(CHARACTERISTIC_UUID);
|
||||
if (pChr) {
|
||||
if (pChr->canRead()) {
|
||||
std::string value = pChr->readValue();
|
||||
Serial.printf("Characteristic value: %s\n", value.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
Serial.printf("ABCD service not found.\n");
|
||||
}
|
||||
|
||||
NimBLEDevice::deleteClient(pClient);
|
||||
Serial.printf("Done with this device!\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.printf("Starting NimBLE Client\n");
|
||||
|
||||
/** Initialize NimBLE and set the device name */
|
||||
NimBLEDevice::init("NimBLE Extended Client");
|
||||
|
||||
/** Create aNimBLE Scan instance and set the callbacks for scan events */
|
||||
NimBLEScan* pScan = NimBLEDevice::getScan();
|
||||
pScan->setScanCallbacks(&scanCallbacks);
|
||||
|
||||
/** Set scan interval (how often) and window (how long) in milliseconds */
|
||||
pScan->setInterval(97);
|
||||
pScan->setWindow(67);
|
||||
|
||||
/**
|
||||
* Active scan will gather scan response data from advertisers
|
||||
* but will use more energy from both devices
|
||||
*/
|
||||
pScan->setActiveScan(true);
|
||||
|
||||
/**
|
||||
* Start scanning for advertisers for the scan time specified (in milliseconds) 0 = forever
|
||||
* Optional callback for when scanning stops.
|
||||
*/
|
||||
pScan->start(scanTime);
|
||||
|
||||
Serial.printf("Scanning for peripherals\n");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
/** Loop here until we find a device we want to connect to */
|
||||
if (doConnect) {
|
||||
if (connectToServer()) {
|
||||
Serial.printf("Success!, scanning for more!\n");
|
||||
} else {
|
||||
Serial.printf("Failed to connect, starting scan\n");
|
||||
}
|
||||
|
||||
doConnect = false;
|
||||
NimBLEDevice::getScan()->start(scanTime);
|
||||
}
|
||||
|
||||
delay(10);
|
||||
}
|
||||
@@ -12,6 +12,10 @@ platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32-solo1
|
||||
build_flags = -DLED_BUILTIN=2
|
||||
lib_ignore = wifi
|
||||
spiffs
|
||||
NetworkClientSecure
|
||||
|
||||
custom_component_remove =
|
||||
espressif/esp_hosted
|
||||
espressif/esp_wifi_remote
|
||||
@@ -31,6 +35,9 @@ platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32-c2-devkitm-1
|
||||
monitor_speed = 115200
|
||||
lib_ignore = wifi
|
||||
spiffs
|
||||
NetworkClientSecure
|
||||
custom_component_remove = espressif/esp_hosted
|
||||
espressif/esp_wifi_remote
|
||||
espressif/esp-dsp
|
||||
@@ -43,12 +50,16 @@ custom_component_remove = espressif/esp_hosted
|
||||
espressif/esp_diagnostics
|
||||
espressif/esp_rainmaker
|
||||
espressif/rmaker_common
|
||||
custom_component_add = espressif/cmake_utilities @ 0.*
|
||||
|
||||
[env:esp32-s3-arduino_nano_esp32]
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = arduino_nano_esp32
|
||||
monitor_speed = 115200
|
||||
lib_ignore = wifi
|
||||
spiffs
|
||||
NetworkClientSecure
|
||||
custom_component_remove = espressif/esp_hosted
|
||||
espressif/esp_wifi_remote
|
||||
espressif/esp-dsp
|
||||
@@ -67,6 +78,9 @@ custom_component_remove = espressif/esp_hosted
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32s3_120_16_8-qio_opi
|
||||
lib_ignore =
|
||||
spiffs
|
||||
NetworkClientSecure
|
||||
custom_sdkconfig = CONFIG_SPIRAM_MODE_OCT=y
|
||||
CONFIG_SPIRAM_SPEED_120M=y
|
||||
CONFIG_LCD_RGB_ISR_IRAM_SAFE=y
|
||||
@@ -87,13 +101,16 @@ custom_component_remove = espressif/esp_hosted
|
||||
espressif/esp_diagnostics
|
||||
espressif/esp_rainmaker
|
||||
espressif/rmaker_common
|
||||
custom_component_add = lvgl/lvgl @ ^9.2.2
|
||||
|
||||
[env:esp32-c6-devkitc-1]
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
build_type = debug
|
||||
board = esp32-c6-devkitc-1
|
||||
monitor_speed = 115200
|
||||
lib_ignore = wifi
|
||||
spiffs
|
||||
NetworkClientSecure
|
||||
custom_component_remove = espressif/esp_hosted
|
||||
espressif/esp_wifi_remote
|
||||
espressif/mdns
|
||||
@@ -106,6 +123,9 @@ platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32-h2-devkitm-1
|
||||
monitor_speed = 115200
|
||||
lib_ignore =
|
||||
spiffs
|
||||
NetworkClientSecure
|
||||
custom_component_remove = espressif/esp_hosted
|
||||
espressif/esp_wifi_remote
|
||||
espressif/mdns
|
||||
@@ -118,6 +138,9 @@ platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32-p4
|
||||
build_flags = -DLED_BUILTIN=2
|
||||
lib_ignore = wifi
|
||||
spiffs
|
||||
NetworkClientSecure
|
||||
monitor_speed = 115200
|
||||
custom_component_remove = espressif/esp_hosted
|
||||
espressif/esp_wifi_remote
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32-s2-saola-1
|
||||
lib_ignore = wifi
|
||||
spiffs
|
||||
NetworkClientSecure
|
||||
build_flags = -DBUILTIN_RGBLED_PIN=18
|
||||
-DNR_OF_LEDS=1
|
||||
|
||||
@@ -9,6 +12,9 @@ build_flags = -DBUILTIN_RGBLED_PIN=18
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32-s3-devkitc-1
|
||||
lib_ignore = wifi
|
||||
spiffs
|
||||
NetworkClientSecure
|
||||
build_flags = -DBUILTIN_RGBLED_PIN=48
|
||||
-DNR_OF_LEDS=1
|
||||
|
||||
@@ -16,6 +22,9 @@ build_flags = -DBUILTIN_RGBLED_PIN=48
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32-c3-devkitm-1
|
||||
lib_ignore = wifi
|
||||
spiffs
|
||||
NetworkClientSecure
|
||||
build_flags = -DBUILTIN_RGBLED_PIN=8
|
||||
-DNR_OF_LEDS=1
|
||||
|
||||
@@ -23,5 +32,8 @@ build_flags = -DBUILTIN_RGBLED_PIN=8
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32-c6-devkitm-1
|
||||
lib_ignore = wifi
|
||||
spiffs
|
||||
NetworkClientSecure
|
||||
build_flags = -DBUILTIN_RGBLED_PIN=8
|
||||
-DNR_OF_LEDS=1
|
||||
|
||||
@@ -12,3 +12,51 @@ platform = espressif32
|
||||
framework = arduino
|
||||
board = esp-wrover-kit
|
||||
monitor_speed = 115200
|
||||
|
||||
[env:esp32-s2]
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32-s2-saola-1
|
||||
upload_protocol = esp-prog
|
||||
monitor_speed = 115200
|
||||
check_tool = clangtidy
|
||||
|
||||
[env:esp32-s3]
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32-s3-devkitc-1
|
||||
upload_protocol = esp-builtin
|
||||
monitor_speed = 115200
|
||||
check_tool = cppcheck
|
||||
|
||||
[env:esp32-c2]
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32-c2-devkitm-1
|
||||
upload_protocol = esp-prog
|
||||
monitor_speed = 115200
|
||||
check_tool = clangtidy
|
||||
custom_component_remove =
|
||||
espressif/esp-dsp
|
||||
espressif/network_provisioning
|
||||
espressif/esp-zboss-lib
|
||||
espressif/esp-zigbee-lib
|
||||
espressif/esp_rainmaker
|
||||
espressif/esp-sr
|
||||
espressif/esp-modbus
|
||||
espressif/esp32-camera
|
||||
|
||||
[env:esp32-c3]
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32-c3-devkitm-1
|
||||
upload_protocol = esp-builtin
|
||||
monitor_speed = 115200
|
||||
check_tool = pvs-studio
|
||||
|
||||
[env:esp32-c6]
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32-c6-devkitm-1
|
||||
upload_protocol = esp-builtin
|
||||
monitor_speed = 115200
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
.pio
|
||||
.vscode
|
||||
@@ -1,4 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.16.0)
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
add_compile_definitions(ARDUINO_ARCH_ESP32=1)
|
||||
project(Arduino_IDF_BLE_scan)
|
||||
@@ -1,7 +0,0 @@
|
||||
# Arduino_IDF_BLE_scan example using 3rd party NimBLE stack
|
||||
|
||||
BLE scan example, using the great h2zero NimBLE implementation. The needed NimBLE lib is loaded via the IDF component manager -> `idf_component.yml`.
|
||||
Mandantory not to forget to switch Arduino included BLE libs.
|
||||
Done in `sdkconfig.defaults`
|
||||
|
||||
Thx @h2zero for the great BLE library.
|
||||
@@ -1,27 +0,0 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env]
|
||||
platform = espressif32
|
||||
framework = arduino, espidf
|
||||
monitor_speed = 115200
|
||||
board_build.embed_txtfiles =
|
||||
managed_components/espressif__esp_insights/server_certs/https_server.crt
|
||||
managed_components/espressif__esp_rainmaker/server_certs/rmaker_mqtt_server.crt
|
||||
managed_components/espressif__esp_rainmaker/server_certs/rmaker_claim_service_server.crt
|
||||
managed_components/espressif__esp_rainmaker/server_certs/rmaker_ota_server.crt
|
||||
lib_ignore =
|
||||
BLE
|
||||
BluetoothSerial
|
||||
SimpleBLE
|
||||
WiFiProv
|
||||
|
||||
[env:esp32]
|
||||
board = esp32dev
|
||||
@@ -1,34 +0,0 @@
|
||||
# CONFIG_AUTOSTART_ARDUINO is not set
|
||||
# CONFIG_WS2812_LED_ENABLE is not set
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_MBEDTLS_PSK_MODES=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y
|
||||
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y
|
||||
|
||||
# Override some defaults so BT stack is enabled
|
||||
# in this example
|
||||
#
|
||||
# BT config
|
||||
#
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
|
||||
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
|
||||
CONFIG_BTDM_CTRL_MODE_BTDM=n
|
||||
CONFIG_BT_BLUEDROID_ENABLED=n
|
||||
CONFIG_BT_NIMBLE_ENABLED=y
|
||||
|
||||
#
|
||||
# Arduino Configuration
|
||||
#
|
||||
#
|
||||
# Disable all Arduino included BLE libraries
|
||||
#
|
||||
CONFIG_ARDUINO_SELECTIVE_COMPILATION=y
|
||||
# CONFIG_ARDUINO_SELECTIVE_WiFiProv is not set
|
||||
# CONFIG_ARDUINO_SELECTIVE_BLE is not set
|
||||
# CONFIG_ARDUINO_SELECTIVE_BluetoothSerial is not set
|
||||
# CONFIG_ARDUINO_SELECTIVE_SimpleBLE is not set
|
||||
# end of Arduino Configuration
|
||||
@@ -1,6 +0,0 @@
|
||||
# This file was automatically generated for projects
|
||||
# without default 'CMakeLists.txt' file.
|
||||
|
||||
FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*)
|
||||
|
||||
idf_component_register(SRCS ${app_sources})
|
||||
@@ -1,41 +0,0 @@
|
||||
dependencies:
|
||||
# Required IDF version
|
||||
idf: ">=4.4"
|
||||
|
||||
esp-nimble-cpp:
|
||||
git: https://github.com/h2zero/esp-nimble-cpp.git
|
||||
version: 877a29a8b1d0022c5e8f67ba8b879316e67b6c3d
|
||||
|
||||
|
||||
# # Defining a dependency from the registry:
|
||||
# # https://components.espressif.com/component/example/cmp
|
||||
# example/cmp: "^3.3.3" # Automatically update minor releases
|
||||
#
|
||||
# # Other ways to define dependencies
|
||||
#
|
||||
# # For components maintained by Espressif only name can be used.
|
||||
# # Same as `espressif/cmp`
|
||||
# component: "~1.0.0" # Automatically update bugfix releases
|
||||
#
|
||||
# # Or in a longer form with extra parameters
|
||||
# component2:
|
||||
# version: ">=2.0.0"
|
||||
#
|
||||
# # For transient dependencies `public` flag can be set.
|
||||
# # `public` flag doesn't have an effect for the `main` component.
|
||||
# # All dependencies of `main` are public by default.
|
||||
# public: true
|
||||
#
|
||||
# # For components hosted on non-default registry:
|
||||
# service_url: "https://componentregistry.company.com"
|
||||
#
|
||||
# # For components in git repository:
|
||||
# test_component:
|
||||
# path: test_component
|
||||
# git: ssh://git@gitlab.com/user/components.git
|
||||
#
|
||||
# # For test projects during component development
|
||||
# # components can be used from a local directory
|
||||
# # with relative or absolute path
|
||||
# some_local_component:
|
||||
# path: ../../projects/component
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
|
||||
Ported to Arduino ESP32 by Evandro Copercini
|
||||
Refactored back to IDF by H2zero
|
||||
*/
|
||||
|
||||
/** NimBLE differences highlighted in comment blocks **/
|
||||
|
||||
/*******original********
|
||||
#include <BLEDevice.h>
|
||||
#include <BLEUtils.h>
|
||||
#include <BLEScan.h>
|
||||
#include <BLEAdvertisedDevice.h>
|
||||
***********************/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <NimBLEDevice.h>
|
||||
|
||||
extern "C"{void app_main(void);}
|
||||
|
||||
int scanTime = 5 * 1000; // In milliseconds, 0 = scan forever
|
||||
BLEScan* pBLEScan;
|
||||
|
||||
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
|
||||
void onResult(BLEAdvertisedDevice* advertisedDevice) {
|
||||
printf("Advertised Device: %s \n", advertisedDevice->toString().c_str());
|
||||
}
|
||||
};
|
||||
|
||||
void scanTask (void * parameter){
|
||||
for(;;) {
|
||||
// put your main code here, to run repeatedly:
|
||||
BLEScanResults foundDevices = pBLEScan->getResults(scanTime, false);
|
||||
printf("Devices found: %d\n", foundDevices.getCount());
|
||||
printf("Scan done!\n");
|
||||
pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory
|
||||
vTaskDelay(2000/portTICK_PERIOD_MS); // Delay a second between loops.
|
||||
}
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main(void) {
|
||||
printf("Scanning...\n");
|
||||
|
||||
BLEDevice::init("");
|
||||
pBLEScan = BLEDevice::getScan(); //create new scan
|
||||
pBLEScan->setScanCallbacks(new MyAdvertisedDeviceCallbacks());
|
||||
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
|
||||
pBLEScan->setInterval(100);
|
||||
pBLEScan->setWindow(99); // less or equal setInterval value
|
||||
xTaskCreate(scanTask, "scanTask", 5000, NULL, 1, NULL);
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16.0)
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
set(PROJECT_VER "1.0")
|
||||
set(PROJECT_VER_NUMBER 1)
|
||||
|
||||
project(matter-light)
|
||||
# This should be done before using the IDF_TARGET variable.
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
project(espidf_arduino_matter_light)
|
||||
|
||||
# WARNING: This is just an example for using key for decrypting the encrypted OTA image
|
||||
# Please do not use it as is.
|
||||
@@ -16,7 +20,7 @@ if(CONFIG_IDF_TARGET_ESP32C2)
|
||||
include(relinker)
|
||||
endif()
|
||||
|
||||
idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++17;-Os;-DCHIP_HAVE_CONFIG_H" APPEND)
|
||||
idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++2a;-Os;-DCHIP_HAVE_CONFIG_H" APPEND)
|
||||
idf_build_set_property(C_COMPILE_OPTIONS "-Os" APPEND)
|
||||
# For RISCV chips, project_include.cmake sets -Wno-format, but does not clear various
|
||||
# flags that depend on -Wformat
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
| Supported Targets | ESP32-S3 | ESP32-C3 | ESP32-C6 |
|
||||
| ----------------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32-C3 | ESP32-C6 |
|
||||
| ----------------- | -------- | -------- |
|
||||
|
||||
|
||||
# Managed Component Light
|
||||
|
||||
This example is configured by default to work with the ESP32-S3, which has the RGB LED GPIO set as pin 48 and the BOOT button on GPIO 0.
|
||||
This example is configured by default to work with the ESP32-C6, which has the RGB LED GPIO set as pin 8 and the BOOT button on GPIO 9.
|
||||
|
||||
This example creates a Color Temperature Light device using the esp_matter component downloaded from the [Espressif Component Registry](https://components.espressif.com/) instead of an extra component locally, so the example can work without setting up the esp-matter environment.
|
||||
|
||||
See the [docs](https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html) for more information about building and flashing the firmware.
|
||||
This example creates a Color Temperature Light device using the esp_matter component automatically downloaded from the [Espressif Component Registry](https://components.espressif.com/). See the [docs](https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html) for more information about matter.
|
||||
|
||||
The code is based on the Arduino API and uses Arduino as an IDF Component.
|
||||
|
||||
@@ -27,8 +25,8 @@ There is no QR Code to be used when the Smartphone APP wants to add the Matter D
|
||||
Please enter the code manually: `34970112332`
|
||||
|
||||
The devboard has a built-in LED that will be used as the Matter Light.
|
||||
The default setting of the code uses pin 48 for the ESP32-S3.
|
||||
Please change it in `main/matter_accessory_driver.h` or in the `sdkconfig.defaults.<SOC>` file.
|
||||
The default setting of the code uses pin 8 for the ESP32-C6,
|
||||
Please change it in `main/matter_accessory_driver.h` or in the `sdkconfig.defaults` file.
|
||||
|
||||
## LED Status and Factory Mode
|
||||
|
||||
@@ -53,10 +51,9 @@ Holding the BOOT button pressed for more than 10 seconds and then releasing it w
|
||||
|
||||
## Building the Application using WiFi and Matter
|
||||
|
||||
Use ESP-IDF 5.1.4 from https://github.com/espressif/esp-idf/tree/release/v5.1
|
||||
This example has been tested with Arduino Core 3.0.4
|
||||
This example has been tested with Arduino Core 3.2.0. It should work with newer versions too.
|
||||
|
||||
There is a configuration file for these SoC: esp32s3, esp32c3, esp32c6.
|
||||
There is a configuration file for these SoCs: esp32c3, esp32c6.
|
||||
Those are the tested devices that have a WS2812 RGB LED and can run BLE, WiFi and Matter.
|
||||
|
||||
In case it is necessary to change the Button Pin or the REG LED Pin, please use the `menuconfig` and change the Menu Option `Light Matter Accessory`
|
||||
@@ -64,5 +61,5 @@ In case it is necessary to change the Button Pin or the REG LED Pin, please use
|
||||
## Using OpenThread with Matter
|
||||
|
||||
This is possible with the ESP32-C6.
|
||||
It is neessasy to have a Thread Border Routed in the Matter Environment. Check you matter hardware provider.
|
||||
It is necessary to have a Thread Border Router in the Matter Environment. Check your Matter hardware provider.
|
||||
|
||||
|
||||
@@ -3,83 +3,32 @@ menu "Light Matter Accessory"
|
||||
config BUTTON_PIN
|
||||
int
|
||||
prompt "Button 1 GPIO"
|
||||
default ENV_GPIO_BOOT_BUTTON
|
||||
default 9 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C6
|
||||
default 0
|
||||
range -1 ENV_GPIO_IN_RANGE_MAX
|
||||
help
|
||||
The GPIO pin for button that will be used to turn on/off the Matter Light. It shall be connected to a push button. It can use the BOOT button of the development board.
|
||||
endmenu
|
||||
|
||||
|
||||
menu "LEDs"
|
||||
config WS2812_PIN
|
||||
int
|
||||
prompt "WS2812 RGB LED GPIO"
|
||||
default ENV_GPIO_RGB_LED
|
||||
default 8 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C6
|
||||
default 48
|
||||
range -1 ENV_GPIO_OUT_RANGE_MAX
|
||||
help
|
||||
The GPIO pin for the Matter Light that will be driven by RMT. It shall be connected to one single WS2812 RGB LED.
|
||||
endmenu
|
||||
|
||||
# TARGET CONFIGURATION
|
||||
if IDF_TARGET_ESP32C3
|
||||
config ENV_GPIO_RANGE_MIN
|
||||
int
|
||||
default 0
|
||||
|
||||
config ENV_GPIO_RANGE_MAX
|
||||
int
|
||||
default 19
|
||||
# GPIOs 20/21 are always used by UART in examples
|
||||
|
||||
config ENV_GPIO_IN_RANGE_MAX
|
||||
int
|
||||
default ENV_GPIO_RANGE_MAX
|
||||
|
||||
config ENV_GPIO_OUT_RANGE_MAX
|
||||
int
|
||||
default ENV_GPIO_RANGE_MAX
|
||||
|
||||
config ENV_GPIO_BOOT_BUTTON
|
||||
int
|
||||
default 9
|
||||
|
||||
config ENV_GPIO_RGB_LED
|
||||
int
|
||||
default 8
|
||||
endif
|
||||
if IDF_TARGET_ESP32C6
|
||||
config ENV_GPIO_RANGE_MIN
|
||||
int
|
||||
default 0
|
||||
|
||||
config ENV_GPIO_RANGE_MAX
|
||||
int
|
||||
default 30
|
||||
# GPIOs 16/17 are always used by UART in examples
|
||||
|
||||
config ENV_GPIO_IN_RANGE_MAX
|
||||
int
|
||||
default ENV_GPIO_RANGE_MAX
|
||||
|
||||
config ENV_GPIO_OUT_RANGE_MAX
|
||||
int
|
||||
default ENV_GPIO_RANGE_MAX
|
||||
|
||||
config ENV_GPIO_BOOT_BUTTON
|
||||
int
|
||||
default 9
|
||||
|
||||
config ENV_GPIO_RGB_LED
|
||||
int
|
||||
default 8
|
||||
endif
|
||||
if IDF_TARGET_ESP32S3
|
||||
config ENV_GPIO_RANGE_MIN
|
||||
int
|
||||
default 0
|
||||
|
||||
config ENV_GPIO_RANGE_MAX
|
||||
int
|
||||
default 19 if IDF_TARGET_ESP32C3
|
||||
default 30 if IDF_TARGET_ESP32C6
|
||||
default 48
|
||||
|
||||
config ENV_GPIO_IN_RANGE_MAX
|
||||
@@ -90,13 +39,4 @@ menu "Light Matter Accessory"
|
||||
int
|
||||
default ENV_GPIO_RANGE_MAX
|
||||
|
||||
config ENV_GPIO_BOOT_BUTTON
|
||||
int
|
||||
default 0
|
||||
|
||||
config ENV_GPIO_RGB_LED
|
||||
int
|
||||
default 48
|
||||
endif
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -18,36 +18,26 @@ typedef struct {
|
||||
} HS_color_t;
|
||||
|
||||
static const HS_color_t temperatureTable[] = {
|
||||
{4, 100}, {8, 100}, {11, 100}, {14, 100}, {16, 100}, {18, 100}, {20, 100}, {22, 100}, {24, 100}, {25, 100},
|
||||
{27, 100}, {28, 100}, {30, 100}, {31, 100}, {31, 95}, {30, 89}, {30, 85}, {29, 80}, {29, 76}, {29, 73},
|
||||
{29, 69}, {28, 66}, {28, 63}, {28, 60}, {28, 57}, {28, 54}, {28, 52}, {27, 49}, {27, 47}, {27, 45},
|
||||
{27, 43}, {27, 41}, {27, 39}, {27, 37}, {27, 35}, {27, 33}, {27, 31}, {27, 30}, {27, 28}, {27, 26},
|
||||
{27, 25}, {27, 23}, {27, 22}, {27, 21}, {27, 19}, {27, 18}, {27, 17}, {27, 15}, {28, 14}, {28, 13},
|
||||
{28, 12}, {29, 10}, {29, 9}, {30, 8}, {31, 7}, {32, 6}, {34, 5}, {36, 4}, {41, 3}, {49, 2},
|
||||
{0, 0}, {294, 2}, {265, 3}, {251, 4}, {242, 5}, {237, 6}, {233, 7}, {231, 8}, {229, 9}, {228, 10},
|
||||
{227, 11}, {226, 11}, {226, 12}, {225, 13}, {225, 13}, {224, 14}, {224, 14}, {224, 15}, {224, 15}, {223, 16},
|
||||
{223, 16}, {223, 17}, {223, 17}, {223, 17}, {222, 18}, {222, 18}, {222, 19}, {222, 19}, {222, 19}, {222, 19},
|
||||
{222, 20}, {222, 20}, {222, 20}, {222, 21}, {222, 21}
|
||||
{4, 100}, {8, 100}, {11, 100}, {14, 100}, {16, 100}, {18, 100}, {20, 100}, {22, 100}, {24, 100}, {25, 100}, {27, 100}, {28, 100}, {30, 100}, {31, 100},
|
||||
{31, 95}, {30, 89}, {30, 85}, {29, 80}, {29, 76}, {29, 73}, {29, 69}, {28, 66}, {28, 63}, {28, 60}, {28, 57}, {28, 54}, {28, 52}, {27, 49},
|
||||
{27, 47}, {27, 45}, {27, 43}, {27, 41}, {27, 39}, {27, 37}, {27, 35}, {27, 33}, {27, 31}, {27, 30}, {27, 28}, {27, 26}, {27, 25}, {27, 23},
|
||||
{27, 22}, {27, 21}, {27, 19}, {27, 18}, {27, 17}, {27, 15}, {28, 14}, {28, 13}, {28, 12}, {29, 10}, {29, 9}, {30, 8}, {31, 7}, {32, 6},
|
||||
{34, 5}, {36, 4}, {41, 3}, {49, 2}, {0, 0}, {294, 2}, {265, 3}, {251, 4}, {242, 5}, {237, 6}, {233, 7}, {231, 8}, {229, 9}, {228, 10},
|
||||
{227, 11}, {226, 11}, {226, 12}, {225, 13}, {225, 13}, {224, 14}, {224, 14}, {224, 15}, {224, 15}, {223, 16}, {223, 16}, {223, 17}, {223, 17}, {223, 17},
|
||||
{222, 18}, {222, 18}, {222, 19}, {222, 19}, {222, 19}, {222, 19}, {222, 20}, {222, 20}, {222, 20}, {222, 21}, {222, 21}
|
||||
};
|
||||
|
||||
/* step brightness table: gamma = 2.3 */
|
||||
static const uint8_t gamma_table[MAX_PROGRESS] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2,
|
||||
2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5,
|
||||
5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
|
||||
10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17,
|
||||
17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25, 25, 26,
|
||||
26, 27, 28, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 36, 36, 37,
|
||||
38, 39, 40, 40, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
|
||||
68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 81, 82, 83, 84, 86,
|
||||
87, 88, 89, 91, 92, 93, 95, 96, 97, 99, 100, 101, 103, 104, 105, 107,
|
||||
108, 110, 111, 112, 114, 115, 117, 118, 120, 121, 123, 124, 126, 128, 129, 131,
|
||||
132, 134, 135, 137, 139, 140, 142, 144, 145, 147, 149, 150, 152, 154, 156, 157,
|
||||
159, 161, 163, 164, 166, 168, 170, 172, 174, 175, 177, 179, 181, 183, 185, 187,
|
||||
189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219,
|
||||
221, 223, 226, 228, 230, 232, 234, 236, 239, 241, 243, 245, 248, 250, 252, 255,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8,
|
||||
8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20,
|
||||
21, 22, 22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38, 39, 40, 40,
|
||||
41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
|
||||
69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 81, 82, 83, 84, 86, 87, 88, 89, 91, 92, 93, 95, 96, 97, 99, 100, 101, 103, 104,
|
||||
105, 107, 108, 110, 111, 112, 114, 115, 117, 118, 120, 121, 123, 124, 126, 128, 129, 131, 132, 134, 135, 137, 139, 140, 142, 144, 145, 147, 149,
|
||||
150, 152, 154, 156, 157, 159, 161, 163, 164, 166, 168, 170, 172, 174, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203,
|
||||
205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 226, 228, 230, 232, 234, 236, 239, 241, 243, 245, 248, 250, 252, 255,
|
||||
};
|
||||
|
||||
BuiltInLED::BuiltInLED() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
dependencies:
|
||||
espressif/esp_matter:
|
||||
version: "^1.3.0"
|
||||
version: ">=1.4.0"
|
||||
espressif/cmake_utilities:
|
||||
version: "0.*"
|
||||
rules:
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
#include "matter_accessory_driver.h"
|
||||
|
||||
/* Do any conversions/remapping for the actual value here */
|
||||
esp_err_t light_accessory_set_power(void *led, uint8_t val)
|
||||
{
|
||||
esp_err_t light_accessory_set_power(void *led, uint8_t val) {
|
||||
BuiltInLED *builtinLED = (BuiltInLED *)led;
|
||||
esp_err_t err = ESP_OK;
|
||||
if (val) {
|
||||
@@ -27,8 +26,7 @@ esp_err_t light_accessory_set_power(void *led, uint8_t val)
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t light_accessory_set_brightness(void *led, uint8_t val)
|
||||
{
|
||||
esp_err_t light_accessory_set_brightness(void *led, uint8_t val) {
|
||||
esp_err_t err = ESP_OK;
|
||||
BuiltInLED *builtinLED = (BuiltInLED *)led;
|
||||
int value = REMAP_TO_RANGE(val, MATTER_BRIGHTNESS, STANDARD_BRIGHTNESS);
|
||||
@@ -41,8 +39,7 @@ esp_err_t light_accessory_set_brightness(void *led, uint8_t val)
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t light_accessory_set_hue(void *led, uint8_t val)
|
||||
{
|
||||
esp_err_t light_accessory_set_hue(void *led, uint8_t val) {
|
||||
esp_err_t err = ESP_OK;
|
||||
BuiltInLED *builtinLED = (BuiltInLED *)led;
|
||||
int value = REMAP_TO_RANGE(val, MATTER_HUE, STANDARD_HUE);
|
||||
@@ -56,8 +53,7 @@ esp_err_t light_accessory_set_hue(void *led, uint8_t val)
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t light_accessory_set_saturation(void *led, uint8_t val)
|
||||
{
|
||||
esp_err_t light_accessory_set_saturation(void *led, uint8_t val) {
|
||||
esp_err_t err = ESP_OK;
|
||||
BuiltInLED *builtinLED = (BuiltInLED *)led;
|
||||
int value = REMAP_TO_RANGE(val, MATTER_SATURATION, STANDARD_SATURATION);
|
||||
@@ -71,8 +67,7 @@ esp_err_t light_accessory_set_saturation(void *led, uint8_t val)
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t light_accessory_set_temperature(void *led, uint16_t val)
|
||||
{
|
||||
esp_err_t light_accessory_set_temperature(void *led, uint16_t val) {
|
||||
esp_err_t err = ESP_OK;
|
||||
BuiltInLED *builtinLED = (BuiltInLED *)led;
|
||||
uint32_t value = REMAP_TO_RANGE_INVERSE(val, STANDARD_TEMPERATURE_FACTOR);
|
||||
@@ -84,8 +79,7 @@ esp_err_t light_accessory_set_temperature(void *led, uint16_t val)
|
||||
return err;
|
||||
}
|
||||
|
||||
app_driver_handle_t light_accessory_init()
|
||||
{
|
||||
app_driver_handle_t light_accessory_init() {
|
||||
/* Initialize led */
|
||||
static BuiltInLED builtinLED;
|
||||
|
||||
|
||||
@@ -21,19 +21,13 @@
|
||||
#include "esp_openthread_types.h"
|
||||
|
||||
#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \
|
||||
{ \
|
||||
.radio_mode = RADIO_MODE_NATIVE, \
|
||||
}
|
||||
{ .radio_mode = RADIO_MODE_NATIVE, }
|
||||
|
||||
#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \
|
||||
{ \
|
||||
.host_connection_mode = HOST_CONNECTION_MODE_NONE, \
|
||||
}
|
||||
{ .host_connection_mode = HOST_CONNECTION_MODE_NONE, }
|
||||
|
||||
#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \
|
||||
{ \
|
||||
.storage_partition_name = "nvs", .netif_queue_size = 10, .task_queue_size = 10, \
|
||||
}
|
||||
{ .storage_partition_name = "nvs", .netif_queue_size = 10, .task_queue_size = 10, }
|
||||
#endif
|
||||
|
||||
// set your board button pin here
|
||||
@@ -72,55 +66,38 @@ bool isThreadConnected() {
|
||||
}
|
||||
#endif
|
||||
|
||||
static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg)
|
||||
{
|
||||
static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) {
|
||||
switch (event->Type) {
|
||||
case chip::DeviceLayer::DeviceEventType::kInterfaceIpAddressChanged:
|
||||
log_i("Interface %s Address changed",
|
||||
event->InterfaceIpAddressChanged.Type == chip::DeviceLayer::InterfaceIpChangeType::kIpV4_Assigned ?
|
||||
"IPv4" : "IPV6" );
|
||||
log_i(
|
||||
"Interface %s Address changed", event->InterfaceIpAddressChanged.Type == chip::DeviceLayer::InterfaceIpChangeType::kIpV4_Assigned ? "IPv4" : "IPV6"
|
||||
);
|
||||
break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningComplete:
|
||||
log_i("Commissioning complete");
|
||||
break;
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningComplete: log_i("Commissioning complete"); break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kFailSafeTimerExpired:
|
||||
log_i("Commissioning failed, fail safe timer expired");
|
||||
break;
|
||||
case chip::DeviceLayer::DeviceEventType::kFailSafeTimerExpired: log_i("Commissioning failed, fail safe timer expired"); break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStarted:
|
||||
log_i("Commissioning session started");
|
||||
break;
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStarted: log_i("Commissioning session started"); break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStopped:
|
||||
log_i("Commissioning session stopped");
|
||||
break;
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStopped: log_i("Commissioning session stopped"); break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningWindowOpened:
|
||||
log_i("Commissioning window opened");
|
||||
break;
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningWindowOpened: log_i("Commissioning window opened"); break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningWindowClosed:
|
||||
log_i("Commissioning window closed");
|
||||
break;
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningWindowClosed: log_i("Commissioning window closed"); break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kFabricRemoved:
|
||||
{
|
||||
log_i("Fabric removed successfully");
|
||||
if (chip::Server::GetInstance().GetFabricTable().FabricCount() == 0)
|
||||
{
|
||||
if (chip::Server::GetInstance().GetFabricTable().FabricCount() == 0) {
|
||||
chip::CommissioningWindowManager &commissionMgr = chip::Server::GetInstance().GetCommissioningWindowManager();
|
||||
constexpr auto kTimeoutSeconds = chip::System::Clock::Seconds16(k_timeout_seconds);
|
||||
if (!commissionMgr.IsCommissioningWindowOpen())
|
||||
{
|
||||
if (!commissionMgr.IsCommissioningWindowOpen()) {
|
||||
/* After removing last fabric, this example does not remove the Wi-Fi credentials
|
||||
* and still has IP connectivity so, only advertising on DNS-SD.
|
||||
*/
|
||||
CHIP_ERROR err = commissionMgr.OpenBasicCommissioningWindow(kTimeoutSeconds,
|
||||
chip::CommissioningWindowAdvertisement::kDnssdOnly);
|
||||
if (err != CHIP_NO_ERROR)
|
||||
{
|
||||
CHIP_ERROR err = commissionMgr.OpenBasicCommissioningWindow(kTimeoutSeconds, chip::CommissioningWindowAdvertisement::kDnssdOnly);
|
||||
if (err != CHIP_NO_ERROR) {
|
||||
log_e("Failed to open commissioning window, err:%" CHIP_ERROR_FORMAT, err.Format());
|
||||
}
|
||||
}
|
||||
@@ -128,30 +105,21 @@ static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg)
|
||||
break;
|
||||
}
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kFabricWillBeRemoved:
|
||||
log_i("Fabric will be removed");
|
||||
break;
|
||||
case chip::DeviceLayer::DeviceEventType::kFabricWillBeRemoved: log_i("Fabric will be removed"); break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kFabricUpdated:
|
||||
log_i("Fabric is updated");
|
||||
break;
|
||||
case chip::DeviceLayer::DeviceEventType::kFabricUpdated: log_i("Fabric is updated"); break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kFabricCommitted:
|
||||
log_i("Fabric is committed");
|
||||
break;
|
||||
case chip::DeviceLayer::DeviceEventType::kFabricCommitted: log_i("Fabric is committed"); break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kBLEDeinitialized:
|
||||
log_i("BLE deinitialized and memory reclaimed");
|
||||
break;
|
||||
case chip::DeviceLayer::DeviceEventType::kBLEDeinitialized: log_i("BLE deinitialized and memory reclaimed"); break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t matter_light_attribute_update(app_driver_handle_t driver_handle, uint16_t endpoint_id, uint32_t cluster_id,
|
||||
uint32_t attribute_id, esp_matter_attr_val_t *val)
|
||||
{
|
||||
esp_err_t matter_light_attribute_update(
|
||||
app_driver_handle_t driver_handle, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val
|
||||
) {
|
||||
esp_err_t err = ESP_OK;
|
||||
if (endpoint_id == light_endpoint_id) {
|
||||
void *led = (void *)driver_handle;
|
||||
@@ -176,8 +144,7 @@ esp_err_t matter_light_attribute_update(app_driver_handle_t driver_handle, uint1
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t matter_light_set_defaults(uint16_t endpoint_id)
|
||||
{
|
||||
esp_err_t matter_light_set_defaults(uint16_t endpoint_id) {
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
void *led = endpoint::get_priv_data(endpoint_id);
|
||||
@@ -224,8 +191,7 @@ esp_err_t matter_light_set_defaults(uint16_t endpoint_id)
|
||||
return err;
|
||||
}
|
||||
|
||||
void button_driver_init()
|
||||
{
|
||||
void button_driver_init() {
|
||||
/* Initialize button */
|
||||
pinMode(button_gpio, INPUT_PULLUP);
|
||||
}
|
||||
@@ -233,9 +199,9 @@ void button_driver_init()
|
||||
// This callback is called for every attribute update. The callback implementation shall
|
||||
// handle the desired attributes and return an appropriate error code. If the attribute
|
||||
// is not of your interest, please do not return an error code and strictly return ESP_OK.
|
||||
static esp_err_t app_attribute_update_cb(attribute::callback_type_t type, uint16_t endpoint_id, uint32_t cluster_id,
|
||||
uint32_t attribute_id, esp_matter_attr_val_t *val, void *priv_data)
|
||||
{
|
||||
static esp_err_t app_attribute_update_cb(
|
||||
attribute::callback_type_t type, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val, void *priv_data
|
||||
) {
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
if (type == PRE_UPDATE) {
|
||||
@@ -249,15 +215,12 @@ static esp_err_t app_attribute_update_cb(attribute::callback_type_t type, uint16
|
||||
|
||||
// This callback is invoked when clients interact with the Identify Cluster.
|
||||
// In the callback implementation, an endpoint can identify itself. (e.g., by flashing an LED or light).
|
||||
static esp_err_t app_identification_cb(identification::callback_type_t type, uint16_t endpoint_id, uint8_t effect_id,
|
||||
uint8_t effect_variant, void *priv_data)
|
||||
{
|
||||
static esp_err_t app_identification_cb(identification::callback_type_t type, uint16_t endpoint_id, uint8_t effect_id, uint8_t effect_variant, void *priv_data) {
|
||||
log_i("Identification callback: type: %u, effect: %u, variant: %u", type, effect_id, effect_variant);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
void setup() {
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
/* Initialize driver */
|
||||
@@ -301,7 +264,7 @@ void setup()
|
||||
cluster_t *color_control_cluster = cluster::get(endpoint, ColorControl::Id);
|
||||
attribute_t *current_x_attribute = attribute::get(color_control_cluster, ColorControl::Attributes::CurrentX::Id);
|
||||
attribute::set_deferred_persistence(current_x_attribute);
|
||||
attribute_t *current_y_attribute = attribute::get(color_control_cluster, ColorControl::Attributes::CurrentY::Id);
|
||||
attribute_t *current_y_attribute = attribute::get(color_control_cluster, ColorControl::Attributes::CurrentY::Id); // codespell:ignore
|
||||
attribute::set_deferred_persistence(current_y_attribute);
|
||||
attribute_t *color_temp_attribute = attribute::get(color_control_cluster, ColorControl::Attributes::ColorTemperatureMireds::Id);
|
||||
attribute::set_deferred_persistence(color_temp_attribute);
|
||||
@@ -412,7 +375,7 @@ void loop() {
|
||||
|
||||
// Factory reset is triggered if the button is pressed for more than 10 seconds
|
||||
if (time_diff > 10000) {
|
||||
log_i("Factory reset triggered. Light will retored to factory settings.");
|
||||
log_i("Factory reset triggered. Light will restored to factory settings.");
|
||||
esp_matter::factory_reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,16 @@ platform = espressif32
|
||||
framework = arduino, espidf
|
||||
board_build.partitions = partitions.csv
|
||||
monitor_speed = 115200
|
||||
build_unflags =
|
||||
-std=c++17
|
||||
-std=gnu++2b
|
||||
build_flags =
|
||||
-std=gnu++2a
|
||||
-Wno-missing-field-initializers
|
||||
|
||||
|
||||
[env:esp32s3]
|
||||
board = esp32-s3-devkitc-1
|
||||
[env:esp32c6]
|
||||
board = esp32-c6-devkitc-1
|
||||
board_build.embed_txtfiles =
|
||||
managed_components/espressif__esp_insights/server_certs/https_server.crt
|
||||
managed_components/espressif__esp_rainmaker/server_certs/rmaker_mqtt_server.crt
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
CONFIG_IDF_TARGET="esp32c6"
|
||||
|
||||
# Arduino Settings
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_AUTOSTART_ARDUINO=y
|
||||
@@ -6,9 +8,17 @@ CONFIG_AUTOSTART_ARDUINO=y
|
||||
# Boot Messages - Log level
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y
|
||||
# Arduino Log Level
|
||||
CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_VERBOSE=y
|
||||
CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_INFO=y
|
||||
# IDF Log Level
|
||||
CONFIG_LOG_DEFAULT_LEVEL_WARN=y
|
||||
CONFIG_LOG_DEFAULT_LEVEL_ERROR=y
|
||||
|
||||
# Default to 921600 baud when flashing and monitoring device
|
||||
CONFIG_ESPTOOLPY_BAUD_921600B=y
|
||||
CONFIG_ESPTOOLPY_BAUD=921600
|
||||
CONFIG_ESPTOOLPY_COMPRESSED=y
|
||||
CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y
|
||||
CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
|
||||
#enable BT
|
||||
CONFIG_BT_ENABLED=y
|
||||
@@ -17,6 +27,11 @@ CONFIG_BT_NIMBLE_ENABLED=y
|
||||
#disable BT connection reattempt
|
||||
CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
|
||||
|
||||
# NIMBLE
|
||||
CONFIG_BT_NIMBLE_EXT_ADV=n
|
||||
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
|
||||
CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING=y
|
||||
|
||||
#enable lwip ipv6 autoconfig
|
||||
CONFIG_LWIP_IPV6_AUTOCONFIG=y
|
||||
|
||||
@@ -28,16 +43,17 @@ CONFIG_PARTITION_TABLE_OFFSET=0xC000
|
||||
# Disable chip shell
|
||||
CONFIG_ENABLE_CHIP_SHELL=n
|
||||
|
||||
# Enable OTA Requester
|
||||
CONFIG_ENABLE_OTA_REQUESTOR=n
|
||||
|
||||
#enable lwIP route hooks
|
||||
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
|
||||
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
|
||||
|
||||
# Button
|
||||
CONFIG_BUTTON_PERIOD_TIME_MS=20
|
||||
CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000
|
||||
|
||||
# disable softap by default
|
||||
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
|
||||
CONFIG_ENABLE_WIFI_STATION=y
|
||||
CONFIG_ENABLE_WIFI_AP=n
|
||||
|
||||
# Disable DS Peripheral
|
||||
CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n
|
||||
@@ -52,15 +68,23 @@ CONFIG_MBEDTLS_HKDF_C=y
|
||||
# unique local addresses for fabrics(MAX_FABRIC), a link local address(1)
|
||||
CONFIG_LWIP_IPV6_NUM_ADDRESSES=6
|
||||
|
||||
# libsodium
|
||||
CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
|
||||
|
||||
# ESP32-S3-DevKitC-1 Settings
|
||||
# FreeRTOS should use legacy API
|
||||
CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY=y
|
||||
|
||||
# Use minimal mDNS
|
||||
CONFIG_USE_MINIMAL_MDNS=y
|
||||
CONFIG_ENABLE_EXTENDED_DISCOVERY=y
|
||||
|
||||
# ESP32-C6-DevKit Settings
|
||||
# Buttons
|
||||
CONFIG_BSP_BUTTONS_NUM=1
|
||||
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
|
||||
CONFIG_BSP_BUTTON_1_GPIO=0
|
||||
CONFIG_BSP_BUTTON_1_LEVEL=0
|
||||
CONFIG_BUTTON_PIN=9
|
||||
# LEDs
|
||||
CONFIG_BSP_LEDS_NUM=1
|
||||
CONFIG_BSP_LED_TYPE_RGB=y
|
||||
CONFIG_BSP_LED_RGB_GPIO=48
|
||||
CONFIG_BSP_LED_RGB_BACKEND_RMT=y
|
||||
CONFIG_WS2812_PIN=8
|
||||
# max GPIO
|
||||
CONFIG_ENV_GPIO_RANGE_MIN=0
|
||||
CONFIG_ENV_GPIO_RANGE_MAX=30
|
||||
CONFIG_ENV_GPIO_IN_RANGE_MAX=30
|
||||
CONFIG_ENV_GPIO_OUT_RANGE_MAX=30
|
||||
|
||||
@@ -56,7 +56,7 @@ CONFIG_LWIP_MULTICAST_PING=y
|
||||
CONFIG_USE_MINIMAL_MDNS=n
|
||||
CONFIG_ENABLE_EXTENDED_DISCOVERY=y
|
||||
|
||||
# Enable OTA Requestor
|
||||
# Enable OTA Requester
|
||||
CONFIG_ENABLE_OTA_REQUESTOR=n
|
||||
|
||||
# Disable STA and AP for ESP32C6
|
||||
@@ -77,4 +77,3 @@ CONFIG_MRP_MAX_RETRANS=3
|
||||
|
||||
# Enable HKDF in mbedtls
|
||||
CONFIG_MBEDTLS_HKDF_C=y
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
CONFIG_IDF_TARGET="esp32c3"
|
||||
|
||||
# Arduino Settings
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_AUTOSTART_ARDUINO=y
|
||||
|
||||
# Log Levels
|
||||
# Boot Messages - Log level
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y
|
||||
# Arduino Log Level
|
||||
CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_INFO=y
|
||||
# IDF Log Level
|
||||
CONFIG_LOG_DEFAULT_LEVEL_ERROR=y
|
||||
|
||||
# Default to 921600 baud when flashing and monitoring device
|
||||
CONFIG_ESPTOOLPY_BAUD_921600B=y
|
||||
CONFIG_ESPTOOLPY_BAUD=921600
|
||||
CONFIG_ESPTOOLPY_COMPRESSED=y
|
||||
CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y
|
||||
CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
|
||||
#enable BT
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BT_NIMBLE_ENABLED=y
|
||||
|
||||
#disable BT connection reattempt
|
||||
CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
|
||||
|
||||
#enable lwip ipv6 autoconfig
|
||||
CONFIG_LWIP_IPV6_AUTOCONFIG=y
|
||||
|
||||
# Use a custom partition table
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0xC000
|
||||
|
||||
# Disable chip shell
|
||||
CONFIG_ENABLE_CHIP_SHELL=n
|
||||
|
||||
# Enable OTA Requestor
|
||||
CONFIG_ENABLE_OTA_REQUESTOR=n
|
||||
|
||||
#enable lwIP route hooks
|
||||
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
|
||||
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
|
||||
|
||||
# disable softap by default
|
||||
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
|
||||
CONFIG_ENABLE_WIFI_STATION=y
|
||||
CONFIG_ENABLE_WIFI_AP=n
|
||||
|
||||
# Disable DS Peripheral
|
||||
CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n
|
||||
|
||||
# Use compact attribute storage mode
|
||||
CONFIG_ESP_MATTER_NVS_USE_COMPACT_ATTR_STORAGE=y
|
||||
|
||||
# Enable HKDF in mbedtls
|
||||
CONFIG_MBEDTLS_HKDF_C=y
|
||||
|
||||
# Increase LwIP IPv6 address number to 6 (MAX_FABRIC + 1)
|
||||
# unique local addresses for fabrics(MAX_FABRIC), a link local address(1)
|
||||
CONFIG_LWIP_IPV6_NUM_ADDRESSES=6
|
||||
@@ -1,68 +1,5 @@
|
||||
CONFIG_IDF_TARGET="esp32c6"
|
||||
|
||||
# Arduino Settings
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_AUTOSTART_ARDUINO=y
|
||||
|
||||
# Log Levels
|
||||
# Boot Messages - Log level
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y
|
||||
# Arduino Log Level
|
||||
CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_INFO=y
|
||||
# IDF Log Level
|
||||
CONFIG_LOG_DEFAULT_LEVEL_ERROR=y
|
||||
|
||||
# Default to 921600 baud when flashing and monitoring device
|
||||
CONFIG_ESPTOOLPY_BAUD_921600B=y
|
||||
CONFIG_ESPTOOLPY_BAUD=921600
|
||||
CONFIG_ESPTOOLPY_COMPRESSED=y
|
||||
CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y
|
||||
CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
|
||||
#enable BT
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BT_NIMBLE_ENABLED=y
|
||||
|
||||
#disable BT connection reattempt
|
||||
CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
|
||||
|
||||
#enable lwip ipv6 autoconfig
|
||||
CONFIG_LWIP_IPV6_AUTOCONFIG=y
|
||||
|
||||
# Use a custom partition table
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0xC000
|
||||
|
||||
# Disable chip shell
|
||||
CONFIG_ENABLE_CHIP_SHELL=n
|
||||
|
||||
# Enable OTA Requestor
|
||||
CONFIG_ENABLE_OTA_REQUESTOR=n
|
||||
|
||||
#enable lwIP route hooks
|
||||
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
|
||||
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
|
||||
|
||||
# disable softap by default
|
||||
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
|
||||
CONFIG_ENABLE_WIFI_STATION=y
|
||||
CONFIG_ENABLE_WIFI_AP=n
|
||||
|
||||
# Disable DS Peripheral
|
||||
CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n
|
||||
|
||||
# Use compact attribute storage mode
|
||||
CONFIG_ESP_MATTER_NVS_USE_COMPACT_ATTR_STORAGE=y
|
||||
|
||||
# Enable HKDF in mbedtls
|
||||
CONFIG_MBEDTLS_HKDF_C=y
|
||||
|
||||
# Increase LwIP IPv6 address number to 6 (MAX_FABRIC + 1)
|
||||
# unique local addresses for fabrics(MAX_FABRIC), a link local address(1)
|
||||
CONFIG_LWIP_IPV6_NUM_ADDRESSES=6
|
||||
|
||||
# libsodium
|
||||
CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
CONFIG_IDF_TARGET="esp32s3"
|
||||
|
||||
# Arduino Settings
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_AUTOSTART_ARDUINO=y
|
||||
|
||||
# Log Levels
|
||||
# Boot Messages - Log level
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y
|
||||
# Arduino Log Level
|
||||
CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_INFO=y
|
||||
# IDF Log Level
|
||||
CONFIG_LOG_DEFAULT_LEVEL_ERROR=y
|
||||
|
||||
# Default to 921600 baud when flashing and monitoring device
|
||||
CONFIG_ESPTOOLPY_BAUD_921600B=y
|
||||
CONFIG_ESPTOOLPY_BAUD=921600
|
||||
CONFIG_ESPTOOLPY_COMPRESSED=y
|
||||
CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y
|
||||
CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
|
||||
#enable BT
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BT_NIMBLE_ENABLED=y
|
||||
|
||||
#disable BT connection reattempt
|
||||
CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
|
||||
|
||||
#enable lwip ipv6 autoconfig
|
||||
CONFIG_LWIP_IPV6_AUTOCONFIG=y
|
||||
|
||||
# Use a custom partition table
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0xC000
|
||||
|
||||
# Disable chip shell
|
||||
CONFIG_ENABLE_CHIP_SHELL=n
|
||||
|
||||
# Enable OTA Requestor
|
||||
CONFIG_ENABLE_OTA_REQUESTOR=n
|
||||
|
||||
#enable lwIP route hooks
|
||||
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
|
||||
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
|
||||
|
||||
# disable softap by default
|
||||
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
|
||||
CONFIG_ENABLE_WIFI_STATION=y
|
||||
CONFIG_ENABLE_WIFI_AP=n
|
||||
|
||||
# Disable DS Peripheral
|
||||
CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n
|
||||
|
||||
# Use compact attribute storage mode
|
||||
CONFIG_ESP_MATTER_NVS_USE_COMPACT_ATTR_STORAGE=y
|
||||
|
||||
# Enable HKDF in mbedtls
|
||||
CONFIG_MBEDTLS_HKDF_C=y
|
||||
|
||||
# Increase LwIP IPv6 address number to 6 (MAX_FABRIC + 1)
|
||||
# unique local addresses for fabrics(MAX_FABRIC), a link local address(1)
|
||||
CONFIG_LWIP_IPV6_NUM_ADDRESSES=6
|
||||
@@ -13,7 +13,6 @@ framework = espidf
|
||||
board = esp32dev
|
||||
monitor_speed = 115200
|
||||
build_flags =
|
||||
; https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-wrover-kit.html#rgb-led
|
||||
-D CONFIG_BLINK_GPIO=2
|
||||
-D CONFIG_BLINK_LED_GPIO=2
|
||||
-D CONFIG_BLINK_PERIOD=1000
|
||||
@@ -37,3 +36,13 @@ build_flags =
|
||||
-D CONFIG_BLINK_GPIO=2
|
||||
-D CONFIG_BLINK_LED_GPIO=2
|
||||
-D CONFIG_BLINK_PERIOD=1000
|
||||
|
||||
[env:esp32-p4]
|
||||
platform = espressif32
|
||||
framework = espidf
|
||||
board = esp32-p4
|
||||
monitor_speed = 115200
|
||||
build_flags =
|
||||
-D CONFIG_BLINK_GPIO=2
|
||||
-D CONFIG_BLINK_LED_GPIO=2
|
||||
-D CONFIG_BLINK_PERIOD=1000
|
||||
|
||||
@@ -18,3 +18,6 @@ board_build.embed_txtfiles =
|
||||
|
||||
[env:esp-wrover-kit]
|
||||
board = esp-wrover-kit
|
||||
build_flags =
|
||||
-D SHOW_METRICS
|
||||
|
||||
|
||||
@@ -29,13 +29,15 @@ lib_ignore = ${env:tasmota32_base.lib_ignore}
|
||||
NetworkClientSecure
|
||||
Zigbee
|
||||
custom_sdkconfig = https://raw.githubusercontent.com/pioarduino/sdkconfig/refs/heads/main/sdkconfig_tasmota_esp32
|
||||
'# CONFIG_BT_ENABLED is not set'
|
||||
'# CONFIG_BT_NIMBLE_ENABLED is not set'
|
||||
'# CONFIG_BT_CONTROLLER_ENABLED is not set'
|
||||
CONFIG_BT_CONTROLLER_DISABLED=y
|
||||
'# CONFIG_ETH_USE_ESP32_EMAC is not set'
|
||||
'# CONFIG_ETH_PHY_INTERFACE_RMII is not set'
|
||||
'# CONFIG_ETH_RMII_CLK_INPUT is not set'
|
||||
'# CONFIG_ETH_RMII_CLK_IN_GPIO is not set'
|
||||
custom_component_remove = espressif/esp_hosted
|
||||
espressif/esp_wifi_remote
|
||||
espressif/esp-dsp
|
||||
custom_component_remove =
|
||||
espressif/network_provisioning
|
||||
espressif/esp-zboss-lib
|
||||
espressif/esp-zigbee-lib
|
||||
|
||||
+45572
File diff suppressed because it is too large
Load Diff
+21108
File diff suppressed because it is too large
Load Diff
+34807
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+70756
File diff suppressed because it is too large
Load Diff
+53987
File diff suppressed because it is too large
Load Diff
+133701
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+46655
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+69011
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,7 @@ IS_WINDOWS = sys.platform.startswith("win")
|
||||
class Esp32ExceptionDecoder(DeviceMonitorFilterBase):
|
||||
NAME = "esp32_exception_decoder"
|
||||
|
||||
ADDR_PATTERN = re.compile(r"((?:0x[0-9a-fA-F]{8}[: ]?)+)\s?$")
|
||||
ADDR_PATTERN = re.compile(r"((?:0x[0-9a-fA-F]{8}[: ]?)+)")
|
||||
ADDR_SPLIT = re.compile(r"[ :]")
|
||||
PREFIX_RE = re.compile(r"^ *")
|
||||
|
||||
|
||||
+88
-39
@@ -6,19 +6,19 @@
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [
|
||||
"dev-platform",
|
||||
"Wi-Fi",
|
||||
"WiFi",
|
||||
"Bluetooth",
|
||||
"Xtensa",
|
||||
"RISC-V"
|
||||
],
|
||||
"engines": {
|
||||
"platformio": ">=6.1.16"
|
||||
"platformio": ">=6.1.18"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pioarduino/platform-espressif32.git"
|
||||
},
|
||||
"version": "54.03.20",
|
||||
"version": "54.03.21",
|
||||
"frameworks": {
|
||||
"arduino": {
|
||||
"script": "builder/frameworks/arduino.py"
|
||||
@@ -33,114 +33,163 @@
|
||||
"type": "framework",
|
||||
"optional": true,
|
||||
"owner": "espressif",
|
||||
"version": "https://github.com/espressif/arduino-esp32/releases/download/3.2.0/esp32-3.2.0.zip"
|
||||
"version": "https://github.com/espressif/arduino-esp32/releases/download/3.2.1/esp32-3.2.1.zip"
|
||||
},
|
||||
"framework-arduinoespressif32-libs": {
|
||||
"type": "framework",
|
||||
"optional": true,
|
||||
"owner": "espressif",
|
||||
"version": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.4/esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip"
|
||||
"version": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.4/esp32-arduino-libs-idf-release_v5.4-858a988d-v1.zip"
|
||||
},
|
||||
"framework-arduino-c2-skeleton-lib": {
|
||||
"type": "framework",
|
||||
"optional": true,
|
||||
"owner": "espressif",
|
||||
"version": "https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/c2_arduino_compile_skeleton.zip"
|
||||
"version": "https://github.com/pioarduino/platform-espressif32/releases/download/54.03.20/c2_arduino_compile_skeleton.zip"
|
||||
},
|
||||
"framework-espidf": {
|
||||
"type": "framework",
|
||||
"optional": true,
|
||||
"owner": "pioarduino",
|
||||
"version": "https://github.com/pioarduino/esp-idf/releases/download/v5.4.1/esp-idf-v5.4.1.zip"
|
||||
"version": "https://github.com/pioarduino/esp-idf/releases/download/v5.4.2/esp-idf-v5.4.2.zip"
|
||||
},
|
||||
"toolchain-xtensa-esp-elf": {
|
||||
"type": "toolchain",
|
||||
"optional": true,
|
||||
"owner": "platformio",
|
||||
"version": "14.2.0+20241119"
|
||||
"owner": "pioarduino",
|
||||
"package-version": "14.2.0+20241119",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/xtensa-esp-elf-14.2.0_20241119.zip"
|
||||
},
|
||||
"toolchain-riscv32-esp": {
|
||||
"type": "toolchain",
|
||||
"optional": true,
|
||||
"owner": "platformio",
|
||||
"version": "14.2.0+20241119"
|
||||
"owner": "pioarduino",
|
||||
"package-version": "14.2.0+20241119",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/riscv32-esp-elf-14.2.0_20241119.zip"
|
||||
},
|
||||
"toolchain-esp32ulp": {
|
||||
"type": "toolchain",
|
||||
"optional": true,
|
||||
"owner": "platformio",
|
||||
"version": "~1.23800.0"
|
||||
"owner": "pioarduino",
|
||||
"package-version": "2.38.0+20240113",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/esp32ulp-elf-2.38_20240113.zip"
|
||||
},
|
||||
"tool-xtensa-esp-elf-gdb": {
|
||||
"type": "debugger",
|
||||
"optional": true,
|
||||
"owner": "platformio",
|
||||
"version": "14.2.0+20240403"
|
||||
"owner": "pioarduino",
|
||||
"package-version": "16.2.0+20250324",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/xtensa-esp-gdb-v16.2_20250324.zip"
|
||||
},
|
||||
"tool-riscv32-esp-elf-gdb": {
|
||||
"type": "debugger",
|
||||
"optional": true,
|
||||
"owner": "platformio",
|
||||
"version": "14.2.0+20240403"
|
||||
"owner": "pioarduino",
|
||||
"package-version": "16.2.0+20250324",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/riscv32-esp-gdb-v16.2_20250324.zip"
|
||||
},
|
||||
"tool-esptoolpy": {
|
||||
"type": "uploader",
|
||||
"optional": false,
|
||||
"owner": "pioarduino",
|
||||
"version": "https://github.com/pioarduino/esptool/releases/download/v4.8.9/esptool.zip"
|
||||
"version": "https://github.com/pioarduino/esptool/releases/download/v5.0.0-dev1/esptool.zip"
|
||||
},
|
||||
"tl-install": {
|
||||
"type": "tool",
|
||||
"optional": false,
|
||||
"owner": "pioarduino",
|
||||
"version": "https://github.com/pioarduino/esp_install/releases/download/v5.0.0/esp_install-v5.0.0.zip"
|
||||
},
|
||||
"tool-dfuutil-arduino": {
|
||||
"type": "uploader",
|
||||
"optional": true,
|
||||
"owner": "platformio",
|
||||
"version": "~1.11.0"
|
||||
"owner": "pioarduino",
|
||||
"package-version": "1.11.0",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/dfuutil-arduino-v1.11.0.zip"
|
||||
},
|
||||
"tool-openocd-esp32": {
|
||||
"type": "debugger",
|
||||
"optional": true,
|
||||
"owner": "platformio",
|
||||
"version": "~2.1100.0"
|
||||
"owner": "pioarduino",
|
||||
"package-version": "2.1200.20250422",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/openocd-v0.12.0-esp32-20250422.zip"
|
||||
},
|
||||
"tool-mklittlefs": {
|
||||
"type": "uploader",
|
||||
"owner": "tasmota",
|
||||
"version": "^3.2.0"
|
||||
"optional": true,
|
||||
"owner": "pioarduino",
|
||||
"package-version": "3.2.0",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/mklittlefs-3.2.0.zip"
|
||||
},
|
||||
"tool-mkfatfs": {
|
||||
"tool-mklittlefs-4.0.0": {
|
||||
"type": "uploader",
|
||||
"optional": true,
|
||||
"owner": "platformio",
|
||||
"version": "~2.0.0"
|
||||
"owner": "pioarduino",
|
||||
"package-version": "4.0.0",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/mklittlefs-4.0.0.zip"
|
||||
},
|
||||
"tool-mkspiffs": {
|
||||
"type": "uploader",
|
||||
"optional": true,
|
||||
"owner": "platformio",
|
||||
"version": "~2.230.0"
|
||||
"owner": "pioarduino",
|
||||
"package-version": "2.230.0",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/mkspiffs-v2.230.0.zip"
|
||||
},
|
||||
"tool-mkfatfs": {
|
||||
"type": "uploader",
|
||||
"optional": true,
|
||||
"owner": "pioarduino",
|
||||
"package-version": "2.0.1",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/mkfatfs-v2.0.1.zip"
|
||||
},
|
||||
"tool-cppcheck": {
|
||||
"type": "tool",
|
||||
"optional": true,
|
||||
"owner": "platformio",
|
||||
"version": "~1.21100"
|
||||
"owner": "pioarduino",
|
||||
"package-version": "2.11.0+230717",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/cppcheck-v2.11.0-230717.zip"
|
||||
},
|
||||
"tool-clangtidy": {
|
||||
"type": "tool",
|
||||
"optional": true,
|
||||
"owner": "platformio",
|
||||
"version": "^1.190100.0"
|
||||
"owner": "pioarduino",
|
||||
"package-version": "18.1.1",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/clangtidy-v18.1.1.zip"
|
||||
},
|
||||
"tool-pvs-studio": {
|
||||
"type": "tool",
|
||||
"optional": true,
|
||||
"owner": "platformio",
|
||||
"version": "^7.18.0"
|
||||
"owner": "pioarduino",
|
||||
"package-version": "7.36.91321",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/pvs-studio-v7.36.91321.zip"
|
||||
},
|
||||
"tool-cmake": {
|
||||
"type": "tool",
|
||||
"optional": true,
|
||||
"owner": "platformio",
|
||||
"version": "~3.30.2"
|
||||
"owner": "pioarduino",
|
||||
"package-version": "3.30.2",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/cmake-3.30.2.zip"
|
||||
},
|
||||
"tool-esp-rom-elfs": {
|
||||
"type": "tool",
|
||||
"optional": true,
|
||||
"owner": "pioarduino",
|
||||
"package-version": "2024.10.11",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/esp-rom-elfs-20241011.zip"
|
||||
},
|
||||
"tool-ninja": {
|
||||
"type": "tool",
|
||||
"optional": true,
|
||||
"owner": "platformio",
|
||||
"version": "^1.7.0"
|
||||
"owner": "pioarduino",
|
||||
"package-version": "1.10.2",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/ninja-1.10.2.zip"
|
||||
},
|
||||
"tool-scons": {
|
||||
"type": "tool",
|
||||
"optional": true,
|
||||
"owner": "pioarduino",
|
||||
"package-version": "4.40801.0",
|
||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/scons-4.8.1.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+495
-107
@@ -13,109 +13,490 @@
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import urllib
|
||||
import sys
|
||||
import contextlib
|
||||
import json
|
||||
import re
|
||||
import requests
|
||||
import subprocess
|
||||
import sys
|
||||
import shutil
|
||||
import logging
|
||||
from typing import Optional, Dict, List, Any
|
||||
|
||||
from platformio.public import PlatformBase, to_unix_path
|
||||
from platformio.proc import get_pythonexe_path
|
||||
from platformio.project.config import ProjectConfig
|
||||
from platformio.package.manager.tool import ToolPackageManager
|
||||
|
||||
# Constants
|
||||
RETRY_LIMIT = 3
|
||||
SUBPROCESS_TIMEOUT = 300
|
||||
MKLITTLEFS_VERSION_320 = "3.2.0"
|
||||
MKLITTLEFS_VERSION_400 = "4.0.0"
|
||||
DEFAULT_DEBUG_SPEED = "5000"
|
||||
DEFAULT_APP_OFFSET = "0x10000"
|
||||
|
||||
# MCUs that support ESP-builtin debug
|
||||
ESP_BUILTIN_DEBUG_MCUS = frozenset([
|
||||
"esp32c3", "esp32c5", "esp32c6", "esp32s3", "esp32h2", "esp32p4"
|
||||
])
|
||||
|
||||
# MCU configuration mapping
|
||||
MCU_TOOLCHAIN_CONFIG = {
|
||||
"xtensa": {
|
||||
"mcus": frozenset(["esp32", "esp32s2", "esp32s3"]),
|
||||
"toolchains": ["toolchain-xtensa-esp-elf"],
|
||||
"debug_tools": ["tool-xtensa-esp-elf-gdb"]
|
||||
},
|
||||
"riscv": {
|
||||
"mcus": frozenset([
|
||||
"esp32c2", "esp32c3", "esp32c5", "esp32c6", "esp32h2", "esp32p4"
|
||||
]),
|
||||
"toolchains": ["toolchain-riscv32-esp"],
|
||||
"debug_tools": ["tool-riscv32-esp-elf-gdb"]
|
||||
}
|
||||
}
|
||||
|
||||
COMMON_IDF_PACKAGES = [
|
||||
"tool-cmake",
|
||||
"tool-ninja",
|
||||
"tool-scons",
|
||||
"tool-esp-rom-elfs"
|
||||
]
|
||||
|
||||
CHECK_PACKAGES = [
|
||||
"tool-cppcheck",
|
||||
"tool-clangtidy",
|
||||
"tool-pvs-studio"
|
||||
]
|
||||
|
||||
# System-specific configuration
|
||||
IS_WINDOWS = sys.platform.startswith("win")
|
||||
# Set Platformio env var to use windows_amd64 for all windows architectures
|
||||
# only windows_amd64 native espressif toolchains are available
|
||||
# needs platformio core >= 6.1.16b2 or pioarduino core 6.1.16+test
|
||||
# needs platformio/pioarduino core >= 6.1.17
|
||||
if IS_WINDOWS:
|
||||
os.environ["PLATFORMIO_SYSTEM_TYPE"] = "windows_amd64"
|
||||
|
||||
# Global variables
|
||||
python_exe = get_pythonexe_path()
|
||||
pm = ToolPackageManager()
|
||||
|
||||
# Configure logger
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def safe_file_operation(operation_func):
|
||||
"""Decorator for safe filesystem operations with error handling."""
|
||||
def wrapper(*args, **kwargs):
|
||||
try:
|
||||
return operation_func(*args, **kwargs)
|
||||
except (OSError, IOError, FileNotFoundError) as e:
|
||||
logger.error(f"Filesystem error in {operation_func.__name__}: {e}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error in {operation_func.__name__}: {e}")
|
||||
raise # Re-raise unexpected exceptions
|
||||
return wrapper
|
||||
|
||||
|
||||
@safe_file_operation
|
||||
def safe_remove_directory(path: str) -> bool:
|
||||
"""Safely remove directories with error handling."""
|
||||
if os.path.exists(path) and os.path.isdir(path):
|
||||
shutil.rmtree(path)
|
||||
logger.debug(f"Directory removed: {path}")
|
||||
return True
|
||||
|
||||
|
||||
@safe_file_operation
|
||||
def safe_copy_file(src: str, dst: str) -> bool:
|
||||
"""Safely copy files with error handling."""
|
||||
os.makedirs(os.path.dirname(dst), exist_ok=True)
|
||||
shutil.copyfile(src, dst)
|
||||
logger.debug(f"File copied: {src} -> {dst}")
|
||||
return True
|
||||
|
||||
|
||||
class Espressif32Platform(PlatformBase):
|
||||
def configure_default_packages(self, variables, targets):
|
||||
if not variables.get("board"):
|
||||
return super().configure_default_packages(variables, targets)
|
||||
"""ESP32 platform implementation for PlatformIO with optimized toolchain management."""
|
||||
|
||||
board_config = self.board_config(variables.get("board"))
|
||||
mcu = variables.get("board_build.mcu", board_config.get("build.mcu", "esp32"))
|
||||
board_sdkconfig = variables.get("board_espidf.custom_sdkconfig", board_config.get("espidf.custom_sdkconfig", ""))
|
||||
core_variant_board = ''.join(variables.get("board_build.extra_flags", board_config.get("build.extra_flags", "")))
|
||||
core_variant_board = core_variant_board.replace("-D", " ")
|
||||
core_variant_build = (''.join(variables.get("build_flags", []))).replace("-D", " ")
|
||||
frameworks = variables.get("pioframework", [])
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize the ESP32 platform with caching mechanisms."""
|
||||
super().__init__(*args, **kwargs)
|
||||
self._packages_dir = None
|
||||
self._tools_cache = {}
|
||||
self._mcu_config_cache = {}
|
||||
|
||||
@property
|
||||
def packages_dir(self) -> str:
|
||||
"""Get cached packages directory path."""
|
||||
if self._packages_dir is None:
|
||||
config = ProjectConfig.get_instance()
|
||||
self._packages_dir = config.get("platformio", "packages_dir")
|
||||
return self._packages_dir
|
||||
|
||||
def _get_tool_paths(self, tool_name: str) -> Dict[str, str]:
|
||||
"""Get centralized path calculation for tools with caching."""
|
||||
if tool_name not in self._tools_cache:
|
||||
tool_path = os.path.join(self.packages_dir, tool_name)
|
||||
self._tools_cache[tool_name] = {
|
||||
'tool_path': tool_path,
|
||||
'package_path': os.path.join(tool_path, "package.json"),
|
||||
'tools_json_path': os.path.join(tool_path, "tools.json"),
|
||||
'piopm_path': os.path.join(tool_path, ".piopm"),
|
||||
'idf_tools_path': os.path.join(
|
||||
self.packages_dir, "tl-install", "tools", "idf_tools.py"
|
||||
)
|
||||
}
|
||||
return self._tools_cache[tool_name]
|
||||
|
||||
def _check_tool_status(self, tool_name: str) -> Dict[str, bool]:
|
||||
"""Check the installation status of a tool."""
|
||||
paths = self._get_tool_paths(tool_name)
|
||||
return {
|
||||
'has_idf_tools': os.path.exists(paths['idf_tools_path']),
|
||||
'has_tools_json': os.path.exists(paths['tools_json_path']),
|
||||
'has_piopm': os.path.exists(paths['piopm_path']),
|
||||
'tool_exists': os.path.exists(paths['tool_path'])
|
||||
}
|
||||
|
||||
def _run_idf_tools_install(self, tools_json_path: str, idf_tools_path: str) -> bool:
|
||||
"""Execute idf_tools.py install command with timeout and error handling."""
|
||||
cmd = [
|
||||
python_exe,
|
||||
idf_tools_path,
|
||||
"--quiet",
|
||||
"--non-interactive",
|
||||
"--tools-json",
|
||||
tools_json_path,
|
||||
"install"
|
||||
]
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
timeout=SUBPROCESS_TIMEOUT,
|
||||
check=False
|
||||
)
|
||||
|
||||
if result.returncode != 0:
|
||||
logger.error("idf_tools.py installation failed")
|
||||
return False
|
||||
|
||||
logger.debug("idf_tools.py executed successfully")
|
||||
return True
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
logger.error(f"Timeout in idf_tools.py after {SUBPROCESS_TIMEOUT}s")
|
||||
return False
|
||||
except (subprocess.SubprocessError, OSError) as e:
|
||||
logger.error(f"Error in idf_tools.py: {e}")
|
||||
return False
|
||||
|
||||
def _check_tool_version(self, tool_name: str) -> bool:
|
||||
"""Check if the installed tool version matches the required version."""
|
||||
paths = self._get_tool_paths(tool_name)
|
||||
|
||||
try:
|
||||
with open(paths['package_path'], 'r', encoding='utf-8') as f:
|
||||
package_data = json.load(f)
|
||||
|
||||
required_version = self.packages.get(tool_name, {}).get("package-version")
|
||||
installed_version = package_data.get("version")
|
||||
|
||||
if not required_version:
|
||||
logger.debug(f"No version check required for {tool_name}")
|
||||
return True
|
||||
|
||||
if not installed_version:
|
||||
logger.warning(f"Installed version for {tool_name} unknown")
|
||||
return False
|
||||
|
||||
version_match = required_version == installed_version
|
||||
if not version_match:
|
||||
logger.info(
|
||||
f"Version mismatch for {tool_name}: "
|
||||
f"{installed_version} != {required_version}"
|
||||
)
|
||||
|
||||
return version_match
|
||||
|
||||
except (json.JSONDecodeError, FileNotFoundError) as e:
|
||||
logger.error(f"Error reading package data for {tool_name}: {e}")
|
||||
return False
|
||||
|
||||
def install_tool(self, tool_name: str, retry_count: int = 0) -> bool:
|
||||
"""Install a tool with optimized retry mechanism."""
|
||||
if retry_count >= RETRY_LIMIT:
|
||||
logger.error(
|
||||
f"Installation of {tool_name} failed after {RETRY_LIMIT} attempts"
|
||||
)
|
||||
return False
|
||||
|
||||
self.packages[tool_name]["optional"] = False
|
||||
paths = self._get_tool_paths(tool_name)
|
||||
status = self._check_tool_status(tool_name)
|
||||
|
||||
# Case 1: New installation with idf_tools
|
||||
if status['has_idf_tools'] and status['has_tools_json']:
|
||||
return self._install_with_idf_tools(tool_name, paths)
|
||||
|
||||
# Case 2: Tool already installed, version check
|
||||
if (status['has_idf_tools'] and status['has_piopm'] and
|
||||
not status['has_tools_json']):
|
||||
return self._handle_existing_tool(tool_name, paths, retry_count)
|
||||
|
||||
logger.debug(f"Tool {tool_name} already configured")
|
||||
return True
|
||||
|
||||
def _install_with_idf_tools(self, tool_name: str, paths: Dict[str, str]) -> bool:
|
||||
"""Install tool using idf_tools.py installation method."""
|
||||
if not self._run_idf_tools_install(
|
||||
paths['tools_json_path'], paths['idf_tools_path']
|
||||
):
|
||||
return False
|
||||
|
||||
# Copy tool files
|
||||
tools_path_default = os.path.join(
|
||||
os.path.expanduser("~"), ".platformio"
|
||||
)
|
||||
target_package_path = os.path.join(
|
||||
tools_path_default, "tools", tool_name, "package.json"
|
||||
)
|
||||
|
||||
if not safe_copy_file(paths['package_path'], target_package_path):
|
||||
return False
|
||||
|
||||
safe_remove_directory(paths['tool_path'])
|
||||
|
||||
tl_path = f"file://{os.path.join(tools_path_default, 'tools', tool_name)}"
|
||||
pm.install(tl_path)
|
||||
|
||||
logger.info(f"Tool {tool_name} successfully installed")
|
||||
return True
|
||||
|
||||
def _handle_existing_tool(
|
||||
self, tool_name: str, paths: Dict[str, str], retry_count: int
|
||||
) -> bool:
|
||||
"""Handle already installed tools with version checking."""
|
||||
if self._check_tool_version(tool_name):
|
||||
# Version matches, use tool
|
||||
self.packages[tool_name]["version"] = paths['tool_path']
|
||||
self.packages[tool_name]["optional"] = False
|
||||
logger.debug(f"Tool {tool_name} found with correct version")
|
||||
return True
|
||||
|
||||
# Wrong version, reinstall
|
||||
logger.info(f"Reinstalling {tool_name} due to version mismatch")
|
||||
safe_remove_directory(paths['tool_path'])
|
||||
return self.install_tool(tool_name, retry_count + 1)
|
||||
|
||||
def _configure_arduino_framework(self, frameworks: List[str]) -> None:
|
||||
"""Configure Arduino framework with dynamic library URL fetching."""
|
||||
if "arduino" not in frameworks:
|
||||
return
|
||||
|
||||
if "arduino" in frameworks:
|
||||
self.packages["framework-arduinoespressif32"]["optional"] = False
|
||||
self.packages["framework-arduinoespressif32-libs"]["optional"] = False
|
||||
|
||||
if variables.get("custom_sdkconfig") is not None or len(str(board_sdkconfig)) > 3:
|
||||
def _configure_espidf_framework(
|
||||
self, frameworks: List[str], variables: Dict, board_config: Dict, mcu: str
|
||||
) -> None:
|
||||
"""Configure ESP-IDF framework based on custom sdkconfig settings."""
|
||||
custom_sdkconfig = variables.get("custom_sdkconfig")
|
||||
board_sdkconfig = variables.get(
|
||||
"board_espidf.custom_sdkconfig",
|
||||
board_config.get("espidf.custom_sdkconfig", "")
|
||||
)
|
||||
|
||||
if custom_sdkconfig is not None or len(str(board_sdkconfig)) > 3:
|
||||
frameworks.append("espidf")
|
||||
self.packages["framework-espidf"]["optional"] = False
|
||||
if mcu == "esp32c2":
|
||||
self.packages["framework-arduino-c2-skeleton-lib"]["optional"] = False
|
||||
|
||||
# Enable check tools only when "check_tool" is active
|
||||
for p in self.packages:
|
||||
if p in ("tool-cppcheck", "tool-clangtidy", "tool-pvs-studio"):
|
||||
self.packages[p]["optional"] = False if str(variables.get("check_tool")).strip("['']") in p else True
|
||||
def _get_mcu_config(self, mcu: str) -> Optional[Dict]:
|
||||
"""Get MCU configuration with optimized caching and search."""
|
||||
if mcu in self._mcu_config_cache:
|
||||
return self._mcu_config_cache[mcu]
|
||||
|
||||
if "buildfs" in targets:
|
||||
filesystem = variables.get("board_build.filesystem", "littlefs")
|
||||
if filesystem == "littlefs":
|
||||
self.packages["tool-mklittlefs"]["optional"] = False
|
||||
elif filesystem == "fatfs":
|
||||
self.packages["tool-mkfatfs"]["optional"] = False
|
||||
for _, config in MCU_TOOLCHAIN_CONFIG.items():
|
||||
if mcu in config["mcus"]:
|
||||
# Dynamically add ULP toolchain
|
||||
result = config.copy()
|
||||
result["ulp_toolchain"] = ["toolchain-esp32ulp"]
|
||||
if mcu != "esp32":
|
||||
result["ulp_toolchain"].append("toolchain-riscv32-esp")
|
||||
self._mcu_config_cache[mcu] = result
|
||||
return result
|
||||
return None
|
||||
|
||||
def _needs_debug_tools(self, variables: Dict, targets: List[str]) -> bool:
|
||||
"""Check if debug tools are needed based on build configuration."""
|
||||
return bool(
|
||||
variables.get("build_type") or
|
||||
"debug" in targets or
|
||||
variables.get("upload_protocol")
|
||||
)
|
||||
|
||||
def _configure_mcu_toolchains(
|
||||
self, mcu: str, variables: Dict, targets: List[str]
|
||||
) -> None:
|
||||
"""Configure MCU-specific toolchains with optimized installation."""
|
||||
mcu_config = self._get_mcu_config(mcu)
|
||||
if not mcu_config:
|
||||
logger.warning(f"Unknown MCU: {mcu}")
|
||||
return
|
||||
|
||||
# Install base toolchains
|
||||
for toolchain in mcu_config["toolchains"]:
|
||||
self.install_tool(toolchain)
|
||||
|
||||
# ULP toolchain if ULP directory exists
|
||||
if mcu_config.get("ulp_toolchain") and os.path.isdir("ulp"):
|
||||
for toolchain in mcu_config["ulp_toolchain"]:
|
||||
self.install_tool(toolchain)
|
||||
|
||||
# Debug tools when needed
|
||||
if self._needs_debug_tools(variables, targets):
|
||||
for debug_tool in mcu_config["debug_tools"]:
|
||||
self.install_tool(debug_tool)
|
||||
self.install_tool("tool-openocd-esp32")
|
||||
|
||||
def _configure_installer(self) -> None:
|
||||
"""Configure the ESP-IDF tools installer."""
|
||||
installer_path = os.path.join(
|
||||
self.packages_dir, "tl-install", "tools", "idf_tools.py"
|
||||
)
|
||||
if os.path.exists(installer_path):
|
||||
self.packages["tl-install"]["optional"] = True
|
||||
|
||||
def _install_common_idf_packages(self) -> None:
|
||||
"""Install common ESP-IDF packages required for all builds."""
|
||||
for package in COMMON_IDF_PACKAGES:
|
||||
self.install_tool(package)
|
||||
|
||||
def _configure_check_tools(self, variables: Dict) -> None:
|
||||
"""Configure static analysis and check tools based on configuration."""
|
||||
check_tools = variables.get("check_tool", [])
|
||||
if not check_tools:
|
||||
return
|
||||
|
||||
for package in CHECK_PACKAGES:
|
||||
if any(tool in package for tool in check_tools):
|
||||
self.install_tool(package)
|
||||
|
||||
def _ensure_mklittlefs_version(self) -> None:
|
||||
"""Ensure correct mklittlefs version is installed."""
|
||||
piopm_path = os.path.join(self.packages_dir, "tool-mklittlefs", ".piopm")
|
||||
|
||||
if os.path.exists(piopm_path):
|
||||
try:
|
||||
with open(piopm_path, 'r', encoding='utf-8') as f:
|
||||
package_data = json.load(f)
|
||||
if package_data.get('version') != MKLITTLEFS_VERSION_320:
|
||||
os.remove(piopm_path)
|
||||
logger.info("Outdated mklittlefs version removed")
|
||||
except (json.JSONDecodeError, KeyError) as e:
|
||||
logger.error(f"Error reading mklittlefs package data: {e}")
|
||||
|
||||
def _setup_mklittlefs_for_download(self) -> None:
|
||||
"""Setup mklittlefs for download functionality with version 4.0.0."""
|
||||
mklittlefs_dir = os.path.join(self.packages_dir, "tool-mklittlefs")
|
||||
mklittlefs400_dir = os.path.join(
|
||||
self.packages_dir, "tool-mklittlefs-4.0.0"
|
||||
)
|
||||
|
||||
# Ensure mklittlefs 3.2.0 is installed
|
||||
if not os.path.exists(mklittlefs_dir):
|
||||
self.install_tool("tool-mklittlefs")
|
||||
if os.path.exists(os.path.join(mklittlefs_dir, "tools.json")):
|
||||
self.install_tool("tool-mklittlefs")
|
||||
|
||||
# Install mklittlefs 4.0.0
|
||||
if not os.path.exists(mklittlefs400_dir):
|
||||
self.install_tool("tool-mklittlefs-4.0.0")
|
||||
if os.path.exists(os.path.join(mklittlefs400_dir, "tools.json")):
|
||||
self.install_tool("tool-mklittlefs-4.0.0")
|
||||
|
||||
# Copy mklittlefs 4.0.0 over 3.2.0
|
||||
if os.path.exists(mklittlefs400_dir):
|
||||
package_src = os.path.join(mklittlefs_dir, "package.json")
|
||||
package_dst = os.path.join(mklittlefs400_dir, "package.json")
|
||||
safe_copy_file(package_src, package_dst)
|
||||
shutil.copytree(mklittlefs400_dir, mklittlefs_dir, dirs_exist_ok=True)
|
||||
self.packages.pop("tool-mkfatfs", None)
|
||||
|
||||
def _handle_littlefs_tool(self, for_download: bool) -> None:
|
||||
"""Handle LittleFS tool installation with special download configuration."""
|
||||
if for_download:
|
||||
self._setup_mklittlefs_for_download()
|
||||
else:
|
||||
self.packages["tool-mkspiffs"]["optional"] = False
|
||||
if variables.get("upload_protocol"):
|
||||
self.packages["tool-openocd-esp32"]["optional"] = False
|
||||
if os.path.isdir("ulp"):
|
||||
self.packages["toolchain-esp32ulp"]["optional"] = False
|
||||
self._ensure_mklittlefs_version()
|
||||
self.install_tool("tool-mklittlefs")
|
||||
|
||||
if "downloadfs" in targets:
|
||||
filesystem = variables.get("board_build.filesystem", "littlefs")
|
||||
if filesystem == "littlefs":
|
||||
# Use Tasmota mklittlefs v4.0.0 to unpack, older version is incompatible
|
||||
self.packages["tool-mklittlefs"]["version"] = "~4.0.0"
|
||||
def _install_filesystem_tool(self, filesystem: str, for_download: bool = False) -> None:
|
||||
"""Install filesystem-specific tools based on the filesystem type."""
|
||||
tool_mapping = {
|
||||
"default": lambda: self._handle_littlefs_tool(for_download),
|
||||
"fatfs": lambda: self.install_tool("tool-mkfatfs"),
|
||||
"spiffs": lambda: self.install_tool("tool-mkspiffs")
|
||||
}
|
||||
|
||||
handler = tool_mapping.get(filesystem, tool_mapping["default"])
|
||||
handler()
|
||||
|
||||
def _handle_dfuutil_tool(self, variables: Dict, for_download: bool = False) -> None:
|
||||
"""Install dfuutil tool for Arduino Nano ESP32 board."""
|
||||
# Currently only Arduino Nano ESP32 uses the dfuutil tool as uploader
|
||||
if variables.get("board") == "arduino_nano_esp32":
|
||||
self.packages["tool-dfuutil-arduino"]["optional"] = False
|
||||
else:
|
||||
del self.packages["tool-dfuutil-arduino"]
|
||||
self.install_tool("tool-dfuutil-arduino")
|
||||
|
||||
# Starting from v12, Espressif's toolchains are shipped without
|
||||
# bundled GDB. Instead, it's distributed as separate packages for Xtensa
|
||||
# and RISC-V targets.
|
||||
for gdb_package in ("tool-xtensa-esp-elf-gdb", "tool-riscv32-esp-elf-gdb"):
|
||||
self.packages[gdb_package]["optional"] = False
|
||||
# if IS_WINDOWS:
|
||||
# Note: On Windows GDB v12 is not able to
|
||||
# launch a GDB server in pipe mode while v11 works fine
|
||||
# self.packages[gdb_package]["version"] = "~11.2.0"
|
||||
def _configure_filesystem_tools(self, variables: Dict, targets: List[str]) -> None:
|
||||
"""Configure filesystem tools based on build targets and filesystem type."""
|
||||
filesystem = variables.get("board_build.filesystem", "littlefs")
|
||||
|
||||
if any(target in targets for target in ["buildfs", "uploadfs"]):
|
||||
self._install_filesystem_tool(filesystem, for_download=False)
|
||||
|
||||
if "downloadfs" in targets:
|
||||
self._install_filesystem_tool(filesystem, for_download=True)
|
||||
|
||||
def configure_default_packages(self, variables: Dict, targets: List[str]) -> Any:
|
||||
"""Main configuration method with optimized package management."""
|
||||
if not variables.get("board"):
|
||||
return super().configure_default_packages(variables, targets)
|
||||
|
||||
# Base configuration
|
||||
board_config = self.board_config(variables.get("board"))
|
||||
mcu = variables.get("board_build.mcu", board_config.get("build.mcu", "esp32"))
|
||||
frameworks = list(variables.get("pioframework", [])) # Create copy
|
||||
|
||||
try:
|
||||
# Configuration steps
|
||||
self._configure_installer()
|
||||
self._configure_arduino_framework(frameworks)
|
||||
self._configure_espidf_framework(frameworks, variables, board_config, mcu)
|
||||
self._configure_mcu_toolchains(mcu, variables, targets)
|
||||
|
||||
# Common packages for IDF and mixed Arduino+IDF projects
|
||||
if "espidf" in frameworks:
|
||||
self.packages["toolchain-esp32ulp"]["optional"] = False
|
||||
for p in self.packages:
|
||||
if p in ("tool-scons", "tool-cmake", "tool-ninja"):
|
||||
self.packages[p]["optional"] = False
|
||||
# elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS:
|
||||
# self.packages[p]["optional"] = False
|
||||
self._install_common_idf_packages()
|
||||
|
||||
if mcu in ("esp32", "esp32s2", "esp32s3"):
|
||||
self.packages["toolchain-xtensa-esp-elf"]["optional"] = False
|
||||
else:
|
||||
self.packages.pop("toolchain-xtensa-esp-elf", None)
|
||||
self._configure_check_tools(variables)
|
||||
self._configure_filesystem_tools(variables, targets)
|
||||
self._handle_dfuutil_tool(variables)
|
||||
|
||||
if mcu in ("esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"):
|
||||
if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"):
|
||||
self.packages.pop("toolchain-esp32ulp", None)
|
||||
# RISC-V based toolchain for ESP32C3, ESP32C6 ESP32S2, ESP32S3 ULP
|
||||
self.packages["toolchain-riscv32-esp"]["optional"] = False
|
||||
logger.info("Package configuration completed successfully")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in package configuration: {type(e).__name__}: {e}")
|
||||
# Don't re-raise to maintain compatibility
|
||||
|
||||
return super().configure_default_packages(variables, targets)
|
||||
|
||||
def get_boards(self, id_=None):
|
||||
"""Get board configuration with dynamic options."""
|
||||
result = super().get_boards(id_)
|
||||
if not result:
|
||||
return result
|
||||
@@ -127,13 +508,14 @@ class Espressif32Platform(PlatformBase):
|
||||
return result
|
||||
|
||||
def _add_dynamic_options(self, board):
|
||||
# upload protocols
|
||||
"""Add dynamic board options for upload protocols and debug tools."""
|
||||
# Upload protocols
|
||||
if not board.get("upload.protocols", []):
|
||||
board.manifest["upload"]["protocols"] = ["esptool", "espota"]
|
||||
if not board.get("upload.protocol", ""):
|
||||
board.manifest["upload"]["protocol"] = "esptool"
|
||||
|
||||
# debug tools
|
||||
# Debug tools
|
||||
debug = board.manifest.get("debug", {})
|
||||
non_debug_protocols = ["esptool", "espota"]
|
||||
supported_debug_tools = [
|
||||
@@ -147,17 +529,21 @@ class Espressif32Platform(PlatformBase):
|
||||
"olimex-arm-usb-ocd-h",
|
||||
"olimex-arm-usb-ocd",
|
||||
"olimex-jtag-tiny",
|
||||
"tumpa",
|
||||
"tumpa"
|
||||
]
|
||||
|
||||
# A special case for the Kaluga board that has a separate interface config
|
||||
# Special configuration for Kaluga board
|
||||
if board.id == "esp32-s2-kaluga-1":
|
||||
supported_debug_tools.append("ftdi")
|
||||
if board.get("build.mcu", "") in ("esp32c3", "esp32c6", "esp32s3", "esp32h2"):
|
||||
|
||||
# ESP-builtin for certain MCUs
|
||||
mcu = board.get("build.mcu", "")
|
||||
if mcu in ESP_BUILTIN_DEBUG_MCUS:
|
||||
supported_debug_tools.append("esp-builtin")
|
||||
|
||||
upload_protocol = board.manifest.get("upload", {}).get("protocol")
|
||||
upload_protocols = board.manifest.get("upload", {}).get("protocols", [])
|
||||
|
||||
if debug:
|
||||
upload_protocols.extend(supported_debug_tools)
|
||||
if upload_protocol and upload_protocol not in upload_protocols:
|
||||
@@ -167,37 +553,13 @@ class Espressif32Platform(PlatformBase):
|
||||
if "tools" not in debug:
|
||||
debug["tools"] = {}
|
||||
|
||||
# Debug tool configuration
|
||||
for link in upload_protocols:
|
||||
if link in non_debug_protocols or link in debug["tools"]:
|
||||
continue
|
||||
|
||||
if link in ("jlink", "cmsis-dap"):
|
||||
openocd_interface = link
|
||||
elif link in ("esp-prog", "ftdi"):
|
||||
if board.id == "esp32-s2-kaluga-1":
|
||||
openocd_interface = "ftdi/esp32s2_kaluga_v1"
|
||||
else:
|
||||
openocd_interface = "ftdi/esp32_devkitj_v1"
|
||||
elif link == "esp-bridge":
|
||||
openocd_interface = "esp_usb_bridge"
|
||||
elif link == "esp-builtin":
|
||||
openocd_interface = "esp_usb_jtag"
|
||||
else:
|
||||
openocd_interface = "ftdi/" + link
|
||||
|
||||
server_args = [
|
||||
"-s",
|
||||
"$PACKAGE_DIR/share/openocd/scripts",
|
||||
"-f",
|
||||
"interface/%s.cfg" % openocd_interface,
|
||||
"-f",
|
||||
"%s/%s"
|
||||
% (
|
||||
("target", debug.get("openocd_target"))
|
||||
if "openocd_target" in debug
|
||||
else ("board", debug.get("openocd_board"))
|
||||
),
|
||||
]
|
||||
openocd_interface = self._get_openocd_interface(link, board)
|
||||
server_args = self._get_debug_server_args(openocd_interface, debug)
|
||||
|
||||
debug["tools"][link] = {
|
||||
"server": {
|
||||
@@ -229,14 +591,43 @@ class Espressif32Platform(PlatformBase):
|
||||
board.manifest["debug"] = debug
|
||||
return board
|
||||
|
||||
def _get_openocd_interface(self, link: str, board) -> str:
|
||||
"""Determine OpenOCD interface configuration for debug link."""
|
||||
if link in ("jlink", "cmsis-dap"):
|
||||
return link
|
||||
if link in ("esp-prog", "ftdi"):
|
||||
if board.id == "esp32-s2-kaluga-1":
|
||||
return "ftdi/esp32s2_kaluga_v1"
|
||||
return "ftdi/esp32_devkitj_v1"
|
||||
if link == "esp-bridge":
|
||||
return "esp_usb_bridge"
|
||||
if link == "esp-builtin":
|
||||
return "esp_usb_jtag"
|
||||
return f"ftdi/{link}"
|
||||
|
||||
def _get_debug_server_args(self, openocd_interface: str, debug: Dict) -> List[str]:
|
||||
"""Generate debug server arguments for OpenOCD configuration."""
|
||||
if 'openocd_target' in debug:
|
||||
config_type = 'target'
|
||||
config_name = debug.get('openocd_target')
|
||||
else:
|
||||
config_type = 'board'
|
||||
config_name = debug.get('openocd_board')
|
||||
return [
|
||||
"-s", "$PACKAGE_DIR/share/openocd/scripts",
|
||||
"-f", f"interface/{openocd_interface}.cfg",
|
||||
"-f", f"{config_type}/{config_name}.cfg"
|
||||
]
|
||||
|
||||
def configure_debug_session(self, debug_config):
|
||||
"""Configure debug session with flash image loading."""
|
||||
build_extra_data = debug_config.build_data.get("extra", {})
|
||||
flash_images = build_extra_data.get("flash_images", [])
|
||||
|
||||
if "openocd" in (debug_config.server or {}).get("executable", ""):
|
||||
debug_config.server["arguments"].extend(
|
||||
["-c", "adapter speed %s" % (debug_config.speed or "5000")]
|
||||
)
|
||||
debug_config.server["arguments"].extend([
|
||||
"-c", f"adapter speed {debug_config.speed or DEFAULT_DEBUG_SPEED}"
|
||||
])
|
||||
|
||||
ignore_conds = [
|
||||
debug_config.load_cmds != ["load"],
|
||||
@@ -248,16 +639,13 @@ class Espressif32Platform(PlatformBase):
|
||||
return
|
||||
|
||||
load_cmds = [
|
||||
'monitor program_esp "{{{path}}}" {offset} verify'.format(
|
||||
path=to_unix_path(item["path"]), offset=item["offset"]
|
||||
)
|
||||
f'monitor program_esp "{to_unix_path(item["path"])}" '
|
||||
f'{item["offset"]} verify'
|
||||
for item in flash_images
|
||||
]
|
||||
load_cmds.append(
|
||||
'monitor program_esp "{%s.bin}" %s verify'
|
||||
% (
|
||||
to_unix_path(debug_config.build_data["prog_path"][:-4]),
|
||||
build_extra_data.get("application_offset", "0x10000"),
|
||||
)
|
||||
f'monitor program_esp '
|
||||
f'"{to_unix_path(debug_config.build_data["prog_path"][:-4])}.bin" '
|
||||
f'{build_extra_data.get("application_offset", DEFAULT_APP_OFFSET)} verify'
|
||||
)
|
||||
debug_config.load_cmds = load_cmds
|
||||
|
||||
Reference in New Issue
Block a user