Arduino Core 3.3.7
This commit is contained in:
@@ -52,21 +52,21 @@ jobs:
|
|||||||
example: "examples/espidf-arduino-matter-light"
|
example: "examples/espidf-arduino-matter-light"
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: "recursive"
|
submodules: "recursive"
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: "3.13"
|
python-version: "3.13"
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@v6
|
uses: astral-sh/setup-uv@v7
|
||||||
with:
|
with:
|
||||||
version: "latest"
|
version: "latest"
|
||||||
enable-cache: false
|
enable-cache: false
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
uv pip install --system -U https://github.com/pioarduino/platformio-core/archive/refs/tags/v6.1.18.zip
|
uv pip install --system -U https://github.com/pioarduino/platformio-core/archive/refs/tags/v6.1.19.zip
|
||||||
pio pkg install --global --platform file://.
|
pio pkg install --global --platform file://.
|
||||||
- name: git clone Tasmota and add to examples
|
- name: git clone Tasmota and add to examples
|
||||||
if: "matrix.example == 'examples/tasmota'"
|
if: "matrix.example == 'examples/tasmota'"
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
# FatFS Integration for Platform-Espressif32
|
||||||
|
|
||||||
|
This platform now supports FatFS as a filesystem option, analogous to the existing LittleFS integration.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Build FatFS Image**: Creates a FatFS filesystem image from a directory
|
||||||
|
- **Upload FatFS Image**: Uploads the FatFS image to the ESP32 device
|
||||||
|
- **Download FatFS Image**: Downloads the FatFS image from the device and extracts it
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### platformio.ini
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[env:myenv]
|
||||||
|
platform = espressif32
|
||||||
|
board = esp32dev
|
||||||
|
framework = arduino
|
||||||
|
|
||||||
|
; Select FatFS as filesystem
|
||||||
|
board_build.filesystem = fatfs
|
||||||
|
|
||||||
|
; Optional: Directory for extracted files (default: unpacked_fs)
|
||||||
|
board_build.unpack_dir = unpacked_fs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Partition Table
|
||||||
|
|
||||||
|
The partition table must contain a FAT partition (Subtype 0x81):
|
||||||
|
|
||||||
|
```csv
|
||||||
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
|
nvs, data, nvs, 0x9000, 0x5000,
|
||||||
|
otadata, data, ota, 0xe000, 0x2000,
|
||||||
|
app0, app, ota_0, 0x10000, 0x140000,
|
||||||
|
app1, app, ota_1, 0x150000,0x140000,
|
||||||
|
ffat, data, fat, 0x290000,0x170000,
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Build FatFS Image
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Place files in data/ directory
|
||||||
|
mkdir -p data
|
||||||
|
echo "Hello FatFS" > data/test.txt
|
||||||
|
|
||||||
|
# Build image
|
||||||
|
pio run -t buildfs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Upload FatFS Image
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pio run -t uploadfs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Download FatFS Image from Device
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pio run -t download_fatfs
|
||||||
|
```
|
||||||
|
|
||||||
|
Files will be extracted to the configured directory (default: `unpacked_fs`).
|
||||||
|
|
||||||
|
## Technical Details
|
||||||
|
|
||||||
|
### Python Dependencies
|
||||||
|
|
||||||
|
The integration uses the `fatfs-ng` package, which is automatically installed.
|
||||||
|
|
||||||
|
### Build Process
|
||||||
|
|
||||||
|
1. A RAM disk is created with the configured FAT data size (partition size minus WL overhead)
|
||||||
|
2. The FatFS is formatted with proper parameters (2 FATs, LFN support)
|
||||||
|
3. All files from the `data/` directory are copied
|
||||||
|
4. The FAT image is wrapped with ESP32 Wear Leveling layer
|
||||||
|
5. The final image is saved as a `.bin` file
|
||||||
|
|
||||||
|
**Important**: The build process automatically adds the ESP32 Wear Leveling layer, which is required by the Arduino FFat library. See [WEAR_LEVELING.md](WEAR_LEVELING.md) for details.
|
||||||
|
|
||||||
|
### Wear Leveling Layer
|
||||||
|
|
||||||
|
ESP32's FFat library requires a wear leveling layer around the FAT filesystem. The build process automatically:
|
||||||
|
- Reserves sectors for wear leveling metadata
|
||||||
|
- Wraps the FAT filesystem with WL_State structures
|
||||||
|
- Calculates proper CRC32 checksums
|
||||||
|
|
||||||
|
### Download Process
|
||||||
|
|
||||||
|
1. The partition table is downloaded from the device
|
||||||
|
2. The FAT partition is identified (Subtype 0x81)
|
||||||
|
3. The filesystem image is downloaded
|
||||||
|
4. The wear leveling layer is automatically detected and removed
|
||||||
|
5. The FAT data is mounted and extracted
|
||||||
|
|
||||||
|
## Extended Features
|
||||||
|
|
||||||
|
The `pyfatfs` package includes extended features for complete directory traversal:
|
||||||
|
|
||||||
|
- **Complete Directory Traversal**: `walk()`, `listdir()`, `stat()`
|
||||||
|
- **Path Operations**: `exists()`, `isfile()`, `isdir()`
|
||||||
|
- **File Operations**: `remove()`, `rmdir()`, `rename()`, `makedirs()`
|
||||||
|
- **Convenience Methods**: `read_file()`, `write_file()`
|
||||||
|
- **Bulk Operations**: `copy_tree_from()`, `copy_tree_to()`
|
||||||
|
|
||||||
|
These features enable full filesystem extraction and manipulation.
|
||||||
|
|
||||||
|
## Comparison: LittleFS vs FatFS
|
||||||
|
|
||||||
|
| Feature | LittleFS | FatFS |
|
||||||
|
|---------|----------|-------|
|
||||||
|
| Wear Leveling | Yes | Yes |
|
||||||
|
| Power-Loss Protection | Yes | Limited |
|
||||||
|
| Compatibility | ESP-IDF specific | Standard FAT |
|
||||||
|
| Sector Size | 4096 | 4096 |
|
||||||
|
| Filesystem Size | Flexible | Larger |
|
||||||
|
|
||||||
|
## Example Code (Arduino)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <FFat.h>
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// Mount FatFS
|
||||||
|
if (!FFat.begin(true)) {
|
||||||
|
Serial.println("FFat Mount Failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read file
|
||||||
|
File file = FFat.open("/test.txt", "r");
|
||||||
|
if (file) {
|
||||||
|
Serial.println(file.readString());
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write file
|
||||||
|
file = FFat.open("/output.txt", "w");
|
||||||
|
if (file) {
|
||||||
|
file.println("Hello from ESP32!");
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "No FAT filesystem partition found"
|
||||||
|
|
||||||
|
- Check the partition table
|
||||||
|
- Ensure a partition with subtype `fat` (0x81) exists
|
||||||
|
|
||||||
|
### Build Errors
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Recreate Python environment
|
||||||
|
rm -rf ~/.platformio/penv
|
||||||
|
pio run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Further Information
|
||||||
|
|
||||||
|
- [FatFS Documentation](http://elm-chan.org/fsw/ff/00index_e.html)
|
||||||
|
- [ESP-IDF FFat Documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/storage/fatfs.html)
|
||||||
|
- [fatfs-ng Repository](https://github.com/Jason2866/pyfatfs)
|
||||||
|
- [Original fatfs-python](https://github.com/krakonos/fatfs-python)
|
||||||
@@ -13,7 +13,7 @@ Espressif Systems is a privately held, fabless semiconductor company renowned fo
|
|||||||
* No support for the Arduino Nora Nano board, issues needs to be solved by the community
|
* No support for the Arduino Nora Nano board, issues needs to be solved by the community
|
||||||
## IDE Preparation
|
## IDE Preparation
|
||||||
Prerequisites:
|
Prerequisites:
|
||||||
- Python (3.10, 3.11, 3.12, 3.13) and git is required for pioarduino to function properly.
|
- Python (3.10, 3.11, 3.12, 3.13, 3.14 not with Windows!) and git is required for pioarduino to function properly.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
- [Download and install Microsoft Visual Studio Code](https://code.visualstudio.com/). pioarduino IDE is on top of it.
|
- [Download and install Microsoft Visual Studio Code](https://code.visualstudio.com/). pioarduino IDE is on top of it.
|
||||||
@@ -57,7 +57,7 @@ pio run -t download_fatfs # Download and extract FatFS from device
|
|||||||
See the [arduino-fatfs example](examples/arduino-fatfs/) for a complete working example.
|
See the [arduino-fatfs example](examples/arduino-fatfs/) for a complete working example.
|
||||||
|
|
||||||
### Stable Arduino
|
### Stable Arduino
|
||||||
currently espressif Arduino 3.3.6 and IDF 5.5.2+
|
currently espressif Arduino 3.3.7 and IDF v5.5.2+
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
[env:stable]
|
[env:stable]
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"core": "esp32",
|
||||||
|
"f_cpu": "160000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"mcu": "esp32c61",
|
||||||
|
"variant": "esp32c61"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"bluetooth",
|
||||||
|
"wifi"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32c61.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "Espressif ESP32-C61-DevKitC-1 (4 MB Flash)",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "4MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 4194304,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 460800
|
||||||
|
},
|
||||||
|
"espidf": {
|
||||||
|
"custom_sdkconfig": [
|
||||||
|
"CONFIG_IDF_TARGET=\"esp32c61\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"url": "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32c61/esp32-c61-devkitc-1/user_guide.html",
|
||||||
|
"vendor": "Espressif"
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||||
|
"-DARDUINO_USB_MODE=1",
|
||||||
|
"-DBOARD_HAS_PSRAM"
|
||||||
|
],
|
||||||
|
"f_cpu": "400000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"f_psram": "200000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"mcu": "esp32p4",
|
||||||
|
"chip_variant": "esp32p4",
|
||||||
|
"variant": "esp32p4"
|
||||||
|
},
|
||||||
|
"arduino": {
|
||||||
|
"partitions": "default_16MB.csv"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"bluetooth",
|
||||||
|
"openthread"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32p4.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "Espressif ESP32-P4 Function EV Board v1.6 (rev.301)",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "16MB",
|
||||||
|
"maximum_ram_size": 512000,
|
||||||
|
"maximum_size": 16777216,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 1500000
|
||||||
|
},
|
||||||
|
"url": "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32p4/esp32-p4-function-ev-board/index.html",
|
||||||
|
"vendor": "Espressif"
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino":{
|
||||||
|
"partitions": "default_8MB.csv",
|
||||||
|
"memory_type": "qio_qspi"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DARDUINO_YB_ESP32S3_AMP",
|
||||||
|
"-DARDUINO_USB_MODE=1",
|
||||||
|
"-DARDUINO_RUNNING_CORE=1",
|
||||||
|
"-DARDUINO_EVENT_RUNNING_CORE=1",
|
||||||
|
"-DBOARD_HAS_PSRAM"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"hwids": [
|
||||||
|
[
|
||||||
|
"0x303A",
|
||||||
|
"0x1001"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"0x1A86",
|
||||||
|
"0x55D3"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "yb_esp32s3_amp"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"wifi",
|
||||||
|
"bluetooth"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"default_tool": "esp-builtin",
|
||||||
|
"onboard_tools": [
|
||||||
|
"esp-builtin"
|
||||||
|
],
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "YelloByte YB-ESP32-S3-AMP",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "8MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 8388608,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 460800
|
||||||
|
},
|
||||||
|
"url": "https://github.com/yellobyte/YB-ESP32-S3-AMP",
|
||||||
|
"vendor": "YelloByte"
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino":{
|
||||||
|
"partitions": "default_8MB.csv",
|
||||||
|
"memory_type": "qio_qspi"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DARDUINO_YB_ESP32S3_DAC",
|
||||||
|
"-DARDUINO_USB_MODE=1",
|
||||||
|
"-DARDUINO_RUNNING_CORE=1",
|
||||||
|
"-DARDUINO_EVENT_RUNNING_CORE=1",
|
||||||
|
"-DBOARD_HAS_PSRAM"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"hwids": [
|
||||||
|
[
|
||||||
|
"0x303A",
|
||||||
|
"0x1001"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"0x1A86",
|
||||||
|
"0x55D3"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "yb_esp32s3_dac"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"wifi",
|
||||||
|
"bluetooth"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"default_tool": "esp-builtin",
|
||||||
|
"onboard_tools": [
|
||||||
|
"esp-builtin"
|
||||||
|
],
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "YelloByte YB-ESP32-S3-DAC",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "8MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 8388608,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 460800
|
||||||
|
},
|
||||||
|
"url": "https://github.com/yellobyte/YB-ESP32-S3-DAC",
|
||||||
|
"vendor": "YelloByte"
|
||||||
|
}
|
||||||
@@ -2067,7 +2067,7 @@ def install_python_deps():
|
|||||||
# https://github.com/platformio/platform-espressif32/issues/635
|
# https://github.com/platformio/platform-espressif32/issues/635
|
||||||
"cryptography": "~=44.0.0",
|
"cryptography": "~=44.0.0",
|
||||||
"pyparsing": ">=3.1.0,<4",
|
"pyparsing": ">=3.1.0,<4",
|
||||||
"idf-component-manager": "~=2.4",
|
"idf-component-manager": "~=2.4.6",
|
||||||
"esp-idf-kconfig": "~=2.5.0"
|
"esp-idf-kconfig": "~=2.5.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+46
-27
@@ -44,7 +44,7 @@ PLATFORMIO_URL_VERSION_RE = re.compile(
|
|||||||
|
|
||||||
# Python dependencies required for ESP32 platform builds
|
# Python dependencies required for ESP32 platform builds
|
||||||
python_deps = {
|
python_deps = {
|
||||||
"platformio": "https://github.com/pioarduino/platformio-core/archive/refs/tags/v6.1.18.zip",
|
"platformio": "https://github.com/pioarduino/platformio-core/archive/refs/tags/v6.1.19.zip",
|
||||||
"littlefs-python": ">=0.16.0",
|
"littlefs-python": ">=0.16.0",
|
||||||
"fatfs-ng": ">=0.1.14",
|
"fatfs-ng": ">=0.1.14",
|
||||||
"pyyaml": ">=6.0.2",
|
"pyyaml": ">=6.0.2",
|
||||||
@@ -219,13 +219,14 @@ def get_packages_to_install(deps, installed_packages):
|
|||||||
yield package
|
yield package
|
||||||
|
|
||||||
|
|
||||||
def install_python_deps(python_exe, external_uv_executable):
|
def install_python_deps(python_exe, external_uv_executable, uv_cache_dir=None):
|
||||||
"""
|
"""
|
||||||
Ensure uv package manager is available in penv and install required Python dependencies.
|
Ensure uv package manager is available in penv and install required Python dependencies.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
python_exe: Path to Python executable in the penv
|
python_exe: Path to Python executable in the penv
|
||||||
external_uv_executable: Path to external uv executable used to create the penv (can be None)
|
external_uv_executable: Path to external uv executable used to create the penv (can be None)
|
||||||
|
uv_cache_dir: Optional path to uv cache directory
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: True if successful, False otherwise
|
bool: True if successful, False otherwise
|
||||||
@@ -233,6 +234,12 @@ def install_python_deps(python_exe, external_uv_executable):
|
|||||||
# Get the penv directory to locate uv within it
|
# Get the penv directory to locate uv within it
|
||||||
penv_dir = os.path.dirname(os.path.dirname(python_exe))
|
penv_dir = os.path.dirname(os.path.dirname(python_exe))
|
||||||
penv_uv_executable = get_executable_path(penv_dir, "uv")
|
penv_uv_executable = get_executable_path(penv_dir, "uv")
|
||||||
|
|
||||||
|
# Build subprocess environment with UV_CACHE_DIR if specified
|
||||||
|
uv_env = None
|
||||||
|
if uv_cache_dir:
|
||||||
|
uv_env = dict(os.environ)
|
||||||
|
uv_env["UV_CACHE_DIR"] = str(uv_cache_dir)
|
||||||
|
|
||||||
# Check if uv is available in the penv
|
# Check if uv is available in the penv
|
||||||
uv_in_penv_available = False
|
uv_in_penv_available = False
|
||||||
@@ -250,28 +257,21 @@ def install_python_deps(python_exe, external_uv_executable):
|
|||||||
# Install uv into penv if not available
|
# Install uv into penv if not available
|
||||||
if not uv_in_penv_available:
|
if not uv_in_penv_available:
|
||||||
if external_uv_executable:
|
if external_uv_executable:
|
||||||
# Use external uv to install uv into the penv
|
# Try external uv first to install uv into the penv
|
||||||
try:
|
try:
|
||||||
subprocess.check_call(
|
subprocess.check_call(
|
||||||
[external_uv_executable, "pip", "install", "uv>=0.1.0", f"--python={python_exe}", "--quiet"],
|
[external_uv_executable, "pip", "install", "uv>=0.1.0", f"--python={python_exe}", "--quiet"],
|
||||||
stdout=subprocess.DEVNULL,
|
stdout=subprocess.DEVNULL,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
timeout=300
|
timeout=300,
|
||||||
|
env=uv_env
|
||||||
)
|
)
|
||||||
except subprocess.CalledProcessError as e:
|
uv_in_penv_available = True
|
||||||
print(f"Error: uv installation failed with exit code {e.returncode}")
|
except Exception:
|
||||||
return False
|
print("Warning: uv installation via external uv failed, falling back to pip")
|
||||||
except subprocess.TimeoutExpired:
|
|
||||||
print("Error: uv installation timed out")
|
if not uv_in_penv_available:
|
||||||
return False
|
# Fallback to pip to install uv into penv
|
||||||
except FileNotFoundError:
|
|
||||||
print("Error: External uv executable not found")
|
|
||||||
return False
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error installing uv package manager into penv: {e}")
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
# No external uv available, use pip to install uv into penv
|
|
||||||
try:
|
try:
|
||||||
subprocess.check_call(
|
subprocess.check_call(
|
||||||
[python_exe, "-m", "pip", "install", "uv>=0.1.0", "--quiet"],
|
[python_exe, "-m", "pip", "install", "uv>=0.1.0", "--quiet"],
|
||||||
@@ -308,7 +308,8 @@ def install_python_deps(python_exe, external_uv_executable):
|
|||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
encoding='utf-8',
|
encoding='utf-8',
|
||||||
timeout=300
|
timeout=300,
|
||||||
|
env=uv_env
|
||||||
)
|
)
|
||||||
|
|
||||||
if result_obj.returncode == 0:
|
if result_obj.returncode == 0:
|
||||||
@@ -356,7 +357,8 @@ def install_python_deps(python_exe, external_uv_executable):
|
|||||||
cmd,
|
cmd,
|
||||||
stdout=subprocess.DEVNULL,
|
stdout=subprocess.DEVNULL,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
timeout=300
|
timeout=300,
|
||||||
|
env=uv_env
|
||||||
)
|
)
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
@@ -375,7 +377,7 @@ def install_python_deps(python_exe, external_uv_executable):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def install_esptool(env, platform, python_exe, uv_executable):
|
def install_esptool(env, platform, python_exe, uv_executable, uv_cache_dir=None):
|
||||||
"""
|
"""
|
||||||
Install esptool from package folder "tool-esptoolpy" using uv package manager.
|
Install esptool from package folder "tool-esptoolpy" using uv package manager.
|
||||||
Ensures esptool is installed from the specific tool-esptoolpy package directory.
|
Ensures esptool is installed from the specific tool-esptoolpy package directory.
|
||||||
@@ -385,6 +387,7 @@ def install_esptool(env, platform, python_exe, uv_executable):
|
|||||||
platform: PlatformIO platform object
|
platform: PlatformIO platform object
|
||||||
python_exe (str): Path to Python executable in virtual environment
|
python_exe (str): Path to Python executable in virtual environment
|
||||||
uv_executable (str): Path to uv executable
|
uv_executable (str): Path to uv executable
|
||||||
|
uv_cache_dir: Optional path to uv cache directory
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
SystemExit: If esptool installation fails or package directory not found
|
SystemExit: If esptool installation fails or package directory not found
|
||||||
@@ -396,6 +399,12 @@ def install_esptool(env, platform, python_exe, uv_executable):
|
|||||||
)
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Build subprocess environment with UV_CACHE_DIR if specified
|
||||||
|
uv_env = None
|
||||||
|
if uv_cache_dir:
|
||||||
|
uv_env = dict(os.environ)
|
||||||
|
uv_env["UV_CACHE_DIR"] = str(uv_cache_dir)
|
||||||
|
|
||||||
# Check if esptool is already installed from the correct path
|
# Check if esptool is already installed from the correct path
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
@@ -427,7 +436,7 @@ def install_esptool(env, platform, python_exe, uv_executable):
|
|||||||
uv_executable, "pip", "install", "--quiet", "--force-reinstall",
|
uv_executable, "pip", "install", "--quiet", "--force-reinstall",
|
||||||
f"--python={python_exe}",
|
f"--python={python_exe}",
|
||||||
"-e", esptool_repo_path
|
"-e", esptool_repo_path
|
||||||
], timeout=60)
|
], timeout=60, env=uv_env)
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
@@ -468,6 +477,9 @@ def _setup_python_environment_core(env, platform, platformio_dir, should_install
|
|||||||
tuple[str, str]: (Path to penv Python executable, Path to esptool script)
|
tuple[str, str]: (Path to penv Python executable, Path to esptool script)
|
||||||
"""
|
"""
|
||||||
penv_dir = str(Path(platformio_dir) / "penv")
|
penv_dir = str(Path(platformio_dir) / "penv")
|
||||||
|
|
||||||
|
# Determine uv cache directory inside .platformio/.cache
|
||||||
|
uv_cache_dir = str(Path(platformio_dir) / ".cache" / "uv")
|
||||||
|
|
||||||
# Create virtual environment if not present
|
# Create virtual environment if not present
|
||||||
if env is not None:
|
if env is not None:
|
||||||
@@ -498,7 +510,7 @@ def _setup_python_environment_core(env, platform, platformio_dir, should_install
|
|||||||
|
|
||||||
# Install required Python dependencies for ESP32 platform
|
# Install required Python dependencies for ESP32 platform
|
||||||
if has_internet_connection() or github_actions:
|
if has_internet_connection() or github_actions:
|
||||||
if not install_python_deps(penv_python, used_uv_executable):
|
if not install_python_deps(penv_python, used_uv_executable, uv_cache_dir):
|
||||||
sys.stderr.write("Error: Failed to install Python dependencies into penv\n")
|
sys.stderr.write("Error: Failed to install Python dependencies into penv\n")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
@@ -508,10 +520,10 @@ def _setup_python_environment_core(env, platform, platformio_dir, should_install
|
|||||||
if should_install_esptool:
|
if should_install_esptool:
|
||||||
if env is not None:
|
if env is not None:
|
||||||
# SCons version
|
# SCons version
|
||||||
install_esptool(env, platform, penv_python, uv_executable)
|
install_esptool(env, platform, penv_python, uv_executable, uv_cache_dir)
|
||||||
else:
|
else:
|
||||||
# Minimal setup - install esptool from tool package
|
# Minimal setup - install esptool from tool package
|
||||||
_install_esptool_from_tl_install(platform, penv_python, uv_executable)
|
_install_esptool_from_tl_install(platform, penv_python, uv_executable, uv_cache_dir)
|
||||||
|
|
||||||
# Setup certifi environment variables
|
# Setup certifi environment variables
|
||||||
_setup_certifi_env(env, penv_python)
|
_setup_certifi_env(env, penv_python)
|
||||||
@@ -582,7 +594,7 @@ def _setup_pipenv_minimal(penv_dir):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _install_esptool_from_tl_install(platform, python_exe, uv_executable):
|
def _install_esptool_from_tl_install(platform, python_exe, uv_executable, uv_cache_dir=None):
|
||||||
"""
|
"""
|
||||||
Install esptool from tl-install provided path into penv.
|
Install esptool from tl-install provided path into penv.
|
||||||
|
|
||||||
@@ -590,6 +602,7 @@ def _install_esptool_from_tl_install(platform, python_exe, uv_executable):
|
|||||||
platform: PlatformIO platform object
|
platform: PlatformIO platform object
|
||||||
python_exe (str): Path to Python executable in virtual environment
|
python_exe (str): Path to Python executable in virtual environment
|
||||||
uv_executable (str): Path to uv executable
|
uv_executable (str): Path to uv executable
|
||||||
|
uv_cache_dir: Optional path to uv cache directory
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
SystemExit: If esptool installation fails or package directory not found
|
SystemExit: If esptool installation fails or package directory not found
|
||||||
@@ -599,6 +612,12 @@ def _install_esptool_from_tl_install(platform, python_exe, uv_executable):
|
|||||||
if not esptool_repo_path or not os.path.isdir(esptool_repo_path):
|
if not esptool_repo_path or not os.path.isdir(esptool_repo_path):
|
||||||
return (None, None)
|
return (None, None)
|
||||||
|
|
||||||
|
# Build subprocess environment with UV_CACHE_DIR if specified
|
||||||
|
uv_env = None
|
||||||
|
if uv_cache_dir:
|
||||||
|
uv_env = dict(os.environ)
|
||||||
|
uv_env["UV_CACHE_DIR"] = str(uv_cache_dir)
|
||||||
|
|
||||||
# Check if esptool is already installed from the correct path
|
# Check if esptool is already installed from the correct path
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
@@ -630,7 +649,7 @@ def _install_esptool_from_tl_install(platform, python_exe, uv_executable):
|
|||||||
uv_executable, "pip", "install", "--quiet", "--force-reinstall",
|
uv_executable, "pip", "install", "--quiet", "--force-reinstall",
|
||||||
f"--python={python_exe}",
|
f"--python={python_exe}",
|
||||||
"-e", esptool_repo_path
|
"-e", esptool_repo_path
|
||||||
], timeout=60)
|
], timeout=60, env=uv_env)
|
||||||
print(f"Installed esptool from tl-install path: {esptool_repo_path}")
|
print(f"Installed esptool from tl-install path: {esptool_repo_path}")
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ build_flags =
|
|||||||
[env:esp32-p4]
|
[env:esp32-p4]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
framework = espidf
|
framework = espidf
|
||||||
board = esp32-p4
|
board = esp32-p4_r3
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
build_flags =
|
build_flags =
|
||||||
-D CONFIG_BLINK_GPIO=2
|
-D CONFIG_BLINK_GPIO=2
|
||||||
|
|||||||
@@ -15,4 +15,4 @@ board = esp32-c6-devkitc-1
|
|||||||
[env:esp32-p4]
|
[env:esp32-p4]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
framework = espidf
|
framework = espidf
|
||||||
board = esp32-p4
|
board = esp32-p4_r3
|
||||||
|
|||||||
+8
-8
@@ -18,7 +18,7 @@
|
|||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/pioarduino/platform-espressif32.git"
|
"url": "https://github.com/pioarduino/platform-espressif32.git"
|
||||||
},
|
},
|
||||||
"version": "55.03.36",
|
"version": "55.03.37",
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"arduino": {
|
"arduino": {
|
||||||
"script": "builder/frameworks/arduino.py"
|
"script": "builder/frameworks/arduino.py"
|
||||||
@@ -33,31 +33,31 @@
|
|||||||
"type": "framework",
|
"type": "framework",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"owner": "espressif",
|
"owner": "espressif",
|
||||||
"version": "https://github.com/espressif/arduino-esp32/releases/download/3.3.6/esp32-core-3.3.6.tar.xz"
|
"version": "https://github.com/espressif/arduino-esp32/releases/download/3.3.7/esp32-core-3.3.7.tar.xz"
|
||||||
},
|
},
|
||||||
"framework-arduinoespressif32-libs": {
|
"framework-arduinoespressif32-libs": {
|
||||||
"type": "framework",
|
"type": "framework",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"owner": "espressif",
|
"owner": "espressif",
|
||||||
"version": "https://github.com/espressif/arduino-esp32/releases/download/3.3.6/esp32-core-3.3.6-libs.tar.xz"
|
"version": "https://github.com/espressif/arduino-esp32/releases/download/3.3.7/esp32-core-3.3.7-libs.tar.xz"
|
||||||
},
|
},
|
||||||
"framework-arduino-c2-skeleton-lib": {
|
"framework-arduino-c2-skeleton-lib": {
|
||||||
"type": "framework",
|
"type": "framework",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"owner": "espressif",
|
"owner": "espressif",
|
||||||
"version": "https://github.com/pioarduino/platform-espressif32/releases/download/c2-skeleton/c2_366dadf354_compile_skeleton.zip"
|
"version": "https://github.com/pioarduino/platform-espressif32/releases/download/c2-skeleton/c2_87912cd291_compile_skeleton.zip"
|
||||||
},
|
},
|
||||||
"framework-arduino-c61-skeleton-lib": {
|
"framework-arduino-c61-skeleton-lib": {
|
||||||
"type": "framework",
|
"type": "framework",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"owner": "espressif",
|
"owner": "espressif",
|
||||||
"version": "https://github.com/pioarduino/platform-espressif32/releases/download/c61-skeleton/c61_366dadf354_compile_skeleton.zip"
|
"version": "https://github.com/pioarduino/platform-espressif32/releases/download/c61-skeleton/c61_87912cd291_compile_skeleton.zip"
|
||||||
},
|
},
|
||||||
"framework-espidf": {
|
"framework-espidf": {
|
||||||
"type": "framework",
|
"type": "framework",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"owner": "pioarduino",
|
"owner": "pioarduino",
|
||||||
"version": "https://github.com/pioarduino/esp-idf/releases/download/v5.5.2.260116/esp-idf-v5.5.2.tar.xz"
|
"version": "https://github.com/pioarduino/esp-idf/releases/download/v5.5.2.260206/esp-idf-v5.5.2.tar.xz"
|
||||||
},
|
},
|
||||||
"toolchain-xtensa-esp-elf": {
|
"toolchain-xtensa-esp-elf": {
|
||||||
"type": "toolchain",
|
"type": "toolchain",
|
||||||
@@ -98,8 +98,8 @@
|
|||||||
"type": "uploader",
|
"type": "uploader",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"owner": "pioarduino",
|
"owner": "pioarduino",
|
||||||
"package-version": "5.1.0",
|
"package-version": "5.1.2",
|
||||||
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/esptoolpy-v5.1.0.zip"
|
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/esptoolpy-v5.1.2.zip"
|
||||||
},
|
},
|
||||||
"tool-esp_install": {
|
"tool-esp_install": {
|
||||||
"type": "tool",
|
"type": "tool",
|
||||||
|
|||||||
+12
-5
@@ -14,11 +14,19 @@
|
|||||||
|
|
||||||
# Python Version Check
|
# Python Version Check
|
||||||
import sys
|
import sys
|
||||||
|
from platformio.compat import IS_WINDOWS
|
||||||
|
|
||||||
if not ((3, 10) <= sys.version_info < (3, 14)):
|
pyver = sys.version_info
|
||||||
print("ERROR: Python version must be between 3.10 and 3.13.", file=sys.stderr)
|
if IS_WINDOWS:
|
||||||
print(f"Current Python version: {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}", file=sys.stderr)
|
allowed = (3, 10) <= pyver < (3, 14)
|
||||||
print("Supported versions: 3.10, 3.11, 3.12, 3.13", file=sys.stderr)
|
supported = "3.10, 3.11, 3.12, 3.13"
|
||||||
|
else:
|
||||||
|
allowed = (3, 10) <= pyver < (3, 15)
|
||||||
|
supported = "3.10, 3.11, 3.12, 3.13, 3.14"
|
||||||
|
if not allowed:
|
||||||
|
print(f"ERROR: Python version must be {supported}.", file=sys.stderr)
|
||||||
|
print(f"Current Python version: {pyver.major}.{pyver.minor}.{pyver.micro}", file=sys.stderr)
|
||||||
|
print(f"Supported versions: {supported}", file=sys.stderr)
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
|
|
||||||
# LZMA support check
|
# LZMA support check
|
||||||
@@ -44,7 +52,6 @@ import subprocess
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Dict, List, Any, Union
|
from typing import Optional, Dict, List, Any, Union
|
||||||
|
|
||||||
from platformio.compat import IS_WINDOWS
|
|
||||||
from platformio.public import PlatformBase, to_unix_path
|
from platformio.public import PlatformBase, to_unix_path
|
||||||
from platformio.proc import get_pythonexe_path
|
from platformio.proc import get_pythonexe_path
|
||||||
from platformio.project.config import ProjectConfig
|
from platformio.project.config import ProjectConfig
|
||||||
|
|||||||
Reference in New Issue
Block a user