Why does a project that works with the nRF7002DK(by Nordic) evaluation board not work with the EVM-WM02-V6(by Fanstel) evaluation board?

Some time ago I asked why the combination of nRF52840 and nRF7002 does not work.

 How do I build with the combination of nrf52840 and nrf7002? I get an error. 

I decided that it would not work with the current SDK 2.5.2, so I gave up.

(Needless to say, I have patched the SDK bug fixes that were mentioned in the reference thread. Then gave up.)

It seems difficult to run with nRF52840, so I plan to use a combination of Raytac's MDBT53V (nRF5340) and Fanstel's WM02C (nRF7002). It doesn't require wireless authentication.

https://www.raytac.com/product/ins.php?index_id=135

https://www.fanstel.com/nrf7002wifi6module

We already have a sample project that has been tested with nRF7002DK. The project is below.

/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <dk_buttons_and_leds.h>
#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/wifi_mgmt.h>

LOG_MODULE_REGISTER(main, LOG_LEVEL_INF);

#define NET_EVENT_WIFI_EVENTS (			\
	NET_EVENT_WIFI_SCAN_RESULT			|	\
	NET_EVENT_WIFI_SCAN_DONE			|	\
	NET_EVENT_WIFI_CONNECT_RESULT		|	\
	NET_EVENT_WIFI_DISCONNECT_RESULT	|	\
	NET_EVENT_WIFI_IFACE_STATUS			|	\
	NET_EVENT_WIFI_TWT					|	\
	NET_EVENT_WIFI_TWT_SLEEP_STATE		|	\
	NET_EVENT_WIFI_RAW_SCAN_RESULT		|	\
	NET_EVENT_WIFI_DISCONNECT_COMPLETE		\
)

#define NET_EVENT_IPV4_EVENTS (				\
	NET_EVENT_IPV4_ADDR_ADD		|			\
	NET_EVENT_IPV4_ADDR_DEL		|			\
	NET_EVENT_IPV4_MADDR_ADD	|			\
	NET_EVENT_IPV4_MADDR_DEL	|			\
	NET_EVENT_IPV4_ROUTER_ADD	|			\
	NET_EVENT_IPV4_ROUTER_DEL	|			\
	NET_EVENT_IPV4_DHCP_START	|			\
	NET_EVENT_IPV4_DHCP_BOUND	|			\
	NET_EVENT_IPV4_DHCP_STOP	|			\
	NET_EVENT_IPV4_MCAST_JOIN	|			\
	NET_EVENT_IPV4_MCAST_LEAVE				\
)

// for User queue(s)
static struct k_work_q uq_button;
K_THREAD_STACK_DEFINE(us_button, 512);
// Semaphore(s)
K_SEM_DEFINE(sem_udp_send, 0, 1);
K_SEM_DEFINE(sem_udp_send_wait, 0, 1);

// Variable(s)
static struct net_mgmt_event_callback wifi_shell_mgmt_cb;
static struct net_mgmt_event_callback net_shell_mgmt_cb;
static struct net_context *udp_ctx;
static char *host = "xxx.xxx.xxx.xxx";
static uint16_t port = 12345;
static uint8_t packet[32];

/* ----- Timer Function Start ----- */
static void udp_rcvd(struct net_context *context, struct net_pkt *pkt, union net_ip_header *ip_hdr, union net_proto_header *proto_hdr, int status, void *user_data)
{
	if (pkt) {
		size_t len = net_pkt_remaining_data(pkt);
		uint8_t byte;

		LOG_INF("Received UDP packet: ");
		for (size_t i = 0; i < len; ++i) {
			net_pkt_read_u8(pkt, &byte);
			LOG_INF("%02x ", byte);
		}

		net_pkt_unref(pkt);
	}
}

