zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.08k stars 6.19k forks source link

ESP32S3 WIFI AP mode with DHCP server #75423

Open Hugokie opened 5 days ago

Hugokie commented 5 days ago

Hello,

I try to set an ESP32 wifi AP mode with DHCP server.

Board : esp32-s3-devkitc-1-N32R8V Zephyr : v3.6.0 Build commannd : west build -p -b esp32s3_devkitm

I'm facing an issue about iface down when DHCP server send ICMP probe when getting a request.

[00:00:16.268,000] <wrn> net_if: iface 0x3fcaa730 is down
[00:00:16.269,000] <err> net_dhcpv4_server: Failed to send ICMP probe

I try to check up state with net_if_is_up() and carrier with net_if_is_carrier_ok() it's okay with that but the dormant flag seems to be always enable (I try net_if_dormant_off() witheout success). The full code below in function configNetAddr().

I don't if I miss something about the NET_REQUEST_WIFI_AP_ENABLE to allow interface to be ready or if there is a bug.

The full sample code:

#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/net/socket.h>
#include <zephyr/net/dhcpv4.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/wifi_mgmt.h>
#include <zephyr/net/dhcpv4_server.h>
#include <zephyr/net/net_ip.h>
#include <zephyr/net/net_core.h>
#include <zephyr/net/net_mgmt.h>

LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);

#define SSID "ESP32_Access_Point"
#define PASSPHRASE "your_password"
#define CHANNEL 6

static struct net_if_addr *ifaddr;
static struct net_if *wifi_iface;

static void wifi_ap_callback(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, struct net_if *iface)
{
    int ret = -1;

    LOG_INF("wifi_ap_callback");
    switch (mgmt_event) {
        case NET_EVENT_IPV4_ADDR_ADD:
            int ret = -1;
            struct in_addr startLease = { .s4_addr = {192, 168, 1, 10}};
            char buf[NET_IPV4_ADDR_LEN];

            LOG_INF("   Address[%d]: %s", net_if_get_by_iface(iface),
                    net_addr_ntop(AF_INET,
                    &iface->config.ip.ipv4->unicast[0].address.in_addr,
                    buf, sizeof(buf)));
            LOG_INF("    Subnet[%d]: %s", net_if_get_by_iface(iface),
                    net_addr_ntop(AF_INET,
                    &iface->config.ip.ipv4->netmask,
                    buf, sizeof(buf)));
            LOG_INF("    Router[%d]: %s", net_if_get_by_iface(iface),
                    net_addr_ntop(AF_INET,
                    &iface->config.ip.ipv4->gw,
                    buf, sizeof(buf)));

            // Set up DHCP server
            ret = net_dhcpv4_server_start(wifi_iface, &startLease);
            // net_dhcpv4_start(wifi_iface);
            if (ret < 0) {
                LOG_ERR("Failed to start DHCP server: %d", ret);
                return;
            }
            return;
        break;
    }

    LOG_INF("Wi-Fi connected");

    // Start HTTP server
    // start_http_server();
}

int configNetAddr()
{
    int ret = -1;
    struct in_addr netAddr = { .s4_addr = {192, 168, 1, 1}};
    struct in_addr netMask = { .s4_addr = {255, 255, 255, 0}};

    if (net_if_is_up(wifi_iface)) {
        LOG_INF("Interface is up");
    }

    net_if_carrier_on(wifi_iface);
    while (!net_if_is_carrier_ok(wifi_iface)) {
        k_sleep(K_MSEC(100));
    }
    LOG_INF("Interface carrier is okay");

    // net_if_dormant_off(wifi_iface);
    // while (!net_if_is_dormant(wifi_iface)) {
    //     k_sleep(K_MSEC(100));
    // }
    // LOG_INF("Interface is dormant off");

    // Config NetMask
    net_if_ipv4_set_netmask(wifi_iface, &netMask);
    // Set up the static IP address for the AP
    ifaddr = net_if_ipv4_addr_add(wifi_iface, &netAddr, NET_ADDR_MANUAL, 0);
    if (!ifaddr) {
        LOG_ERR("Failed to set IP address");
        return -1;
    }

    return 0;
}

