diff --git a/components/wifi_cfg/CMakeLists.txt b/components/wifi_cfg/CMakeLists.txt new file mode 100644 index 0000000..504f7be --- /dev/null +++ b/components/wifi_cfg/CMakeLists.txt @@ -0,0 +1,11 @@ +idf_component_register( + SRCS "wifi_cfg.c" + INCLUDE_DIRS "." + REQUIRES + esp_wifi + esp_netif + nvs_flash + esp_event + driver + esp_driver_usb_serial_jtag +) diff --git a/components/wifi_cfg/tmp.txt b/components/wifi_cfg/tmp.txt new file mode 100644 index 0000000..e24165e --- /dev/null +++ b/components/wifi_cfg/tmp.txt @@ -0,0 +1,313 @@ +// wifi_cfg_dualmode.c — ESP-IDF v5.3.x +// Listens for CFG/END Wi‑Fi config on BOTH UART(console/COM) and USB‑Serial/JTAG concurrently. +// - UART path uses stdio (fgets on stdin) — works with /dev/ttyUSB* +// - USB path uses driver API (usb_serial_jtag_read_bytes / write_bytes) — works with /dev/ttyACM* +// - Tolerates ESP_ERR_INVALID_STATE on repeated inits +// - Supports DHCP or static IP, persists to NVS, applies immediately + +#include +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "nvs.h" +#include "esp_netif.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_check.h" +#include "esp_event.h" +#include "driver/usb_serial_jtag.h" // direct read/write API (no VFS remap) +#include "wifi_cfg.h" + + +// wifi_cfg.c + +static const char *TAG = "wifi_cfg"; + +static esp_netif_t *sta_netif = NULL; +static bool cfg_dhcp = true; + +static void trim(char *s){ + int n = strlen(s); + while(n>0 && (s[n-1]=='\r' || s[n-1]=='\n' || isspace((unsigned char)s[n-1]))) s[--n]=0; + while(*s && isspace((unsigned char)*s)){ + memmove(s, s+1, strlen(s)); + } +} + +static esp_err_t nvs_set_str2(nvs_handle_t h, const char *key, const char *val){ + return val ? nvs_set_str(h, key, val) : nvs_erase_key(h, key); +} + +static void save_cfg(const char* ssid, const char* pass, const char* ip, const char* mask, const char* gw, bool dhcp){ + nvs_handle_t h; + if (nvs_open("netcfg", NVS_READWRITE, &h) != ESP_OK) return; + if (ssid) nvs_set_str2(h, "ssid", ssid); + if (pass) nvs_set_str2(h, "pass", pass); + if (ip) nvs_set_str2(h, "ip", ip); + if (mask) nvs_set_str2(h, "mask", mask); + if (gw) nvs_set_str2(h, "gw", gw); + nvs_set_u8(h, "dhcp", dhcp ? 1 : 0); + nvs_commit(h); + nvs_close(h); + cfg_dhcp = dhcp; +} + +static bool load_cfg(char* ssid, size_t ssz, char* pass, size_t psz, + char* ip, size_t isz, char* mask, size_t msz, char* gw, size_t gsz, bool* dhcp){ + nvs_handle_t h; + if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) return false; + size_t len; + esp_err_t e; + if ((e = nvs_get_str(h, "ssid", NULL, &len)) != ESP_OK){ nvs_close(h); return false; } + if (len >= ssz){ nvs_close(h); return false; } + nvs_get_str(h, "ssid", ssid, &len); + len = psz; e = nvs_get_str(h, "pass", pass, &len); if (e!=ESP_OK) pass[0]=0; + len = isz; e = nvs_get_str(h, "ip", ip, &len); if (e!=ESP_OK) ip[0]=0; + len = msz; e = nvs_get_str(h, "mask", mask, &len); if (e!=ESP_OK) mask[0]=0; + len = gsz; e = nvs_get_str(h, "gw", gw, &len); if (e!=ESP_OK) gw[0]=0; + uint8_t d=1; nvs_get_u8(h, "dhcp", &d); *dhcp = (d!=0); + nvs_close(h); + return true; +} + +void wifi_cfg_force_dhcp(bool enable){ cfg_dhcp = enable; } + + +/* --- One-time net stack bring-up (thread-safe) --- */ +static atomic_bool s_net_stack_ready = false; + +static esp_err_t ensure_net_stack_once(void) +{ + bool expected = false; + if (atomic_compare_exchange_strong(&s_net_stack_ready, &expected, true)) { + ESP_RETURN_ON_ERROR(esp_netif_init(), TAG, "esp_netif_init"); + esp_err_t err = esp_event_loop_create_default(); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + ESP_RETURN_ON_ERROR(err, TAG, "event loop create"); + } + } + return ESP_OK; +} + +/* --- One-time Wi-Fi driver init (thread-safe, idempotent) --- */ +static atomic_bool s_wifi_inited = false; + +esp_err_t wifi_ensure_inited(void) +{ + bool expected = false; + if (!atomic_compare_exchange_strong(&s_wifi_inited, &expected, true)) { + // someone else already initialized (or is initializing and finished) + return ESP_OK; + } + + ESP_RETURN_ON_ERROR(ensure_net_stack_once(), TAG, "net stack"); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + esp_err_t err = esp_wifi_init(&cfg); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + // roll back the flag so a later attempt can retry + atomic_store(&s_wifi_inited, false); + ESP_RETURN_ON_ERROR(err, TAG, "esp_wifi_init"); + } + + // Optional: set default interface and mode now or let caller do it + // ESP_RETURN_ON_ERROR(esp_wifi_set_mode(WIFI_MODE_STA), TAG, "set mode"); + + return ESP_OK; +} + + +static void apply_ip_static(const char* ip, const char* mask, const char* gw){ + if (!sta_netif) return; + esp_netif_ip_info_t info = {0}; + esp_netif_dhcpc_stop(sta_netif); + info.ip.addr = esp_ip4addr_aton(ip); + info.netmask.addr = esp_ip4addr_aton(mask); + info.gw.addr = esp_ip4addr_aton(gw); + ESP_ERROR_CHECK( esp_netif_set_ip_info(sta_netif, &info) ); +} + +bool wifi_cfg_apply_from_nvs(void){ + char ssid[64]={0}, pass[64]={0}, ip[32]={0}, mask[32]={0}, gw[32]={0}; + bool dhcp = true; + if (!load_cfg(ssid,sizeof(ssid), pass,sizeof(pass), ip,sizeof(ip), mask,sizeof(mask), gw,sizeof(gw), &dhcp)){ + ESP_LOGW(TAG, "No Wi‑Fi config in NVS"); + return false; + } + ESP_LOGI(TAG, "Applying Wi‑Fi config: SSID=%s DHCP=%d IP=%s", ssid, dhcp, ip); + + static bool inited = false; + if (!inited){ + // NVS (with recovery) + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + nvs_flash_erase(); + err = nvs_flash_init(); + } + if (err != ESP_OK) { ESP_ERROR_CHECK(err); } + + // Netif + default event loop (tolerate already-initialized state) + do{ esp_err_t __e = esp_netif_init(); if(__e!=ESP_OK && __e!=ESP_ERR_INVALID_STATE){ ESP_ERROR_CHECK(__e);} }while(0); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { ESP_ERROR_CHECK(err); } + + do{ esp_err_t __e = esp_event_loop_create_default(); if(__e!=ESP_OK && __e!=ESP_ERR_INVALID_STATE){ ESP_ERROR_CHECK(__e);} }while(0); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { ESP_ERROR_CHECK(err); } + + if (sta_netif == NULL) { + sta_netif = esp_netif_create_default_wifi_sta(); + } + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(err=wifi_ensure_inited()); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { ESP_ERROR_CHECK(err); } + + inited = true; + } + + wifi_config_t wcfg = (wifi_config_t){0}; + strncpy((char*)wcfg.sta.ssid, ssid, sizeof(wcfg.sta.ssid)-1); + strncpy((char*)wcfg.sta.password, pass, sizeof(wcfg.sta.password)-1); + wcfg.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; + wcfg.sta.sae_pwe_h2e = WPA3_SAE_PWE_BOTH; + + ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wcfg) ); + + if (!dhcp && ip[0] && mask[0] && gw[0]){ + apply_ip_static(ip, mask, gw); + } else { + if (sta_netif) esp_netif_dhcpc_start(sta_netif); + } + + esp_err_t err2 = esp_wifi_start(); + if (err2 != ESP_OK && err2 != ESP_ERR_INVALID_STATE) { ESP_ERROR_CHECK(err2); } + err2 = esp_wifi_connect(); + if (err2 != ESP_OK && err2 != ESP_ERR_WIFI_NOT_INIT && err2 != ESP_ERR_INVALID_STATE) { ESP_ERROR_CHECK(err2); } + return true; +} + +// -------------------- Dual input paths -------------------- + +typedef struct { + // emit() should write a short line back to the same channel (optional) + void (*emit)(const char *s, void *ctx); + void *ctx; + // fetch_line() should fill buf with a single line (without trailing CR/LF) and return true if a line was read + bool (*fetch_line)(char *buf, size_t sz, void *ctx); +} cfg_io_t; + +static void on_cfg_line(const char *line, char *ssid, char *pass, char *ip, char *mask, char *gw, bool *dhcp){ + if (strncmp(line, "SSID:",5)==0){ strncpy(ssid, line+5, 63); ssid[63]=0; return; } + if (strncmp(line, "PASS:",5)==0){ strncpy(pass, line+5, 63); pass[63]=0; return; } + if (strncmp(line, "IP:",3)==0){ strncpy(ip, line+3, 31); ip[31]=0; return; } + if (strncmp(line, "MASK:",5)==0){ strncpy(mask, line+5, 31); mask[31]=0; return; } + if (strncmp(line, "GW:",3)==0){ strncpy(gw, line+3, 31); gw[31]=0; return; } + if (strncmp(line, "DHCP:",5)==0){ *dhcp = atoi(line+5) ? true:false; return; } +} + +static void cfg_worker(const cfg_io_t *io){ + char line[160]; + char ssid[64]={0}, pass[64]={0}, ip[32]={0}, mask[32]={0}, gw[32]={0}; + bool dhcp = true; + bool in_cfg = false; + + for(;;){ + if (!io->fetch_line(line, sizeof(line), io->ctx)){ + vTaskDelay(pdMS_TO_TICKS(20)); + continue; + } + trim(line); + if (!in_cfg){ + if (strcmp(line, "CFG")==0){ + in_cfg = true; + ssid[0]=pass[0]=ip[0]=mask[0]=gw[0]=0; + dhcp = true; + } + continue; + } + if (strcmp(line, "END")==0){ + save_cfg(ssid, pass, ip, mask, gw, dhcp); + if (io->emit) io->emit("OK\n", io->ctx); + wifi_cfg_apply_from_nvs(); + in_cfg = false; + continue; + } + on_cfg_line(line, ssid, pass, ip, mask, gw, &dhcp); + } +} + +// ---- UART(stdin) path ---- +static bool uart_fetch_line(char *buf, size_t sz, void *ctx){ + (void)ctx; + if (!fgets(buf, sz, stdin)) return false; + return true; +} +static void uart_emit(const char *s, void *ctx){ + (void)ctx; + fputs(s, stdout); + fflush(stdout); +} +static void cfg_listener_uart_task(void *arg){ + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + cfg_io_t io = {.emit = uart_emit, .ctx = NULL, .fetch_line = uart_fetch_line}; + cfg_worker(&io); +} + +// ---- USB-Serial/JTAG path ---- +typedef struct { int dummy; } usb_ctx_t; +static bool usb_fetch_line(char *buf, size_t sz, void *ctx){ + (void)ctx; + static char acc[256]; + static size_t acc_len = 0; + + uint8_t tmp[64]; + int n = usb_serial_jtag_read_bytes(tmp, sizeof(tmp), pdMS_TO_TICKS(10)); + if (n <= 0){ + return false; + } + for (int i=0; i +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "nvs.h" +#include "esp_netif.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_check.h" +#include "esp_event.h" +#include "driver/usb_serial_jtag.h" // direct read/write API (no VFS remap) +#include "wifi_cfg.h" + + +// wifi_cfg.c + +static const char *TAG = "wifi_cfg"; + +static esp_netif_t *sta_netif = NULL; +static bool cfg_dhcp = true; + +static void trim(char *s){ + int n = strlen(s); + while(n>0 && (s[n-1]=='\r' || s[n-1]=='\n' || isspace((unsigned char)s[n-1]))) s[--n]=0; + while(*s && isspace((unsigned char)*s)){ + memmove(s, s+1, strlen(s)); + } +} + +static esp_err_t nvs_set_str2(nvs_handle_t h, const char *key, const char *val){ + return val ? nvs_set_str(h, key, val) : nvs_erase_key(h, key); +} + +static void save_cfg(const char* ssid, const char* pass, const char* ip, const char* mask, const char* gw, bool dhcp){ + nvs_handle_t h; + if (nvs_open("netcfg", NVS_READWRITE, &h) != ESP_OK) return; + if (ssid) nvs_set_str2(h, "ssid", ssid); + if (pass) nvs_set_str2(h, "pass", pass); + if (ip) nvs_set_str2(h, "ip", ip); + if (mask) nvs_set_str2(h, "mask", mask); + if (gw) nvs_set_str2(h, "gw", gw); + nvs_set_u8(h, "dhcp", dhcp ? 1 : 0); + nvs_commit(h); + nvs_close(h); + cfg_dhcp = dhcp; +} + +static bool load_cfg(char* ssid, size_t ssz, char* pass, size_t psz, + char* ip, size_t isz, char* mask, size_t msz, char* gw, size_t gsz, bool* dhcp){ + nvs_handle_t h; + if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) return false; + size_t len; + esp_err_t e; + if ((e = nvs_get_str(h, "ssid", NULL, &len)) != ESP_OK){ nvs_close(h); return false; } + if (len >= ssz){ nvs_close(h); return false; } + nvs_get_str(h, "ssid", ssid, &len); + len = psz; e = nvs_get_str(h, "pass", pass, &len); if (e!=ESP_OK) pass[0]=0; + len = isz; e = nvs_get_str(h, "ip", ip, &len); if (e!=ESP_OK) ip[0]=0; + len = msz; e = nvs_get_str(h, "mask", mask, &len); if (e!=ESP_OK) mask[0]=0; + len = gsz; e = nvs_get_str(h, "gw", gw, &len); if (e!=ESP_OK) gw[0]=0; + uint8_t d=1; nvs_get_u8(h, "dhcp", &d); *dhcp = (d!=0); + nvs_close(h); + return true; +} + +void wifi_cfg_force_dhcp(bool enable){ cfg_dhcp = enable; } + + +/* --- One-time net stack bring-up (thread-safe) --- */ +static atomic_bool s_net_stack_ready = false; + +static esp_err_t ensure_net_stack_once(void) +{ + bool expected = false; + if (atomic_compare_exchange_strong(&s_net_stack_ready, &expected, true)) { + ESP_RETURN_ON_ERROR(esp_netif_init(), TAG, "esp_netif_init"); + esp_err_t err = esp_event_loop_create_default(); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + ESP_RETURN_ON_ERROR(err, TAG, "event loop create"); + } + } + return ESP_OK; +} + +/* --- One-time Wi-Fi driver init (thread-safe, idempotent) --- */ +static atomic_bool s_wifi_inited = false; + +esp_err_t wifi_ensure_inited(void) +{ + bool expected = false; + if (!atomic_compare_exchange_strong(&s_wifi_inited, &expected, true)) { + // someone else already initialized (or is initializing and finished) + return ESP_OK; + } + + ESP_RETURN_ON_ERROR(ensure_net_stack_once(), TAG, "net stack"); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + esp_err_t err = esp_wifi_init(&cfg); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + // roll back the flag so a later attempt can retry + atomic_store(&s_wifi_inited, false); + ESP_RETURN_ON_ERROR(err, TAG, "esp_wifi_init"); + } + + // Optional: set default interface and mode now or let caller do it + // ESP_RETURN_ON_ERROR(esp_wifi_set_mode(WIFI_MODE_STA), TAG, "set mode"); + + return ESP_OK; +} + + +static void apply_ip_static(const char* ip, const char* mask, const char* gw){ + if (!sta_netif) return; + esp_netif_ip_info_t info = {0}; + esp_netif_dhcpc_stop(sta_netif); + info.ip.addr = esp_ip4addr_aton(ip); + info.netmask.addr = esp_ip4addr_aton(mask); + info.gw.addr = esp_ip4addr_aton(gw); + ESP_ERROR_CHECK( esp_netif_set_ip_info(sta_netif, &info) ); +} + +bool wifi_cfg_apply_from_nvs(void){ + char ssid[64]={0}, pass[64]={0}, ip[32]={0}, mask[32]={0}, gw[32]={0}; + bool dhcp = true; + if (!load_cfg(ssid,sizeof(ssid), pass,sizeof(pass), ip,sizeof(ip), mask,sizeof(mask), gw,sizeof(gw), &dhcp)){ + ESP_LOGW(TAG, "No Wi‑Fi config in NVS"); + return false; + } + ESP_LOGI(TAG, "Applying Wi‑Fi config: SSID=%s DHCP=%d IP=%s", ssid, dhcp, ip); + + static bool inited = false; + if (!inited){ + // NVS (with recovery) + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + nvs_flash_erase(); + err = nvs_flash_init(); + } + if (err != ESP_OK) { ESP_ERROR_CHECK(err); } + + // Netif + default event loop (tolerate already-initialized state) + do{ esp_err_t __e = esp_netif_init(); if(__e!=ESP_OK && __e!=ESP_ERR_INVALID_STATE){ ESP_ERROR_CHECK(__e);} }while(0); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { ESP_ERROR_CHECK(err); } + + do{ esp_err_t __e = esp_event_loop_create_default(); if(__e!=ESP_OK && __e!=ESP_ERR_INVALID_STATE){ ESP_ERROR_CHECK(__e);} }while(0); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { ESP_ERROR_CHECK(err); } + + if (sta_netif == NULL) { + sta_netif = esp_netif_create_default_wifi_sta(); + } + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(err=wifi_ensure_inited()); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { ESP_ERROR_CHECK(err); } + + inited = true; + } + + wifi_config_t wcfg = (wifi_config_t){0}; + strncpy((char*)wcfg.sta.ssid, ssid, sizeof(wcfg.sta.ssid)-1); + strncpy((char*)wcfg.sta.password, pass, sizeof(wcfg.sta.password)-1); + wcfg.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; + wcfg.sta.sae_pwe_h2e = WPA3_SAE_PWE_BOTH; + + ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wcfg) ); + + if (!dhcp && ip[0] && mask[0] && gw[0]){ + apply_ip_static(ip, mask, gw); + } else { + if (sta_netif) esp_netif_dhcpc_start(sta_netif); + } + + esp_err_t err2 = esp_wifi_start(); + if (err2 != ESP_OK && err2 != ESP_ERR_INVALID_STATE) { ESP_ERROR_CHECK(err2); } + err2 = esp_wifi_connect(); + if (err2 != ESP_OK && err2 != ESP_ERR_WIFI_NOT_INIT && err2 != ESP_ERR_INVALID_STATE) { ESP_ERROR_CHECK(err2); } + return true; +} + +// -------------------- Dual input paths -------------------- + +typedef struct { + // emit() should write a short line back to the same channel (optional) + void (*emit)(const char *s, void *ctx); + void *ctx; + // fetch_line() should fill buf with a single line (without trailing CR/LF) and return true if a line was read + bool (*fetch_line)(char *buf, size_t sz, void *ctx); +} cfg_io_t; + +static void on_cfg_line(const char *line, char *ssid, char *pass, char *ip, char *mask, char *gw, bool *dhcp){ + if (strncmp(line, "SSID:",5)==0){ strncpy(ssid, line+5, 63); ssid[63]=0; return; } + if (strncmp(line, "PASS:",5)==0){ strncpy(pass, line+5, 63); pass[63]=0; return; } + if (strncmp(line, "IP:",3)==0){ strncpy(ip, line+3, 31); ip[31]=0; return; } + if (strncmp(line, "MASK:",5)==0){ strncpy(mask, line+5, 31); mask[31]=0; return; } + if (strncmp(line, "GW:",3)==0){ strncpy(gw, line+3, 31); gw[31]=0; return; } + if (strncmp(line, "DHCP:",5)==0){ *dhcp = atoi(line+5) ? true:false; return; } +} + +static void cfg_worker(const cfg_io_t *io){ + char line[160]; + char ssid[64]={0}, pass[64]={0}, ip[32]={0}, mask[32]={0}, gw[32]={0}; + bool dhcp = true; + bool in_cfg = false; + + for(;;){ + if (!io->fetch_line(line, sizeof(line), io->ctx)){ + vTaskDelay(pdMS_TO_TICKS(20)); + continue; + } + trim(line); + if (!in_cfg){ + if (strcmp(line, "CFG")==0){ + in_cfg = true; + ssid[0]=pass[0]=ip[0]=mask[0]=gw[0]=0; + dhcp = true; + } + continue; + } + if (strcmp(line, "END")==0){ + save_cfg(ssid, pass, ip, mask, gw, dhcp); + if (io->emit) io->emit("OK\n", io->ctx); + wifi_cfg_apply_from_nvs(); + in_cfg = false; + continue; + } + on_cfg_line(line, ssid, pass, ip, mask, gw, &dhcp); + } +} + +// ---- UART(stdin) path ---- +static bool uart_fetch_line(char *buf, size_t sz, void *ctx){ + (void)ctx; + if (!fgets(buf, sz, stdin)) return false; + return true; +} +static void uart_emit(const char *s, void *ctx){ + (void)ctx; + fputs(s, stdout); + fflush(stdout); +} +static void cfg_listener_uart_task(void *arg){ + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + cfg_io_t io = {.emit = uart_emit, .ctx = NULL, .fetch_line = uart_fetch_line}; + cfg_worker(&io); +} + +// ---- USB-Serial/JTAG path ---- +typedef struct { int dummy; } usb_ctx_t; +static bool usb_fetch_line(char *buf, size_t sz, void *ctx){ + (void)ctx; + static char acc[256]; + static size_t acc_len = 0; + + uint8_t tmp[64]; + int n = usb_serial_jtag_read_bytes(tmp, sizeof(tmp), pdMS_TO_TICKS(10)); + if (n <= 0){ + return false; + } + for (int i=0; i + +void wifi_cfg_init(void); // starts serial listener task +bool wifi_cfg_apply_from_nvs(void); // reads saved config and connects Wi‑Fi +void wifi_cfg_force_dhcp(bool enable); // for testing + +#ifdef __cplusplus +} +#endif diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 6a68988..4aa8685 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,3 +1,3 @@ -idf_component_register(SRCS "main.c" "iperf.c" "wifi_cfg.c" +idf_component_register(SRCS "main.c" INCLUDE_DIRS "." REQUIRES led_strip driver) diff --git a/main/main.c b/main/main.c index f121014..e01384c 100644 --- a/main/main.c +++ b/main/main.c @@ -22,8 +22,24 @@ static const char *TAG = "main"; -// WS2812 RGB LED - try both GPIO 38 and 48 -#define RGB_LED_GPIO 48 // If this doesn't work, try 38 +// RGB LED GPIO pin configuration +#if CONFIG_IDF_TARGET_ESP32S3 + // ESP32-S3-DevKitC-1 v1.0 uses GPIO48, v1.1 uses GPIO38 + // Default to GPIO48 for backward compatibility, but you may need GPIO38 + #define RGB_LED_GPIO 48 // Change to 38 if you have v1.1 board +#elif CONFIG_IDF_TARGET_ESP32C5 + #define RGB_LED_GPIO 27 +#elif CONFIG_IDF_TARGET_ESP32C6 + #define RGB_LED_GPIO 8 +#elif CONFIG_IDF_TARGET_ESP32C3 + #define RGB_LED_GPIO 8 +#elif CONFIG_IDF_TARGET_ESP32S2 + #define RGB_LED_GPIO 18 +#elif CONFIG_IDF_TARGET_ESP32 + #define RGB_LED_GPIO 2 +#else + #error "Unsupported target - define RGB_LED_GPIO for your board" +#endif static led_strip_handle_t led_strip;