static void udp_sent(struct net_context *context, int status, void *user_data)
{
	ARG_UNUSED(context);
	ARG_UNUSED(status);
	ARG_UNUSED(user_data);

	LOG_DBG("Message sent");
	k_sem_give(&sem_udp_send_wait);
}

static void timer_handler(struct k_timer *timer)
{
    // Send
	k_sem_give(&sem_udp_send);
}
K_TIMER_DEFINE(timer, timer_handler, NULL);
/* ----- Timer Function End ----- */

static void wifi_disconnect_work_handler(struct k_work *work)
{
	struct net_if *iface;

	// Parameter(s)
	iface = net_if_get_default();

	// Connect
	if (net_mgmt(NET_REQUEST_WIFI_CONNECT, iface, NULL, 0)) {
		LOG_ERR("Disconnection request failed.");
	}
}
K_WORK_DELAYABLE_DEFINE(wifi_disconnect, wifi_disconnect_work_handler);

static void wifi_connect_work_handler(struct k_work *work)
{
	struct net_if *iface;
	struct wifi_connect_req_params cnx_params;

	// if (context.connected) {
	// 	LOG_WRN("Already connected.");
	// 	return;
	// }

	// Parameter(s)
	iface = net_if_get_default();
	cnx_params.timeout = 30;
	cnx_params.ssid = "ssid";
	cnx_params.ssid_length = strlen(cnx_params.ssid);
	cnx_params.security = WIFI_SECURITY_TYPE_PSK;
	cnx_params.psk = "password";
	cnx_params.psk_length = strlen(cnx_params.psk);
	cnx_params.channel = WIFI_CHANNEL_ANY;
	cnx_params.mfp = WIFI_MFP_OPTIONAL;

	// Connect
	if (net_mgmt(NET_REQUEST_WIFI_CONNECT, iface, &cnx_params, sizeof(struct wifi_connect_req_params))) {
		LOG_ERR("Connection request failed.");
	}
}
K_WORK_DELAYABLE_DEFINE(wifi_connect, wifi_connect_work_handler);

static void print_dhcp_ip(struct net_mgmt_event_callback *cb)
{
	/* Get DHCP info from struct net_if_dhcpv4 and print */
	const struct net_if_dhcpv4 *dhcpv4 = cb->info;
	const struct in_addr *addr = &dhcpv4->requested_ip;
	char dhcp_info[128];

	net_addr_ntop(AF_INET, addr, dhcp_info, sizeof(dhcp_info));
	LOG_INF("DHCP IP address: %s", dhcp_info);
}

static void net_mgmt_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, struct net_if *iface)
{
	switch (mgmt_event) {
        case NET_EVENT_IPV4_ADDR_ADD:
        LOG_INF("NET_EVENT_IPV4_ADDR_ADD");
        break;

        case NET_EVENT_IPV4_ADDR_DEL:
        LOG_INF("NET_EVENT_IPV4_ADDR_DEL");
        break;

        case NET_EVENT_IPV4_MADDR_ADD:
        LOG_INF("NET_EVENT_IPV4_MADDR_ADD");
        break;

        case NET_EVENT_IPV4_MADDR_DEL:
        LOG_INF("NET_EVENT_IPV4_MADDR_DEL");
        break;

        case NET_EVENT_IPV4_ROUTER_ADD:
        LOG_INF("NET_EVENT_IPV4_ROUTER_ADD");
        break;

        case NET_EVENT_IPV4_ROUTER_DEL:
        LOG_INF("NET_EVENT_IPV4_ROUTER_DEL");
        break;

        case NET_EVENT_IPV4_DHCP_START:
        LOG_INF("NET_EVENT_IPV4_DHCP_START");
        break;

        case NET_EVENT_IPV4_DHCP_BOUND:
        LOG_INF("NET_EVENT_IPV4_DHCP_BOUND");
		print_dhcp_ip(cb);
        k_timer_start(&timer, K_NO_WAIT, K_MSEC(100));
		break;

        case NET_EVENT_IPV4_DHCP_STOP:
        LOG_INF("NET_EVENT_IPV4_DHCP_STOP");
        break;

        case NET_EVENT_IPV4_MCAST_JOIN:
        LOG_INF("NET_EVENT_IPV4_MCAST_JOIN");
        break;

        case NET_EVENT_IPV4_MCAST_LEAVE:
        LOG_INF("NET_EVENT_IPV4_MCAST_LEAVE");
        break;

        default:
        LOG_INF("NET_EVENT_IPV4_OTHER");
		break;
	}
}