int wifiApMode(struct net_if * ifWifi)
{
    static struct net_mgmt_event_callback wifi_cb;
    int ret = -1;

    // Configure Wi-Fi AP
    struct wifi_connect_req_params wifi_params = {
        .ssid = SSID,
        .ssid_length = strlen(SSID),
        .psk = PASSPHRASE,
        .psk_length = strlen(PASSPHRASE),
        .channel = CHANNEL,
        .security = WIFI_SECURITY_TYPE_PSK
    };

    net_mgmt_init_event_callback(&wifi_cb, wifi_ap_callback, NET_EVENT_IPV4_ADDR_ADD);
    net_mgmt_add_event_callback(&wifi_cb);

    ret = net_mgmt(NET_REQUEST_WIFI_AP_ENABLE, ifWifi, &wifi_params, sizeof(wifi_params));
    if (ret < 0) {
        LOG_ERR("Failed to request Wifi AP mode: %d", ret);
        return ret;
    }

    ret = configNetAddr();
    if (ret != 0) {
        LOG_ERR("Failed to configure network: %d", ret);
    }

    LOG_INF("WIFI AP mode requested...");

    return 0;
}

int main(void)
{
    int ret;

    LOG_INF("Starting ESP32 AP");

    // Get the Wi-Fi interface
    wifi_iface = net_if_get_default();
    if (!wifi_iface) {
        LOG_ERR("No default network interface found");
        return -1;
    }

    if (wifiApMode(wifi_iface)) {
        return -1;
    }

    LOG_INF("ESP32 AP started, SSID: %s", SSID);

    return 0;
}

The full log of the app:

