feat: prove build, flashing, and stable basic operation

This commit is contained in:
2026-08-27 23:33:17 +03:00
parent 0d921a83a0
commit c1fb19af53
5 changed files with 164 additions and 5 deletions
+2 -1
View File
@@ -1,3 +1,4 @@
.obsidian
sdkconfig.esp32-c6-devkitm-1
.pio/build
.pio
.vscode
+12 -2
View File
@@ -114,7 +114,7 @@ If all criteria pass, set this milestone to `DONE`, append its execution record,
## Milestone 001 — Prove build, flashing, and stable basic operation
**Status:** `IN PROGRESS`
**Status:** `DONE`
**Depends on:** Milestone 000
### Objective
@@ -153,11 +153,21 @@ Prove that the configuration selected in Milestone 000 works reliably on the phy
If all criteria pass, set this milestone to `DONE`, append its execution record, and change Milestone 002 from `BLOCKED` to `READY`.
Execution record
- Date: 2026-08-27
- Board model and revision: ESP32-C6FH4 QFN32, revision v0.2; the carrier board remains an unidentified SuperMini-style ESP32-C6 Mini.
- Toolchain and library versions: PlatformIO Core 6.1.19; `espressif32` 7.0.1; ESP-IDF 6.0.1; esptool.py 4.11.0; RISC-V toolchain 15.2.0+20251204.
- Result: PASS
- Evidence: `src/main.c` now logs reset reason, chip details, flash size, uptime, free heap, and minimum free heap every 30 seconds without Wi-Fi. `platformio.ini`, `sdkconfig.esp32-c6-devkitm-1`, and `partitions.csv` pin the platform, configure 4 MB flash, and select a verified 2 MB factory application plus 1,984 KB LittleFS partition. Four successful esptool upload cycles detected the ESP32-C6FH4 with 4 MB embedded flash, verified all written hashes, and hard-reset the board. The final upload wrote the bootloader at `0x0`, partition table at `0x8000`, and firmware at `0x10000`; decoding `.pio/build/esp32-c6-devkitm-1/partitions.bin` confirmed the configured NVS, PHY, factory, and LittleFS partitions. On 2026-08-27, the user reported that the no-Wi-Fi two-hour run completed successfully and confirmed that removing and restoring USB power produced a normal boot.
- Measurements: Final clean build: RAM 11,116 / 327,680 bytes (3.4%); firmware 161,288 / 2,097,152 bytes (7.7%). Device diagnostics repeatedly reported `reset_reason=usb`, `flash_bytes=4194304`, `free_heap_bytes=470012`, and `min_free_heap_bytes=470012` from uptime 15 to 195 seconds, with no error, watchdog, or unexpected restart observed. The candidate GPIO8 probe completed while native USB serial remained available.
- Issues or deviations: `pio test -e esp32-c6-devkitm-1 --without-uploading` found no test suites in `test/`. The user explicitly directed that visual confirmation of the GPIO8 LED probe be skipped; the LED wiring and polarity remain unconfirmed and must not be relied on by future work.
- Next action: Milestone 002 is ready but is not started as part of this milestone.
---
## Milestone 002 — Prove the Wi-Fi, LittleFS, and HTTP vertical slice
**Status:** `BLOCKED`
**Status:** `READY`
**Depends on:** Milestone 001
### Objective
+5
View File
@@ -0,0 +1,5 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 0x200000,
littlefs, data, littlefs,0x210000, 0x1f0000,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x6000
3 phy_init data phy 0xf000 0x1000
4 factory app factory 0x10000 0x200000
5 littlefs data littlefs 0x210000 0x1f0000
+4 -1
View File
@@ -9,6 +9,9 @@
; https://docs.platformio.org/page/projectconf.html
[env:esp32-c6-devkitm-1]
platform = espressif32
platform = espressif32 @ 7.0.1
board = esp32-c6-devkitm-1
framework = espidf
board_build.partitions = partitions.csv
monitor_port = /dev/ttyACM0
monitor_speed = 115200
+141 -1
View File
@@ -1 +1,141 @@
void app_main() {}
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include "driver/gpio.h"
#include "esp_chip_info.h"
#include "esp_err.h"
#include "esp_flash.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
static const char *const kLogTag = "bringup";
static const gpio_num_t kCandidateLedGpio = GPIO_NUM_8;
static const uint32_t kLedProbeCount = 10;
static const uint32_t kLedProbeIntervalMs = 500;
static const uint32_t kHealthIntervalMs = 30000;
static const uint32_t kStartupAttachmentDelayMs = 10000;
static const char *reset_reason_name(esp_reset_reason_t reason) {
switch (reason) {
case ESP_RST_UNKNOWN:
return "unknown";
case ESP_RST_POWERON:
return "power_on";
case ESP_RST_EXT:
return "external";
case ESP_RST_SW:
return "software";
case ESP_RST_PANIC:
return "panic";
case ESP_RST_INT_WDT:
return "interrupt_watchdog";
case ESP_RST_TASK_WDT:
return "task_watchdog";
case ESP_RST_WDT:
return "other_watchdog";
case ESP_RST_DEEPSLEEP:
return "deep_sleep";
case ESP_RST_BROWNOUT:
return "brownout";
case ESP_RST_SDIO:
return "sdio";
case ESP_RST_USB:
return "usb";
case ESP_RST_JTAG:
return "jtag";
case ESP_RST_EFUSE:
return "efuse";
case ESP_RST_PWR_GLITCH:
return "power_glitch";
case ESP_RST_CPU_LOCKUP:
return "cpu_lockup";
}
return "unrecognized";
}
static void log_heap(uint64_t uptime_ms) {
const size_t free_heap_bytes = esp_get_free_heap_size();
const size_t minimum_free_heap_bytes = esp_get_minimum_free_heap_size();
uint32_t flash_size_bytes = 0;
const esp_err_t flash_result = esp_flash_get_size(NULL, &flash_size_bytes);
if (flash_result == ESP_OK) {
ESP_LOGI(kLogTag,
"health uptime_ms=%" PRIu64 " reset_reason=%s flash_bytes=%" PRIu32
" free_heap_bytes=%u min_free_heap_bytes=%u",
uptime_ms,
reset_reason_name(esp_reset_reason()),
flash_size_bytes,
(unsigned int)free_heap_bytes,
(unsigned int)minimum_free_heap_bytes);
} else {
ESP_LOGE(kLogTag, "health flash_size_failed=%s", esp_err_to_name(flash_result));
}
}
static void probe_candidate_led(void) {
ESP_LOGI(kLogTag,
"led_probe gpio=%d transitions=%" PRIu32 " interval_ms=%" PRIu32 "; visually confirm the LED",
(int)kCandidateLedGpio,
kLedProbeCount,
kLedProbeIntervalMs);
esp_err_t result = gpio_reset_pin(kCandidateLedGpio);
if (result != ESP_OK) {
ESP_LOGW(kLogTag, "led_probe gpio_reset_pin failed: %s", esp_err_to_name(result));
return;
}
result = gpio_set_direction(kCandidateLedGpio, GPIO_MODE_OUTPUT);
if (result != ESP_OK) {
ESP_LOGW(kLogTag, "led_probe gpio_set_direction failed: %s", esp_err_to_name(result));
return;
}
for (uint32_t transition = 0; transition < kLedProbeCount; ++transition) {
gpio_set_level(kCandidateLedGpio, transition % 2U);
vTaskDelay(pdMS_TO_TICKS(kLedProbeIntervalMs));
}
gpio_set_level(kCandidateLedGpio, 0);
ESP_LOGI(kLogTag, "led_probe complete; USB serial remained available during probe");
}
static void log_startup(void) {
esp_chip_info_t chip_info = {0};
uint32_t flash_size_bytes = 0;
const esp_err_t flash_result = esp_flash_get_size(NULL, &flash_size_bytes);
esp_chip_info(&chip_info);
ESP_LOGI(kLogTag,
"startup reset_reason=%s chip_model=%d chip_revision=%d cores=%d features=0x%08" PRIx32,
reset_reason_name(esp_reset_reason()),
(int)chip_info.model,
chip_info.revision,
chip_info.cores,
chip_info.features);
if (flash_result == ESP_OK) {
ESP_LOGI(kLogTag, "startup flash_bytes=%" PRIu32, flash_size_bytes);
} else {
ESP_LOGE(kLogTag, "startup flash_size_failed=%s", esp_err_to_name(flash_result));
}
log_heap(0);
}
void app_main(void) {
vTaskDelay(pdMS_TO_TICKS(kStartupAttachmentDelayMs));
log_startup();
probe_candidate_led();
while (true) {
log_heap((uint64_t)(esp_timer_get_time() / 1000));
vTaskDelay(pdMS_TO_TICKS(kHealthIntervalMs));
}
}