static void handle_wifi_disconnect_result(struct net_mgmt_event_callback *cb)
{
	const struct wifi_status *status = (const struct wifi_status *) cb->info;

    LOG_INF("Disconnection request %s (%d)", status->status ? "failed" : "done", status->status);
}

static void handle_wifi_connect_result(struct net_mgmt_event_callback *cb)
{
	const struct wifi_status *status = (const struct wifi_status *) cb->info;

	if (status->status) {
		LOG_ERR("Connection failed.(%d)", status->status);
	} else {
		LOG_INF("Connected");
	}
}

// Callback
static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, struct net_if *iface)
{
	switch (mgmt_event) {
        case NET_EVENT_WIFI_SCAN_RESULT:
        LOG_INF("NET_EVENT_WIFI_SCAN_RESULT");
        break;

        case NET_EVENT_WIFI_SCAN_DONE:
        LOG_INF("NET_EVENT_WIFI_SCAN_DONE");
        break;

        case NET_EVENT_WIFI_CONNECT_RESULT:
        LOG_INF("NET_EVENT_WIFI_CONNECT_RESULT");
        handle_wifi_connect_result(cb);
        break;

        case NET_EVENT_WIFI_DISCONNECT_RESULT:
        LOG_INF("NET_EVENT_WIFI_DISCONNECT_RESULT");
		handle_wifi_disconnect_result(cb);
        break;

        case NET_EVENT_WIFI_IFACE_STATUS:
        LOG_INF("NET_EVENT_WIFI_IFACE_STATUS");
        break;

        case NET_EVENT_WIFI_TWT:
        LOG_INF("NET_EVENT_WIFI_TWT");
        break;

        case NET_EVENT_WIFI_TWT_SLEEP_STATE:
        LOG_INF("NET_EVENT_WIFI_TWT_SLEEP_STATE");
        break;

        case NET_EVENT_WIFI_RAW_SCAN_RESULT:
        LOG_INF("NET_EVENT_WIFI_RAW_SCAN_RESULT");
        break;

        case NET_EVENT_WIFI_DISCONNECT_COMPLETE:
        LOG_INF("NET_EVENT_WIFI_DISCONNECT_COMPLETE");
        break;

        default:
        LOG_WRN("NET_EVENT_WIFI_OTHER");
        break;
	}
}

static void button_holding_work_handler(struct k_work *work)
{
    LOG_INF("Button holding!");
}
K_WORK_DELAYABLE_DEFINE(button_holding, button_holding_work_handler);

void button_changed(uint32_t button_state, uint32_t has_changed)
{
    if (has_changed & 0x01) {
        if (button_state & has_changed) {
            LOG_DBG("button 0 changes to on");
			// WiFi connect
			k_work_schedule(&wifi_connect, K_NO_WAIT);
            // Long push
            k_work_schedule_for_queue(&uq_button, &button_holding, K_MSEC(2000));
        } else {
            LOG_DBG("button 0 changes to off.");
            k_work_cancel_delayable(&button_holding);
        }
    }

#if DT_NODE_EXISTS(DT_ALIAS(sw1))
    if (has_changed & 0x02) {
        if (button_state & has_changed) {
            LOG_DBG("button 1 changes to on");
			// WiFi disconnect
			k_work_schedule(&wifi_disconnect, K_NO_WAIT);
            // Long push
            k_work_schedule_for_queue(&uq_button, &button_holding, K_MSEC(2000));
        } else {
            LOG_DBG("button 1 changes to off.");
            k_work_cancel_delayable(&button_holding);
        }
    }
#endif

#if DT_NODE_EXISTS(DT_ALIAS(sw2))
    if (has_changed & 0x04) {
        if (button_state & has_changed) {
            LOG_INF("button 2 changes to on");
        } else {
            LOG_INF("button 2 changes to off.");
        }
    }
#endif

#if DT_NODE_EXISTS(DT_ALIAS(sw3))
    if (has_changed & 0x08) {
        if (button_state & has_changed) {
            LOG_INF("button 3 changes to on");
        } else {
            LOG_INF("button 3 changes to off.");
        }
    }
#endif
}