*** Booting Zephyr OS build v3.6.0 ***
[00:00:00.429,000] <inf> net_config: Initializing network
[00:00:00.429,000] <inf> net_config: Waiting interface 1 (0x3fcaa730) to be up...
[00:00:00.429,000] <inf> net_config: Interface 1 (0x3fcaa730) coming up
[00:00:00.429,000] <inf> net_config: Running dhcpv4 client...
[00:00:00.430,000] <inf> main: Starting ESP32 AP
[00:00:00.964,000] <inf> main: Interface is up
[00:00:00.964,000] <inf> main: Interface carrier is okay
[00:00:00.964,000] <inf> main: wifi_ap_callback
[00:00:00.964,000] <inf> main:    Address[1]: 192.168.1.1
[00:00:00.964,000] <inf> main:     Subnet[1]: 255.255.255.0
[00:00:00.964,000] <inf> main:     Router[1]: 0.0.0.0
[00:00:00.966,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start: Started DHCPv4 server, address pool:
[00:00:00.966,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start:     0: 192.168.1.10
[00:00:00.966,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start:     1: 192.168.1.11
[00:00:00.966,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start:     2: 192.168.1.12
[00:00:00.966,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start:     3: 192.168.1.13
[00:00:00.966,000] <inf> main: WIFI AP mode requested...
[00:00:00.966,000] <inf> main: ESP32 AP started, SSID: ESP32_Access_Point
[00:00:16.268,000] <wrn> net_if: iface 0x3fcaa730 is down
[00:00:16.269,000] <err> net_dhcpv4_server: Failed to send ICMP probe
[00:00:17.367,000] <wrn> net_if: iface 0x3fcaa730 is down
[00:00:17.367,000] <err> net_dhcpv4_server: Failed to send ICMP probe
[00:00:19.283,000] <wrn> net_if: iface 0x3fcaa730 is down
[00:00:19.283,000] <err> net_dhcpv4_server: Failed to send ICMP probe
[00:00:23.357,000] <wrn> net_if: iface 0x3fcaa730 is down
[00:00:23.357,000] <err> net_dhcpv4_server: Failed to send ICMP probe
[00:00:31.336,000] <wrn> net_if: iface 0x3fcaa730 is down
[00:00:31.336,000] <err> net_dhcpv4_server: Failed to send ICMP probe

prj.conf:

CONFIG_EARLY_CONSOLE=y

CONFIG_NETWORKING=y
CONFIG_TEST_RANDOM_GENERATOR=y

CONFIG_NET_TX_STACK_SIZE=2048
CONFIG_NET_RX_STACK_SIZE=2048

CONFIG_NET_PKT_RX_COUNT=10
CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_BUF_RX_COUNT=20
CONFIG_NET_BUF_TX_COUNT=20
CONFIG_NET_MAX_CONTEXTS=10
CONFIG_NET_DHCPV4=y

CONFIG_NET_IPV4=y
CONFIG_NET_IPV6=n

CONFIG_NET_TCP=y

CONFIG_NET_LOG=y
CONFIG_INIT_STACKS=y

CONFIG_NET_STATISTICS=y
CONFIG_NET_STATISTICS_PERIODIC_OUTPUT=n

CONFIG_WIFI=y
CONFIG_WIFI_LOG_LEVEL_ERR=y
CONFIG_WIFI=y

CONFIG_NETWORKING=y
CONFIG_NET_L2_ETHERNET=y

CONFIG_NET_IPV6=n
CONFIG_NET_IPV4=y
CONFIG_NET_DHCPV4=y
CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y

CONFIG_NET_DHCPV4_SERVER=y

# Enable networking
CONFIG_NETWORKING=y
CONFIG_NET_SOCKETS=y
CONFIG_NET_CONFIG_SETTINGS=y

# Enable Wi-Fi
CONFIG_WIFI=y

# Enable DHCP server
CONFIG_NET_DHCPV4_SERVER=y
CONFIG_NET_DHCPV4_SERVER_LOG_LEVEL_DBG=y

# Enable HTTP server
CONFIG_HTTP_SERVER=y
CONFIG_HTTP_PARSER_URL=y

# Enable logging
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3
github-actions[bot] commented 5 days ago

Hi @Hugokie! We appreciate you submitting your first issue for our open-source project. 🌟

Even though I'm a bot, I can assure you that the whole community is genuinely grateful for your time and effort. 🤖💙

Hugokie commented 5 days ago

I add dbg info on wifi and net_if module:

[00:00:00.346,000] <I (349) wifi:wifi driver task: 3fc8cdf0, prio:2, stack:6656, core=0
I (351) wifi:wifi firmware version: 63017e0
I (351) wifi:wifi certification version: v7.0
I (354) wifi:config NVS flash: disabled
I (358) wifi:config nano formating: disabled
I (362) wifi:Init data frame dynamic rx buffer num: 32
I (367) wifi:Init management frame dynamic rx buffer num: 32
I (372) wifi:Init management short buffer num: 32
I (376) wifi:Init dynamic tx buffer num: 32
I (380) wifi:Init static tx FG buffer num: 2
I (384) wifi:Init static rx buffer size: 1600
I (388) wifi:Init static rx buffer num: 10
I (392) wifi:Init dynamic rx buffer num: 32
I (475) wifi:mode : sta (7c:df:a1:fb:08:a4)
I (475) wifi:enable tsf
I (480) wifi:mode : softAP (7c:df:a1:fb:08:a5)
I (481) wifi:Total power save buffer number: 16
I (481) wifi:Init max length of beacon: 752/752
I (483) wifi:Init max length of beacon: 752/752
I (1015) wifi:Total power save buffer number: 16
dbg> net_if: net_if_init: (0x3fc8d308): 
--- 5 messages dropped ---
*** Booting Zephyr OS build v3.6.0 ***
[00:00:00.477,000] <inf> net_config: Initializing network
[00:00:00.477,000] <inf> net_config: Waiting interface 1 (0x3fcaa888) to be up...
[00:00:00.477,000] <dbg> net_if: update_operational_state: (0x3fc8d388): iface 0x3fcaa888, oper state UP admin UP carrier ON dormant OFF
[00:00:00.477,000] <inf> net_config: Interface 1 (0x3fcaa888) coming up
[00:00:00.477,000] <inf> net_config: Running dhcpv4 client...
[00:00:00.478,000] <inf> main: Starting ESP32 AP
[00:00:01.016,000] <inf> main: Interface is up
[00:00:01.016,000] <inf> main: Interface carrier is okay
[00:00:01.017,000] <dbg> net_if: net_if_ipv4_addr_add: (0x3fc8d308): [0] interface 0x3fcaa888 address 192.168.1.1 type MANUAL added
[00:00:01.017,000] <inf> main: wifi_ap_callback
[00:00:01.017,000] <inf> main:    Address[1]: 192.168.1.1
[00:00:01.017,000] <inf> main:     Subnet[1]: 255.255.255.0
[00:00:01.017,000] <inf> main:     Router[1]: 0.0.0.0
[00:00:01.019,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start: Started DHCPv4 server, address pool:
[00:00:01.019,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start:     0: 192.168.1.10
[00:00:01.019,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start:     1: 192.168.1.11
[00:00:01.019,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start:     2: 192.168.1.12
[00:00:01.019,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start:     3: 192.168.1.13
[00:00:01.019,000] <inf> main: WIFI AP mode requested...
[00:00:01.019,000] <inf> main: ESP32 AP started, SSID: ESP32AP
[00:00:01.020,000] <dbg> net_if: update_operational_state: (0x3fc8d388): iface 0x3fcaa888, oper state DOWN admin UP carrier OFF dormant OFF
I (13522) wifi:new:<6,1>, old:<6,1>, ap:<6,1>, sta:<255,255>, prof:6
I (13523) wifi:station: XX:XX:XX:XX:XX:XX join, AID=1, bgn, 40U
W (14604) wifi:<ba-add>idx:2 (ifx:1, XX:XX:XX:XX:XX:XX), tid:0, ssn:7, winSize:64
[00:00:13.782,000] <wrn> net_if: iface 0x3fcaa888 is down
[00:00:13.782,000] <err> net_dhcpv4_server: Failed to send ICMP probe
[00:00:14.776,000] <wrn> net_if: iface 0x3fcaa888 is down
[00:00:14.776,000] <err> net_dhcpv4_server: Failed to send ICMP probe
[00:00:16.930,000] <wrn> net_if: iface 0x3fcaa888 is down
[00:00:16.930,000] <err> net_dhcpv4_server: Failed to send ICMP probe
[00:00:21.306,000] <wrn> net_if: iface 0x3fcaa888 is down
[00:00:21.306,000] <err> net_dhcpv4_server: Failed to send ICMP probe
[00:00:28.975,000] <wrn> net_if: iface 0x3fcaa888 is down
[00:00:28.975,000] <err> net_dhcpv4_server: Failed to send ICMP probe
I (31778) wifi:station: XX:XX:XX:XX:XX:XX leave, AID = 1, bss_flags is 658531, bss:0x3fc9f620
I (31778) wifi:new:<6,0>, old:<6,1>, ap:<6,1>, sta:<255,255>, prof:6
W (31782) wifi:<ba-del>idx
Hugokie commented 5 days ago

Some progress... But !

If I wait a litlle after the AP mode is set and network addr is set I can net_if_carrier_on() the device become ready and send an offer. But the program stop without error :

*** Booting Zephyr OS build v3.6.0 ***
[00:00:00.475,000] <inf> main: Starting ESP32 AP
[00:00:01.015,000] <dbg> net_if: update_operational_state: (0x3fc8d348): iface 0x3fcaafd8, oper state UP admin UP carrier ON dormant OFF
[00:00:01.016,000] <inf> main: Interface is up
[00:00:01.016,000] <dbg> net_if: net_if_ipv4_addr_add: (0x3fc8d2c8): [0] interface 0x3fcaafd8 address 192.168.1.1 type MANUAL added
[00:00:01.016,000] <inf> main: wifi_ap_callback
[00:00:01.016,000] <inf> main:    Address[1]: 192.168.1.1
[00:00:01.016,000] <inf> main:     Subnet[1]: 255.255.255.0
[00:00:01.016,000] <inf> main:     Router[1]: 0.0.0.0
[00:00:01.018,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start: Started DHCPv4 server, address pool:
[00:00:01.018,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start:     0: 192.168.1.10
[00:00:01.018,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start:     1: 192.168.1.11
[00:00:01.018,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start:     2: 192.168.1.12
[00:00:01.018,000] <dbg> net_dhcpv4_server: net_dhcpv4_server_start:     3: 192.168.1.13
[00:00:01.018,000] <inf> main: WIFI AP mode requested...
[00:00:01.018,000] <inf> main: ESP32 AP started, SSID: ESP32AP
[00:00:01.019,000] <dbg> net_if: update_operational_state: (0x3fc8d348): iface 0x3fcaafd8, oper state DOWN admin UP carrier OFF dormant OFF
[00:00:01.218,000] <dbg> net_if: update_operational_state: (0x3fc8d2c8): iface 0x3fcaafd8, oper state UP admin UP carrier ON dormant OFF
[00:00:01.218,000] <inf> main: Interface carrier is okay
[00:00:01.218,000] <inf> main: Alive
[00:00:02.219,000] <inf> main: Alive
[00:00:20.220,000] <inf> main: Alive
I (22018) wifi:new:<1,1>, old:<1,1>, ap:<1,1>, sta:<255,255>, prof:1
I (22019) wifi:station: XX:XX:XX:XX:XX join, AID=1, bgn, 40U
[00:00:21.220,000] <inf> main: Alive
[00:00:22.221,000] <inf> main: Alive
W (24146) wifi:<ba-add>idx:2 (ifx:1, XX:XX:XX:XX:XX), tid:0, ssn:9, winSize:64
[00:00:23.221,000] <inf> main: Alive
[00:00:24.221,000] <inf> main: Alive
[00:00:27.221,000] <inf> main: Alive
[00:00:27.312,000] <dbg> net_if: net_if_tx: (0x3fc8ce40): Processing (pkt 0x3fca6d14, prio 0) network packet iface 0x3fcaafd8/1
[00:00:27.313,000] <dbg> esp32_wifi: esp32_wifi_send: pkt sent 0x3fca6cd4 len 42
[00:00:27.314,000] <dbg> net_dhcpv4_server: dhcpv4_handle_discover: DHCPv4 processing Discover - reserved 192.168.1.10
[00:00:28.221,000] <inf> main: Alive

Alive is print each second in the main. Nothing is print after the offer was sent and the AP is not available.

The new full code :

#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/net/socket.h>
#include <zephyr/net/dhcpv4.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/wifi_mgmt.h>
#include <zephyr/net/dhcpv4_server.h>
#include <zephyr/net/net_ip.h>
#include <zephyr/net/net_core.h>
#include <zephyr/net/net_mgmt.h>

LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);

#define SSID "ESP32AP"
#define PASSPHRASE "123456789"
#define CHANNEL 1

static struct net_if_addr *ifaddr;
static struct net_if *wifi_iface;

static void wifi_ap_callback(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, struct net_if *iface)
{
    int ret = -1;

    LOG_INF("wifi_ap_callback");
    switch (mgmt_event) {
        case NET_EVENT_IPV4_ADDR_ADD:
            int ret = -1;
            struct in_addr startLease = { .s4_addr = {192, 168, 1, 10}};
            char buf[NET_IPV4_ADDR_LEN];

            LOG_INF("   Address[%d]: %s", net_if_get_by_iface(iface),
                    net_addr_ntop(AF_INET,
                    &iface->config.ip.ipv4->unicast[0].address.in_addr,
                    buf, sizeof(buf)));
            LOG_INF("    Subnet[%d]: %s", net_if_get_by_iface(iface),
                    net_addr_ntop(AF_INET,
                    &iface->config.ip.ipv4->netmask,
                    buf, sizeof(buf)));
            LOG_INF("    Router[%d]: %s", net_if_get_by_iface(iface),
                    net_addr_ntop(AF_INET,
                    &iface->config.ip.ipv4->gw,
                    buf, sizeof(buf)));

            // Set up DHCP server
            ret = net_dhcpv4_server_start(wifi_iface, &startLease);
            // net_dhcpv4_start(wifi_iface);
            if (ret < 0) {
                LOG_ERR("Failed to start DHCP server: %d", ret);
                return;
            }
            return;
        break;
    }

    LOG_INF("Wi-Fi connected");

    // Start HTTP server
    // start_http_server();
}

int configNetAddr()
{
    int ret = -1;
    struct in_addr netAddr = { .s4_addr = {192, 168, 1, 1}};
    struct in_addr netMask = { .s4_addr = {255, 255, 255, 0}};

    if (net_if_is_up(wifi_iface)) {
        LOG_INF("Interface is up");
    } else {
        LOG_ERR("Interface is down");
        return -1;
    }

    // Config NetMask
    net_if_ipv4_set_netmask(wifi_iface, &netMask);
    // Set up the static IP address for the AP
    ifaddr = net_if_ipv4_addr_add(wifi_iface, &netAddr, NET_ADDR_MANUAL, 0);
    if (!ifaddr) {
        LOG_ERR("Failed to set IP address");
        return -1;
    }

    return 0;
}

int wifiApMode(struct net_if * ifWifi)
{
    static struct net_mgmt_event_callback wifi_cb;
    int ret = -1;

    // Configure Wi-Fi AP
    struct wifi_connect_req_params wifi_params = {
        .ssid = SSID,
        .ssid_length = strlen(SSID),
        .psk = PASSPHRASE,
        .psk_length = strlen(PASSPHRASE),
        .channel = CHANNEL,
        .security = WIFI_SECURITY_TYPE_PSK
    };

    net_mgmt_init_event_callback(&wifi_cb, wifi_ap_callback, NET_EVENT_IPV4_ADDR_ADD);
    net_mgmt_add_event_callback(&wifi_cb);

    ret = net_mgmt(NET_REQUEST_WIFI_AP_ENABLE, ifWifi, &wifi_params, sizeof(wifi_params));
    if (ret < 0) {
        LOG_ERR("Failed to request Wifi AP mode: %d", ret);
        return ret;
    }

    ret = configNetAddr();
    if (ret != 0) {
        LOG_ERR("Failed to configure network: %d", ret);
    }

    LOG_INF("WIFI AP mode requested...");

    return 0;
}

int main(void)
{
    int ret;

    LOG_INF("Starting ESP32 AP");

    // Get the Wi-Fi interface
    wifi_iface = net_if_get_default();
    if (!wifi_iface) {
        LOG_ERR("No default network interface found");
        return -1;
    }

    if (wifiApMode(wifi_iface)) {
        return -1;
    }

    LOG_INF("ESP32 AP started, SSID: %s", SSID);

    k_sleep(K_MSEC(200));

    net_if_carrier_on(wifi_iface);
    while (!net_if_is_carrier_ok(wifi_iface)) {
        k_sleep(K_MSEC(100));
    }
    LOG_INF("Interface carrier is okay");

    while (1) {
        LOG_INF("Alive");
        k_sleep(K_SECONDS(1));
    }

    return 0;
}

Last config file:

CONFIG_EARLY_CONSOLE=y

# Network config
CONFIG_NETWORKING=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_TX_STACK_SIZE=4096
CONFIG_NET_RX_STACK_SIZE=4096
CONFIG_NET_PKT_RX_COUNT=10
CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_BUF_RX_COUNT=20
CONFIG_NET_BUF_TX_COUNT=20
CONFIG_NET_MAX_CONTEXTS=10
CONFIG_NET_DHCPV4=y
CONFIG_NET_IPV4=y
CONFIG_NET_IPV6=n
CONFIG_NET_TCP=y
CONFIG_NET_STATISTICS=y
CONFIG_NET_STATISTICS_PERIODIC_OUTPUT=n
# CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y

CONFIG_NET_LOG=y
CONFIG_NET_IF_LOG_LEVEL_DBG=y

# Enable Wifi
CONFIG_WIFI=y
CONFIG_WIFI_LOG_LEVEL_DBG=y

# Enable DHCP server
CONFIG_NET_DHCPV4_SERVER=y
CONFIG_NET_DHCPV4_SERVER_ADDR_COUNT=1
# CONFIG_NET_DHCPV4_SERVER_ICMP_PROBE_TIMEOUT=0
CONFIG_NET_DHCPV4_SERVER_LOG_LEVEL_DBG=y

# Enable HTTP server
CONFIG_HTTP_SERVER=y
CONFIG_HTTP_PARSER_URL=y

# Enable logging
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3
Hugokie commented 1 day ago

Now, I have a working code WifiAP + DHCP.

The bug seems to come from the DHCP ICMP Probe. If I disable ICMP probe it works and the program don't stop after replying to a DHCP request.

Below the full code and configuration, if it can helps anyone...

Full code :

#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/net/socket.h>
#include <zephyr/net/dhcpv4.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/wifi_mgmt.h>
#include <zephyr/net/dhcpv4_server.h>
#include <zephyr/net/net_ip.h>
#include <zephyr/net/net_core.h>
#include <zephyr/net/net_mgmt.h>

LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);

#define SSID "ESP32AP"
#define PASSPHRASE "123456789"
#define CHANNEL 1

static struct net_if_addr *ifaddr;
static struct net_if *wifi_iface;

static void wifi_ap_callback(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, struct net_if *iface)
{
    int ret = -1;

    LOG_INF("wifi_ap_callback");
    switch (mgmt_event) {
        case NET_EVENT_IPV4_ADDR_ADD:
            int ret = -1;
            struct in_addr startLease = { .s4_addr = {192, 168, 1, 10}};
            char buf[NET_IPV4_ADDR_LEN];

            LOG_INF("   Address[%d]: %s", net_if_get_by_iface(iface),
                    net_addr_ntop(AF_INET,
                    &iface->config.ip.ipv4->unicast[0].address.in_addr,
                    buf, sizeof(buf)));
            LOG_INF("    Subnet[%d]: %s", net_if_get_by_iface(iface),
                    net_addr_ntop(AF_INET,
                    &iface->config.ip.ipv4->netmask,
                    buf, sizeof(buf)));
            LOG_INF("    Router[%d]: %s", net_if_get_by_iface(iface),
                    net_addr_ntop(AF_INET,
                    &iface->config.ip.ipv4->gw,
                    buf, sizeof(buf)));

            // Set up DHCP server
            ret = net_dhcpv4_server_start(wifi_iface, &startLease);
            if (ret < 0) {
                LOG_ERR("Failed to start DHCP server: %d", ret);
                return;
            }
            return;
        break;
    }

    LOG_INF("Wi-Fi connected");

    // Start HTTP server
    // start_http_server();
}

int configNetAddr()
{
    int ret = -1;
    struct in_addr netAddr = { .s4_addr = {192, 168, 1, 1}};
    struct in_addr netMask = { .s4_addr = {255, 255, 255, 0}};

    if (net_if_is_up(wifi_iface)) {
        LOG_INF("Interface is up");
    } else {
        LOG_ERR("Interface is down");
        return -1;
    }

    // Config NetMask
    net_if_ipv4_set_netmask(wifi_iface, &netMask);
    // Set up the static IP address for the AP
    ifaddr = net_if_ipv4_addr_add(wifi_iface, &netAddr, NET_ADDR_MANUAL, 0);
    if (!ifaddr) {
        LOG_ERR("Failed to set IP address");
        return -1;
    }

    return 0;
}

int wifiApMode(struct net_if * ifWifi)
{
    static struct net_mgmt_event_callback wifi_cb;
    int ret = -1;

    // Configure Wi-Fi AP
    struct wifi_connect_req_params wifi_params = {
        .ssid = SSID,
        .ssid_length = strlen(SSID),
        .psk = PASSPHRASE,
        .psk_length = strlen(PASSPHRASE),
        .channel = CHANNEL,
        .security = WIFI_SECURITY_TYPE_PSK
    };

    net_mgmt_init_event_callback(&wifi_cb, wifi_ap_callback, NET_EVENT_IPV4_ADDR_ADD);
    net_mgmt_add_event_callback(&wifi_cb);

    ret = net_mgmt(NET_REQUEST_WIFI_AP_ENABLE, ifWifi, &wifi_params, sizeof(wifi_params));
    if (ret < 0) {
        LOG_ERR("Failed to request Wifi AP mode: %d", ret);
        return ret;
    }

    ret = configNetAddr();
    if (ret != 0) {
        LOG_ERR("Failed to configure network: %d", ret);
    }

    LOG_INF("WIFI AP mode requested...");

    return 0;
}

int main(void)
{
    int ret;

    LOG_INF("Starting ESP32 AP");

    // Get the Wi-Fi interface
    wifi_iface = net_if_get_default();
    if (!wifi_iface) {
        LOG_ERR("No default network interface found");
        return -1;
    }

    if (wifiApMode(wifi_iface)) {
        return -1;
    }

    LOG_INF("ESP32 AP started, SSID: %s", SSID);

    k_sleep(K_MSEC(200));

    net_if_carrier_on(wifi_iface);
    while (!net_if_is_carrier_ok(wifi_iface)) {
        k_sleep(K_MSEC(100));
    }
    LOG_INF("Interface carrier is okay");

    while (1) {
        LOG_INF("Alive");
        k_sleep(K_SECONDS(1));
    }

    return 0;
}

prj.conf :

CONFIG_EARLY_CONSOLE=y

# Network config
CONFIG_NETWORKING=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_TX_STACK_SIZE=4096
CONFIG_NET_RX_STACK_SIZE=4096
CONFIG_NET_PKT_RX_COUNT=10
CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_BUF_RX_COUNT=20
CONFIG_NET_BUF_TX_COUNT=20
CONFIG_NET_MAX_CONTEXTS=10
CONFIG_NET_DHCPV4=y
CONFIG_NET_IPV4=y
CONFIG_NET_IPV6=n
CONFIG_NET_TCP=y
CONFIG_NET_STATISTICS=y
CONFIG_NET_STATISTICS_PERIODIC_OUTPUT=n

# Enable Wifi
CONFIG_WIFI=y

# Enable DHCP server
CONFIG_NET_DHCPV4_SERVER=y
CONFIG_NET_DHCPV4_SERVER_ADDR_COUNT=10
CONFIG_NET_DHCPV4_SERVER_ICMP_PROBE_TIMEOUT=0

# Enable HTTP server
CONFIG_HTTP_SERVER=y
CONFIG_HTTP_PARSER_URL=y

# Enable logging
CONFIG_NET_LOG=y
# Debug Log
# CONFIG_NET_IF_LOG_LEVEL_DBG=y
# CONFIG_NET_ARP_LOG_LEVEL_DBG=y
# CONFIG_WIFI_LOG_LEVEL_DBG=y
# CONFIG_NET_DHCPV4_SERVER_LOG_LEVEL_DBG=y

CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3
munir-zin commented 18 hours ago

I am trying this example, but unable to get IP address. It is getting self assigned IP instead from ESP32.

image
Hugokie commented 16 hours ago

To add information about the bug.

I realized that the DBG log masked the error if I remove the DBG log and enable ICMP probe a load prohibited exception occurs.

To reproduce get my last sample code and activate ICMP Probe (CONFIG_NET_DHCPV4_SERVER_ICMP_PROBE_TIMEOUT=1000)

For people want to use DHCP and AP without ICMP probe the same code is working with CONFIG_NET_DHCPV4_SERVER_ICMP_PROBE_TIMEOUT=0

The error below:

[00:00:15.167,000] <err> os:  ** FATAL EXCEPTION
[00:00:15.167,000] <err> os:  ** CPU 0 EXCCAUSE 28 (load prohibited)
[00:00:15.167,000] <err> os:  **  PC 0x4037720c VADDR 0x60810
0x4037720c: xtensa_restore_high_regs at /workdir/zephyr/arch/xtensa/core/xtensa_asm2_util.S:109

[00:00:15.167,000] <err> os:  **  PS 0x50f20
[00:00:15.167,000] <err> os:  **    (INTLEVEL:0 EXCM: 0 UM:1 RING:0 WOE:1 OWB:15 CALLINC:1)
[00:00:15.167,000] <err> os:  **  A0 0x40377238  SP 0x3fc988cc  A2 0x60810  A3 0x60820
0x40377238: _restore_context at /workdir/zephyr/arch/xtensa/core/xtensa_asm2_util.S:154

[00:00:15.167,000] <err> os:  **  A4 0x4037735d  A5 0x3fc97600  A6 0x3fc988c8  A7 0x3fc8d228
0x4037735d: _do_call_3 at /workdir/zephyr/arch/xtensa/core/xtensa_asm2_util.S:306

[00:00:15.167,000] <err> os:  **  A8 0x40377372  A9 0x3fc975c0 A10 0x3fc988c8 A11 0x40000
0x40377372: _xstack_call0_5 at /workdir/zephyr/arch/xtensa/core/xtensa_asm2_util.S:306

[00:00:15.167,000] <err> os:  ** A12 0x4 A13 0 A14 0x1000 A15 0x3fc975c0
[00:00:15.167,000] <err> os:  ** LBEG 0 LEND 0 LCOUNT 0
[00:00:15.167,000] <err> os:  ** SAR 0xe
[00:00:15.167,000] <err> os:  **  THREADPTR 0
[00:00:15.167,000] <err> os: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
[00:00:15.167,000] <err> os: Current thread: 0x3fc8d1c8 (unknown)
[00:00:15.253,000] <err> os: Halting system