int main(void)
{
    int err, ret;
    struct net_if *iface;
    struct sockaddr addr;
    int addrlen;

    // Initialize variable(s)
    memset(packet, 0x31, sizeof(packet));

    // Initialize Buttons and LEDs
    err = dk_buttons_init(button_changed);
    if (err) {
        LOG_ERR("Failed to initialize button[s].(%d)", err);
        return -1;
    }
    err = dk_leds_init();
    if (err) {
        LOG_ERR("Failed to initialize led[s].(%d)", err);
        return -1;
    }

	// User queue for button holding
    k_work_queue_start(&uq_button, us_button, K_THREAD_STACK_SIZEOF(us_button), K_PRIO_PREEMPT(0), NULL);

    // WiFi callback
	net_mgmt_init_event_callback(&wifi_shell_mgmt_cb, wifi_mgmt_event_handler, NET_EVENT_WIFI_EVENTS);
	net_mgmt_add_event_callback(&wifi_shell_mgmt_cb);
	net_mgmt_init_event_callback(&net_shell_mgmt_cb, net_mgmt_event_handler, NET_EVENT_IPV4_EVENTS);
	net_mgmt_add_event_callback(&net_shell_mgmt_cb);

    while (true) {
        if (!k_sem_take(&sem_udp_send, K_MSEC(500))) {
            if (udp_ctx && net_context_is_used(udp_ctx)) {
                LOG_WRN("Network context already in use");
                continue;
            }

            memset(&addr, 0, sizeof(addr));
            ret = net_ipaddr_parse(host, strlen(host), &addr);
            if (ret < 0) {
                LOG_WRN("Cannot parse address \"%s\"", host);
                continue;
            }

            ret = net_context_get(addr.sa_family, SOCK_DGRAM, IPPROTO_UDP, &udp_ctx);
            if (ret < 0) {
                LOG_WRN("Cannot get UDP context.(%d)", ret);
                continue;
            }

            if (IS_ENABLED(CONFIG_NET_IPV4) && addr.sa_family == AF_INET) {
                net_sin(&addr)->sin_port = htons(port);
                addrlen = sizeof(struct sockaddr_in);

                iface = net_if_ipv4_select_src_iface(&net_sin(&addr)->sin_addr);
            } else {
                LOG_WRN("IPv4 is disabled, cannot %s.", "send");
                goto release_ctx;
            }

            if (!iface) {
                LOG_WRN("No interface to send to given host");
                goto release_ctx;
            }

            net_context_set_iface(udp_ctx, iface);

            ret = net_context_recv(udp_ctx, udp_rcvd, K_NO_WAIT, NULL);
            if (ret < 0) {
                LOG_WRN("Setting rcv callback failed (%d)", ret);
                goto release_ctx;
            }

            ret = net_context_sendto(udp_ctx, packet, sizeof(packet), &addr, addrlen, udp_sent, K_FOREVER, NULL);
            if (ret < 0) {
                LOG_WRN("Sending packet failed (%d)", ret);
                goto release_ctx;
            }

            ret = k_sem_take(&sem_udp_send_wait, K_SECONDS(2));
            if (ret == -EAGAIN) {
                LOG_WRN("UDP packet sending failed");
            }

release_ctx:
            ret = net_context_put(udp_ctx);
            if (ret < 0) {
                LOG_WRN("Cannot put UDP context (%d)", ret);
            }
        }
    }
}

CONFIG_WIFI=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_IPV6=n
CONFIG_HEAP_MEM_POOL_SIZE=153600
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
CONFIG_WPA_SUPP=y
CONFIG_WPA_SUPP_ADVANCED_FEATURES=n
CONFIG_WPA_SUPP_WPA3=n
CONFIG_DK_LIBRARY=y
CONFIG_WIFI_NRF700X=y
CONFIG_NET_TX_STACK_SIZE=8192
CONFIG_NET_RX_STACK_SIZE=8192
CONFIG_USE_SEGGER_RTT=y
CONFIG_FLASH=y
CONFIG_COMMON_LIBC_MALLOC=n
CONFIG_DEBUG_THREAD_INFO=y
CONFIG_NVS=y
CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=100
CONFIG_NETWORKING=y
CONFIG_NET_IPV4=y
CONFIG_NET_DHCPV4=y
CONFIG_NET_TCP=y
CONFIG_NET_LOG=y
CONFIG_NET_CONN_LOG_LEVEL_INF=y
CONFIG_NET_CONFIG_INIT_TIMEOUT=0
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_SETTINGS=y
CONFIG_FLASH_MAP=y
CONFIG_DEBUG_OPTIMIZATIONS=y

In addition, a script to receive UDP in Python is also attached. (Sorry, Japanese is used in some parts.)

import socket
import threading
import time

def receive_data():
    while True:
        data, addr = udp_socket.recvfrom(1024)
        message = data.decode()
        print(f"受信したデータ: {message}")
        print(f"送信元アドレス: {addr}")

listen_ip = ""
listen_port = 12345
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_socket.bind((listen_ip, listen_port))

receiver_thread = threading.Thread(target=receive_data)
receiver_thread.daemon = True
receiver_thread.start()

# ここでメインスレッドで他の処理を実行できます
while True:
    try:
#        print("Thread: " + str(receiver_thread.is_alive()))
        time.sleep(0.5)
        pass

    except KeyboardInterrupt:
        print('Interrupted.')
        break

The problem is that this sample project does not work on the Fanstel evaluation board.

https://www.fanstel.com/buy/ev-bt840f-evaluation-board-for-bt840f-6bk4n-98fsj-9b346

I purchased this evaluation board.

https://static1.squarespace.com/static/561459a2e4b0b39f5cefa12e/t/650f6b859c544f0ec6fc36e8/1695509382121/EVM-WM02-V6B.pdf

Here is the schematic of the Fanstel evaluation board, and as far as I can see it has the same connections as the nRF7002DK. In other words, Fanstel's evaluation board is compatible with the nRF7002DK. The only difference is that they have individual antennas instead of a common one. Hence the P1.10 GPIOs are not used on the Fanstel evaluation board.

I can't think of any reason why the Fanstel evaluation board wouldn't work. Are these two boards incompatible, even though they have the same I/O connections?

Parents
  • Hi,

     

    The Fanstel design does not have an external flash, which the nRF7002-DK has.

    If you add an overlay containing this:

    /delete-node/ &mx25r64;
    &spi4 {
    	status = "disabled";
    };

     

    It should run as expected. Could you try this and report back?

     

    Kind regards,

    Håkon

  • Thanks for your advice, and I tried. But it didn't work...

    This project can build, but the network module error is displayed when debug trace.

    *** Booting nRF Connect SDK v2.5.2 ***
    [00:00:00.566,711] <inf> net_config: Initializing network
    [00:00:00.566,741] <inf> net_config: Waiting interface 1 (0x20000720) to be up...
    [00:00:30.567,474] <inf> net_config: IPv4 address: 10.0.9.237
    [00:00:30.567,535] <inf> net_config: Running dhcpv4 client...
    [00:00:30.567,779] <err> net_config: Timeout while waiting network interface
    [00:00:30.567,810] <err> net_config: Network initialization failed (-115)

    I am sure this is not due to the device tree. Can you think of anything else? Again, it works correctly on the nRF7002DK evaluation board.

  • Hi,

     

    Here's the output I get with the fanstel DK after booting and pressing the button:

    *** Booting nRF Connect SDK v2.5.2 ***
    [00:00:00.488,677] <inf> net_config: Initializing network
    [00:00:00.488,708] <inf> net_config: Waiting interface 1 (0x20000738) to be up...
    [00:00:00.488,708] <inf> net_config: Running dhcpv4 client...
    OK
    OK
    OK
    OK
    OK
    OK
    OK
    OK
    OK
    OK
    OK
    [00:00:08.561,370] <inf> main: NET_EVENT_IPV4_DHCP_STOP
    [00:00:08.561,431] <inf> main: NET_EVENT_IPV4_DHCP_START
    [00:00:08.563,873] <inf> main: NET_EVENT_WIFI_CONNECT_RESULT
    [00:00:08.563,903] <inf> main: Connected
    [00:00:11.895,690] <inf> net_dhcpv4: Received: 192.168.32.224
    [00:00:11.895,812] <inf> main: NET_EVENT_IPV4_ADDR_ADD
    [00:00:11.895,874] <inf> net_config: IPv4 address: 192.168.32.224
    [00:00:11.895,874] <inf> net_config: Lease time: 43200 seconds
    [00:00:11.895,935] <inf> net_config: Subnet: 255.255.255.0
    [00:00:11.895,965] <inf> net_config: Router: 192.168.32.1
    [00:00:11.896,026] <inf> main: NET_EVENT_IPV4_DHCP_BOUND
    [00:00:11.896,087] <inf> main: DHCP IP address: 192.168.32.224
    ...

    Here's the .zip for your convenience. Remember to change the AP/password.

    322405.zip

     

    Kind regards,

    Håkon 

Reply
  • Hi,

     

    Here's the output I get with the fanstel DK after booting and pressing the button:

    *** Booting nRF Connect SDK v2.5.2 ***
    [00:00:00.488,677] <inf> net_config: Initializing network
    [00:00:00.488,708] <inf> net_config: Waiting interface 1 (0x20000738) to be up...
    [00:00:00.488,708] <inf> net_config: Running dhcpv4 client...
    OK
    OK
    OK
    OK
    OK
    OK
    OK
    OK
    OK
    OK
    OK
    [00:00:08.561,370] <inf> main: NET_EVENT_IPV4_DHCP_STOP
    [00:00:08.561,431] <inf> main: NET_EVENT_IPV4_DHCP_START
    [00:00:08.563,873] <inf> main: NET_EVENT_WIFI_CONNECT_RESULT
    [00:00:08.563,903] <inf> main: Connected
    [00:00:11.895,690] <inf> net_dhcpv4: Received: 192.168.32.224
    [00:00:11.895,812] <inf> main: NET_EVENT_IPV4_ADDR_ADD
    [00:00:11.895,874] <inf> net_config: IPv4 address: 192.168.32.224
    [00:00:11.895,874] <inf> net_config: Lease time: 43200 seconds
    [00:00:11.895,935] <inf> net_config: Subnet: 255.255.255.0
    [00:00:11.895,965] <inf> net_config: Router: 192.168.32.1
    [00:00:11.896,026] <inf> main: NET_EVENT_IPV4_DHCP_BOUND
    [00:00:11.896,087] <inf> main: DHCP IP address: 192.168.32.224
    ...

    Here's the .zip for your convenience. Remember to change the AP/password.

    322405.zip

     

    Kind regards,

    Håkon 

Children
Related