Target Wake Time (TWT) on nRF7002-DK is not working properly

Hi,

I wrote an application based on the wifi-sta sample to test the Target Wake Time (TWT) feature and measure the current consumption while the nRF7002 is in sleep mode.

My test-setup consists of one nRF7002-DK operating as "Wifi-sta" and one Fritz!Box 7530 AX operating as "Wifi-AP" and a power porfiler kit II to measure the current.

A udp-server was implemented in the application so that the station receives incoming messages from a udp-client (PC) over the Wifi 6 network created by the Wifi-AP ( Fritz!Box 7530 AX ).

The station (nRF7002-DK) was able to connect to the network and receive messages from the udp client.

But when the TWT mode is activated the station (nRF7002-DK) does not receive any messages from the udp-client .

In the next photo you can see the current consumption of the nRF7002 (PPK is connected to P23 on the DK).

As you can see the nRF7002 goes to sleep for the amount of time which was set (wifi twt setup 0 0 1 1 0 0 0 0 150 2000) which is a good indicator but the station does not receive the messages any more form the udp-client !

When i deactivate the TWT feature by (wifi twt teardown_all) the station will be able to receive messages again from the udp cleint.

So, Why cant the station receive messages when the TWT mode is active?

I also repeated the test with different settings for the TWT like:

wifi twt setup 0 0 1 1 1 1 1 1 100 2000
wifi twt setup 0 0 1 1 1 1 0 1 255 2000
wifi twt setup 0 0 1 1 1 1 0 1 255 300
wifi twt setup 1 0 1 1 1 1 0 1 255 300
wifi twt setup 1 0 1 1 0 0 0 0 255 300
wifi twt setup 2 0 1 1 1 1 0 1 200 300

But the result is the same.

No messages were received when the TWT mode is active.

I would be very thankful if you could provide me with solutions or ideas to solve this problem!

Best regards

Tareq

Parents
  • Hi Tareq,

    Could you verify that you have correct PPK2 setup as shown in power profiling?

    Have you checked if your Wi-Fi AP fully supports TWT?

    Could you provide more information about your application?

    Have you tried using "wifi twt teardown 0 0 x x" instead of "wifi twt teardown_all"?

    Best regards,
    Dejan

  • Hi Dejon
    Thank for your reply.
    I have connected the PPK2 as shown in power profiling and set the parameters of the TWT like:
    wifi twt setup 0 0 1 1 0 1 1 1 65  60000


    As you can see the current consumption is around 13.57µA when the nrf7002 is in sleep mode and around 79µA as average for the TWT-intervall 1min.
    When i try now to send messages from the computer to the station (nrf7002 dk) via UDP the station will not receive any messages!

    When i try to use "wifi twt teardown 0 0 1 1" it works. ( i mean the TWT session will be teared down)
    After that when i try again to send messages from the computer to the station (nrf7002 dk) via UDP the station will receive the messages successfully without any problems.
    This is shown in the next image:

    So, the problem is that the station does not receive the messages when the TWT is activated! Have you checked if your Wi-Fi AP fully supports TWT?
    As AP i am using the fritzbox-7590-ax https://en.avm.de/products/fritzbox/fritzbox-7590-ax/technical-specifications/
    As described in the "technical-specifications" it should support the Wi-Fi 6 (802.11ax) protocol. I i guess that means it should support the TWT feature.

    Below you can find the code of the project.

    Best regards

    Tareq

    prj.conf

    CONFIG_WIFI=y
    CONFIG_WIFI_NRF700X=y
    #CONFIG_NRF700X_REV_A=y

    # WPA supplicant
    CONFIG_WPA_SUPP=y
    CONFIG_NET_L2_WIFI_SHELL=y
    # Below configs need to be modified based on security
    CONFIG_STA_SAMPLE_SSID="wifi6test"
    CONFIG_STA_SAMPLE_PASSWORD="wifi6test"
    CONFIG_STA_KEY_MGMT_WPA2=y

    # System settings
    CONFIG_NEWLIB_LIBC=y
    CONFIG_NEWLIB_LIBC_NANO=n

    # Networking
    CONFIG_NETWORKING=y
    CONFIG_NET_SOCKETS=y
    CONFIG_POSIX_API=n
    CONFIG_NET_SOCKETS_POSIX_NAMES=y
    CONFIG_NET_LOG=y
    CONFIG_NET_IPV4=y
    CONFIG_NET_UDP=y
    CONFIG_NET_TCP=y
    CONFIG_NET_DHCPV4=y

    CONFIG_NET_PKT_RX_COUNT=8
    CONFIG_NET_PKT_TX_COUNT=8

    # Below section is the primary contributor to SRAM and is currently
    # tuned for performance, but this will be revisited in the future.
    CONFIG_NET_BUF_RX_COUNT=16
    CONFIG_NET_BUF_TX_COUNT=16
    CONFIG_NET_BUF_DATA_SIZE=128
    CONFIG_HEAP_MEM_POOL_SIZE=153600
    CONFIG_NET_TC_TX_COUNT=0

    CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=1
    CONFIG_NET_MAX_CONTEXTS=5
    CONFIG_NET_CONTEXT_SYNC_RECV=y

    CONFIG_INIT_STACKS=y

    CONFIG_NET_L2_ETHERNET=y

    CONFIG_NET_CONFIG_SETTINGS=y

    CONFIG_NET_SOCKETS_POLL_MAX=4

    # Memories
    CONFIG_MAIN_STACK_SIZE=4096
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
    CONFIG_NET_TX_STACK_SIZE=4096
    CONFIG_NET_RX_STACK_SIZE=4096

    # Debugging
    CONFIG_STACK_SENTINEL=y
    CONFIG_DEBUG_COREDUMP=y
    CONFIG_DEBUG_COREDUMP_BACKEND_LOGGING=y
    CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN=y
    CONFIG_SHELL_CMDS_RESIZE=n


    # Kernel options
    CONFIG_ENTROPY_GENERATOR=y

    # Logging
    CONFIG_LOG=y
    CONFIG_PRINTK=y
    CONFIG_POSIX_CLOCK=y

    CONFIG_NET_MGMT_EVENT_STACK_SIZE=2048
    CONFIG_SHELL=y
    CONFIG_SHELL_GETOPT=y
    CONFIG_DEVICE_SHELL=y
    CONFIG_DATE_SHELL=y
    main.c
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(sta, LOG_LEVEL_DBG);

    #include <nrfx_clock.h>
    #include <zephyr/kernel.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <zephyr/shell/shell.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/init.h>

    #include <zephyr/net/net_if.h>
    #include <zephyr/net/wifi_mgmt.h>
    #include <zephyr/net/net_event.h>


    #include <zephyr/net/socket.h>
    #include <zephyr/net/net_mgmt.h>
    #include <zephyr/net/net_ip.h>
    #include <zephyr/net/udp.h>

    #include "net_private.h"

    #define WIFI_SHELL_MODULE "wifi"

    #define WIFI_SHELL_MGMT_EVENTS (NET_EVENT_WIFI_CONNECT_RESULT |        \
                    NET_EVENT_WIFI_DISCONNECT_RESULT)

    #define MAX_SSID_LEN        32
    // IP adresse of the server(Receiver)
    #define IP_ADDR "192.168.178.22"
    #define IP_ADDR_client "192.168.178.22"
    #define IP_ADDR_server "192.168.178.21"

    static struct net_mgmt_event_callback wifi_shell_mgmt_cb;
    static struct net_mgmt_event_callback net_shell_mgmt_cb;

    static struct {
        const struct shell *sh;
        union {
            struct {
                uint8_t disconnecting    : 1;
                uint8_t _unused        : 6;
            };
            uint8_t all;
        };
    } context;

    #define PORT     1337
    #define MAXLINE 1024
        
    // Driver code
    int udp_server(void) {
        int sockfd;
        char buffer[MAXLINE];
        char *hello = "Hello from server";
        struct sockaddr_in servaddr, cliaddr;
            
        // Creating socket file descriptor
        if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
            LOG_ERR("socket creation failed");
            return -errno;
        }
            
        memset(&servaddr, 0, sizeof(servaddr));
        memset(&cliaddr, 0, sizeof(cliaddr));
            
        // Filling server information
        servaddr.sin_family = AF_INET; // IPv4
        servaddr.sin_addr.s_addr = INADDR_ANY;
        servaddr.sin_port = htons(PORT);
            
        // Bind the socket with the server address
        if ( bind(sockfd, (const struct sockaddr *)&servaddr,
                sizeof(servaddr)) < 0 )
        {
            LOG_ERR("bind failed");
            return -errno;
        }
            
        int len, n;
        
        len = sizeof(cliaddr); //len is value/result
        
        while(true) {
            n = recvfrom(sockfd, (char *)buffer, MAXLINE,
                        MSG_WAITALL, ( struct sockaddr *) &cliaddr,
                        &len);
            buffer[n] = '\0';
            printf("Client : %s\n", buffer);
            // If you want to send a response to the sender
            //sendto(sockfd, (const char *)hello, strlen(hello),0, (const struct sockaddr *) &cliaddr,&len);
            //buffer[n] = '\0';
        
        }
            
        return 0;
    }

    static int cmd_wifi_status(void)
    {
        struct net_if *iface = net_if_get_default();
        struct wifi_iface_status status = { 0 };

        if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &status,
                    sizeof(struct wifi_iface_status))) {
            printk("Status request failed\n");

            return -ENOEXEC;
        }

        printk("Status: successful\n");
        printk("==================\n");
        printk("State: %s\n", wifi_state_txt(status.state));

        if (status.state >= WIFI_STATE_ASSOCIATED) {
            uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")];

            printk("Interface Mode: %s\n",
                   wifi_mode_txt(status.iface_mode));
            printk("Link Mode: %s\n",
                   wifi_link_mode_txt(status.link_mode));
            printk("SSID: %-32s\n", status.ssid);
            printk("BSSID: %s\n",
                   net_sprint_ll_addr_buf(
                    status.bssid, WIFI_MAC_ADDR_LEN,
                    mac_string_buf, sizeof(mac_string_buf)));
            printk("Band: %s\n", wifi_band_txt(status.band));
            printk("Channel: %d\n", status.channel);
            printk("Security: %s\n", wifi_security_txt(status.security));
            printk("MFP: %s\n", wifi_mfp_txt(status.mfp));
            printk("RSSI: %d\n", status.rssi);
        }


        return 0;
    }

    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 request failed (%d)", status->status);
        } else {
            LOG_INF("Connected");
        }

        cmd_wifi_status();
    }

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

        if (context.disconnecting) {
            LOG_INF("Disconnection request %s (%d)",
                 status->status ? "failed" : "done",
                        status->status);
            context.disconnecting = false;
        } else {
            LOG_INF("Disconnected");
        }

        cmd_wifi_status();
    }

    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_CONNECT_RESULT:
            handle_wifi_connect_result(cb);
            break;
        case NET_EVENT_WIFI_DISCONNECT_RESULT:
            handle_wifi_disconnect_result(cb);
            break;
        default:
            break;
        }
    }



    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("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_DHCP_BOUND:
            print_dhcp_ip(cb);
            break;
        default:
            break;
        }
    }

    static int __wifi_args_to_params(struct wifi_connect_req_params *params)
    {
        params->timeout = SYS_FOREVER_MS;

        /* SSID */
        params->ssid = CONFIG_STA_SAMPLE_SSID;
        params->ssid_length = strlen(params->ssid);

    #if defined(CONFIG_STA_KEY_MGMT_WPA2)
        params->security = 1;
    #elif defined(CONFIG_STA_KEY_MGMT_WPA2_256)
        params->security = 2;
    #elif defined(CONFIG_STA_KEY_MGMT_WPA3)
        params->security = 3;
    #else
        params->security = 0;
    #endif

    #if !defined(CONFIG_STA_KEY_MGMT_NONE)
        params->psk = CONFIG_STA_SAMPLE_PASSWORD;
        params->psk_length = strlen(params->psk);
    #endif
        params->channel = WIFI_CHANNEL_ANY;

        /* MFP (optional) */
        params->mfp = WIFI_MFP_OPTIONAL;

        return 0;
    }

    static int wifi_connect(void)
    {
        struct net_if *iface = net_if_get_default();
        static struct wifi_connect_req_params cnx_params;

        __wifi_args_to_params(&cnx_params);

        if (net_mgmt(NET_REQUEST_WIFI_CONNECT, iface,
                 &cnx_params, sizeof(struct wifi_connect_req_params))) {
            //LOG_ERR("Connection request failed");

            return -ENOEXEC;
        }

        //LOG_INF("Connection requested");

        return 0;
    }

    static int wifi_disconnect(void)
    {
        struct net_if *iface = net_if_get_default();
        int status;

        context.disconnecting = true;

        status = net_mgmt(NET_REQUEST_WIFI_DISCONNECT, iface, NULL, 0);

        if (status) {
            context.disconnecting = false;

            if (status == -EALREADY) {
                //LOG_INF("Already disconnected");
            } else {
            //    LOG_ERR("Disconnect request failed");
                return -ENOEXEC;
            }
        } else {
            //LOG_INF("Disconnect requested");
        }

        return 0;
    }

    void main(void)
    {
        context.all = 0U;

        net_mgmt_init_event_callback(&wifi_shell_mgmt_cb,
                         wifi_mgmt_event_handler,
                         WIFI_SHELL_MGMT_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_DHCP_BOUND);

        net_mgmt_add_event_callback(&net_shell_mgmt_cb);

    #ifdef CLOCK_FEATURE_HFCLK_DIVIDE_PRESENT
        /* For now hardcode to 128MHz */
        nrfx_clock_divider_set(NRF_CLOCK_DOMAIN_HFCLK,
                       NRF_CLOCK_HFCLK_DIV_1);
    #endif
        LOG_INF("Starting %s with CPU frequency: %d MHz", CONFIG_BOARD, SystemCoreClock/MHZ(1));
        k_sleep(K_SECONDS(1));

        wifi_connect();
        udp_server();
        //send_udp_datagram();
        k_sleep(K_FOREVER);

    }
  • Hi,

    Could you provide information about the NCS version/tag which you used for testing?

    Have you tried decreasing the sleeping time of the TWT Wake Interval from specified 60 seconds to 500 ms? 

    For better visibility, when you submit code, you could use Insert->Code.

    Best regards,
    Dejan

  • Hi,

    I used the nRF Connect SDK 2.2 and the nRF Connect Toolchain 2.2.0
    Yes i have tried decreasing the sleeping time of the TWT Wake Interval from specified 60 seconds to 500 ms on less. But that did not help also!

    Have you tested the TWT feature in such example?

    I mean have you tested sending messages to nRF7002 module while TWT is active?

    What is the WiFi Access point that you have used for the test?

    Best regards,
    Tareq

  • Hi Tareq,

    UDP server is expected to work with TWT. In out tests, we were able to run UDP_RX (AP to DK) when TWT was active. We used Qualcomm and ASUS devices as access points.

    Best regards,
    Dejan

  • Hi dejans,

    I have again tested this feature with a WiFi 6 Asus access point RT-AX92U but it did not work also.
    Could you please tell me what is the ASUS device that you have used to test the TWT feature with UDP ?

    Best regards,

    Tareq

Reply Children
  • Hi Tareq,

    In order to be able to better assist you, we would need you to perform several experiments which would provide us with better understanding of your problem. After you finish with 3 experiments mentioned below, please provide the results.

    Experiment 1
    1) Connect to AP 
    2) Ping from UDP client to UDP server - 5 pings 
    3) Setup TWT 
    4) Run UDP RX


    Experiment 2
    1) Connect to AP 
    2) Create Static ARP table at both devices (# arp -s 192.168.0.65 00:50:ba:85:85:ca)    
    3) Setup TWT 
    4) Run UDP RX


    Experiment 3 
    1) Connect to AP 
    2) Run UDP RX for 10 seconds (in legacy power save) 
    3) Setup TWT 
    4) Run UDP RX


    Best regards,
    Dejan

  • Hi dejans,

    Thank you very much for your reply.

    Here are the results for the first experiment:

    1) Connect to AP : successful

    2) Ping from UDP client to UDP server - 5 pings  : successful

    3) Setup TWT : 0 0 1 1 1 1 1 1 100 500 : successful

    4) Run UDP RX : Not successful!

    The first 8 messages were received, but not the rest!

    See

    I have also tried another TWT setup and the results were like this:

    1) Connect to AP : successful

    2) Ping from UDP client to UDP server - 5 pings  : successful

    3) Setup TWT : 0 0 1 1 1 1 1 1 100 3000 : successful

    4) Run UDP RX : Not successful!

    No messages were received!

    Wait 40 sec then do wifi twt teardown 0 0 1 1

    The Messages that were sent will be received directly at once.

    See the Photos:

    1. After setting up the TWT and sending the messages:

    2. After waiting about 40 sec and then calling wifi twt teardown 0 0 1 1 

    I will be very thankful if you could help solving this problem!

    The code i am using is below.

    Best regards

    Tareq

    #
    # Copyright (c) 2022 Nordic Semiconductor ASA
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    CONFIG_WIFI=y
    CONFIG_WIFI_NRF700X=y
    #CONFIG_NRF700X_REV_A=y
    
    # WPA supplicant
    CONFIG_WPA_SUPP=y
    CONFIG_NET_L2_WIFI_SHELL=y
    # Below configs need to be modified based on security
    CONFIG_STA_SAMPLE_SSID="wifi6test"
    CONFIG_STA_SAMPLE_PASSWORD="wifi6test"
    #CONFIG_STA_SAMPLE_SSID="grandcentrix"
    #CONFIG_STA_SAMPLE_PASSWORD="multimeter"
    #CONFIG_STA_SAMPLE_SSID="iPhone"
    #CONFIG_STA_SAMPLE_PASSWORD="12345678@@"
    CONFIG_STA_KEY_MGMT_WPA2=y
    
    # System settings
    CONFIG_NEWLIB_LIBC=y
    CONFIG_NEWLIB_LIBC_NANO=n
    
    # Networking
    CONFIG_NETWORKING=y
    CONFIG_NET_SOCKETS=y
    CONFIG_POSIX_API=n
    CONFIG_NET_SOCKETS_POSIX_NAMES=y
    CONFIG_NET_LOG=y
    CONFIG_NET_IPV4=y
    CONFIG_NET_UDP=y
    CONFIG_NET_TCP=y
    CONFIG_NET_DHCPV4=y
    
    CONFIG_NET_PKT_RX_COUNT=8
    CONFIG_NET_PKT_TX_COUNT=8
    
    CONFIG_COAP=y
    #CONFIG_THINGSBOARD=y
    CONFIG_COAP_EXTENDED_OPTIONS_LEN=y
    CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE=20
    
    CONFIG_JSON_LIBRARY=y
    # Below section is the primary contributor to SRAM and is currently
    # tuned for performance, but this will be revisited in the future.
    CONFIG_NET_BUF_RX_COUNT=16
    CONFIG_NET_BUF_TX_COUNT=16
    CONFIG_NET_BUF_DATA_SIZE=128
    CONFIG_HEAP_MEM_POOL_SIZE=153600
    CONFIG_NET_TC_TX_COUNT=0
    
    CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=1
    CONFIG_NET_MAX_CONTEXTS=5
    CONFIG_NET_CONTEXT_SYNC_RECV=y
    
    CONFIG_INIT_STACKS=y
    
    CONFIG_NET_L2_ETHERNET=y
    
    CONFIG_NET_CONFIG_SETTINGS=y
    
    CONFIG_NET_SOCKETS_POLL_MAX=4
    
    # Memories
    CONFIG_MAIN_STACK_SIZE=4096
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
    CONFIG_NET_TX_STACK_SIZE=4096
    CONFIG_NET_RX_STACK_SIZE=4096
    
    # Debugging
    CONFIG_STACK_SENTINEL=y
    CONFIG_DEBUG_COREDUMP=y
    CONFIG_DEBUG_COREDUMP_BACKEND_LOGGING=y
    CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN=y
    CONFIG_SHELL_CMDS_RESIZE=n
    
    
    # Kernel options
    CONFIG_ENTROPY_GENERATOR=y
    
    # Logging
    CONFIG_LOG=y
    CONFIG_PRINTK=y
    CONFIG_POSIX_CLOCK=y
    
    CONFIG_NET_MGMT_EVENT_STACK_SIZE=2048
    CONFIG_SHELL=y
    CONFIG_SHELL_GETOPT=y
    CONFIG_DEVICE_SHELL=y
    CONFIG_DATE_SHELL=y
    
    CONFIG_NET_SHELL=y
    #CONFIG_NET_RAW_MODE=n
    CONFIG_NET_ARP=y
    
    #CONFIG_NET_MGMT_EVENT_MONITOR=y
    #CONFIG_NET_STATISTICS=y
    #CONFIG_NET_CAPTURE=y
    

  • Here is also the C code :

    /*
     * Copyright (c) 2022 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    /** @file
     * @brief WiFi station sample
     */
    
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(sta, LOG_LEVEL_DBG);
    
    #include <nrfx_clock.h>
    #include <zephyr/kernel.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <zephyr/shell/shell.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/init.h>
    
    #include <zephyr/net/net_if.h>
    #include <zephyr/net/wifi_mgmt.h>
    #include <zephyr/net/net_event.h>
    
    
    #include <zephyr/net/socket.h>
    #include <zephyr/net/net_mgmt.h>
    #include <zephyr/net/net_ip.h>
    #include <zephyr/net/udp.h>
    
    //#include <zephyr/net/net_shell.h>
    #include <sys/types.h> 
    #include "net_private.h"
    
    #define PORT	 1337
    #define MAXLINE 1024
    #define WIFI_SHELL_MODULE "wifi"
    
    #define WIFI_SHELL_MGMT_EVENTS (NET_EVENT_WIFI_CONNECT_RESULT |		\
    				NET_EVENT_WIFI_DISCONNECT_RESULT)
    
    #define MAX_SSID_LEN        32
    
    #define IP_ADDR "192.168.178.21"
    #define Receive_Stack    1024
    
    
    static struct net_mgmt_event_callback wifi_shell_mgmt_cb;
    static struct net_mgmt_event_callback net_shell_mgmt_cb;
    
    static struct {
    	const struct shell *sh;
    	union {
    		struct {
    			uint8_t disconnecting	: 1;
    			uint8_t _unused		: 6;
    		};
    		uint8_t all;
    	};
    } context;
    
    
    
    int udp_server(void) {
    
    	int sockfd;
    	char buffer[MAXLINE];
    	char *hello = "Hello";
    	struct sockaddr_in servaddr, cliaddr;
    	
    	// Creating socket file descriptor
    	if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
    		LOG_ERR("socket creation failed");
    		return -errno;
    	}
    		
    	memset(&servaddr, 0, sizeof(servaddr));
    	memset(&cliaddr, 0, sizeof(cliaddr));
    		
    	// Filling server information
    	servaddr.sin_family = AF_INET; // IPv4
    	servaddr.sin_addr.s_addr = INADDR_ANY;
    	servaddr.sin_port = htons(PORT);
    		
    	// Bind the socket with the server address
    	if ( bind(sockfd, (const struct sockaddr *)&servaddr,
    			sizeof(servaddr)) < 0 )
    	{
    		LOG_ERR("bind failed");
    		return -errno;
    	}
    		
    	int len, n;
    	len = sizeof(cliaddr); //len is value/result
    
    	while(true) {		
    		n = recvfrom(sockfd, (char *)buffer, MAXLINE,
    		 			MSG_WAITALL, ( struct sockaddr *) &cliaddr,
    		 			&len);
    		buffer[n] = '\0';
    		printf("Message client : %s\n", buffer);	
    	}
    		
    	return 0;
    }
    
    
     int send_udp_datagram(void) {
    	int err;
    	struct sockaddr_in server;
    
    	server.sin_family = AF_INET;
    	server.sin_port = htons(1337);
    	if (inet_pton(AF_INET, IP_ADDR, &server.sin_addr) != 1) {
    		LOG_ERR("Could not convert IP addr %s\n", IP_ADDR);
    		return -1;
    	}
    
    	int coap_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    	if (coap_socket < 0) {
    		LOG_ERR("Failed to create CoAP socket: %d.\n", errno);
    		return -errno;
    	}
    
    	err = connect(coap_socket, (struct sockaddr *)&server,sizeof(struct sockaddr_in));
    	if (err < 0) {
    		LOG_ERR("Failed to connect UDP socket (err %d)\n", err);
    		return err;
    	}
    
    	const char * payload = "Hello from the nRF7002";
    	
    	err = send(coap_socket, payload, strlen(payload), 0);
    	if (err < 0) {
    		LOG_ERR("Failed to send message via UDP socket (errno %d)\n", -errno);
    		return -errno;
    	}
    	
    	err = sendto(coap_socket, payload, strlen(payload),0, (struct sockaddr *)&server, sizeof(struct sockaddr_in));
    	if (err < 0) {
    		LOG_ERR("Failed to send message via UDP socket (errno %d)\n", -errno);
    		return -errno;
    	}
    	LOG_INF("Message sent");
    	
    
    	close(coap_socket);
    
    	return 0;
    }
    
    static int cmd_wifi_status(void)
    {
    	struct net_if *iface = net_if_get_default();
    	struct wifi_iface_status status = { 0 };
    
    	if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &status,
    				sizeof(struct wifi_iface_status))) {
    		printk("Status request failed\n");
    
    		return -ENOEXEC;
    	}
    
    	printk("Status: successful\n");
    	printk("==================\n");
    	printk("State: %s\n", wifi_state_txt(status.state));
    
    	if (status.state >= WIFI_STATE_ASSOCIATED) {
    		uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")];
    
    		printk("Interface Mode: %s\n",
    		       wifi_mode_txt(status.iface_mode));
    		printk("Link Mode: %s\n",
    		       wifi_link_mode_txt(status.link_mode));
    		printk("SSID: %-32s\n", status.ssid);
    		printk("BSSID: %s\n",
    		       net_sprint_ll_addr_buf(
    				status.bssid, WIFI_MAC_ADDR_LEN,
    				mac_string_buf, sizeof(mac_string_buf)));
    		printk("Band: %s\n", wifi_band_txt(status.band));
    		printk("Channel: %d\n", status.channel);
    		printk("Security: %s\n", wifi_security_txt(status.security));
    		printk("MFP: %s\n", wifi_mfp_txt(status.mfp));
    		printk("RSSI: %d\n", status.rssi);
    	}
    
    	return 0;
    }
    
    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 request failed (%d)", status->status);
    	} else {
    		LOG_INF("Connected");
    	}
    
    	cmd_wifi_status();
    }
    
    static void handle_wifi_disconnect_result(struct net_mgmt_event_callback *cb)
    {
    	const struct wifi_status *status =
    		(const struct wifi_status *) cb->info;
    
    	if (context.disconnecting) {
    		LOG_INF("Disconnection request %s (%d)",
    			 status->status ? "failed" : "done",
    					status->status);
    		context.disconnecting = false;
    	} else {
    		LOG_INF("Disconnected");
    	}
    
    	cmd_wifi_status();
    }
    
    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_CONNECT_RESULT:
    		handle_wifi_connect_result(cb);
    		break;
    	case NET_EVENT_WIFI_DISCONNECT_RESULT:
    		handle_wifi_disconnect_result(cb);
    		break;
    	default:
    		break;
    	}
    }
    
    
    
    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("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_DHCP_BOUND:
    		print_dhcp_ip(cb);
    		break;
    	default:
    		break;
    	}
    }
    
    static int __wifi_args_to_params(struct wifi_connect_req_params *params)
    {
    	params->timeout = SYS_FOREVER_MS;
    
    	/* SSID */
    	params->ssid = CONFIG_STA_SAMPLE_SSID;
    	params->ssid_length = strlen(params->ssid);
    
    #if defined(CONFIG_STA_KEY_MGMT_WPA2)
    	params->security = 1;
    #elif defined(CONFIG_STA_KEY_MGMT_WPA2_256)
    	params->security = 2;
    #elif defined(CONFIG_STA_KEY_MGMT_WPA3)
    	params->security = 3;
    #else
    	params->security = 0;
    #endif
    
    #if !defined(CONFIG_STA_KEY_MGMT_NONE)
    	params->psk = CONFIG_STA_SAMPLE_PASSWORD;
    	params->psk_length = strlen(params->psk);
    #endif
    	params->channel = WIFI_CHANNEL_ANY;
    
    	/* MFP (optional) */
    	params->mfp = WIFI_MFP_OPTIONAL;
    
    	return 0;
    }
    
    static int wifi_connect(void)
    {
    	struct net_if *iface = net_if_get_default();
    	static struct wifi_connect_req_params cnx_params;
    
    	__wifi_args_to_params(&cnx_params);
    
    	if (net_mgmt(NET_REQUEST_WIFI_CONNECT, iface,
    		     &cnx_params, sizeof(struct wifi_connect_req_params))) {
    		LOG_ERR("Connection request failed");
    
    		return -ENOEXEC;
    	}
    
    	LOG_INF("Connection requested");
    
    	return 0;
    }
    
    static int wifi_disconnect(void)
    {
    	struct net_if *iface = net_if_get_default();
    	int status;
    
    	context.disconnecting = true;
    
    	status = net_mgmt(NET_REQUEST_WIFI_DISCONNECT, iface, NULL, 0);
    
    	if (status) {
    		context.disconnecting = false;
    
    		if (status == -EALREADY) {
    			LOG_INF("Already disconnected");
    		} else {
    			LOG_ERR("Disconnect request failed");
    			return -ENOEXEC;
    		}
    	} else {
    		LOG_INF("Disconnect requested");
    	}
    
    	return 0;
    }
    
    void main(void)
    {
    
    	context.all = 0U;
    
    	net_mgmt_init_event_callback(&wifi_shell_mgmt_cb,
    				     wifi_mgmt_event_handler,
    				     WIFI_SHELL_MGMT_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_DHCP_BOUND);
    
    	net_mgmt_add_event_callback(&net_shell_mgmt_cb);
    
    #ifdef CLOCK_FEATURE_HFCLK_DIVIDE_PRESENT
    	/* For now hardcode to 128MHz */
    	nrfx_clock_divider_set(NRF_CLOCK_DOMAIN_HFCLK,
    			       NRF_CLOCK_HFCLK_DIV_1);
    #endif
    	LOG_INF("Starting %s with CPU frequency: %d MHz", CONFIG_BOARD, SystemCoreClock/MHZ(1));
    	k_sleep(K_SECONDS(1));
    
        // Start receiving messages via udp
    	udp_server();
    }

  • Hi Tareq,

    I have reported the issue internally. I'll get back to you when I get new information, hopefully during this week or the next one.

    Could you please provide the results of the other two experiments?

    Best regards,
    Dejan

  • Hi dejans,
    Thank you for your reply.

    The results for the Experiment 2
    1) Connect to AP : successful
    2) Create Static ARP table at both devices

    The command (# arp -s 192.168.0.65 00:50:ba:85:85:ca) worked on the udp-client device Laptop (ubuntu) but not on the udp-server device(nRF7002-dk). See next image:


    3) Setup TWT : successful for three variants:

    For: 0 0 1 1 1 1 1 1 100 3000

    and for: 0 0 1 1 1 1 1 1 100 15000

    and for: 0 0 1 1 1 1 1 1 100 10000

    The results were:

    For: 0 0 1 1 1 1 1 1 100 3000

    The udp-server was able to receive some of the messages but not all of them!

    See the next image:

    For: 0 0 1 1 1 1 1 1 100 15000

    The udp-server was able to receive just the second message and then no more!

    For: 0 0 1 1 1 1 1 1 100 10000

    Again the udp-server was able to receive some of the messages but not all of them until the <inf> message came. After that udp-server was not able to receive any messages.

    I've also found that there's a higher chance of receiving a message if the message is sent just before the UDP-server device wakes up.

    In this test the ncs v2.2.0 was used.

    As Wifi 6 AP the FRITZ!Box 6690 was used.

    Here is the used code:

    /* Minimal UDP+Shell source code (was tested on nRF connect sdk 2.22) 
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(codi, LOG_LEVEL_DBG);
    
    #include <nrfx_clock.h>
    #include <zephyr/kernel.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <zephyr/shell/shell.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/net/socket.h>
    
    
    #define PORT	 1337
    #define MAXLINE 1024
    #define IP_ADDR "192.168.50.54"
    #define Receive_Stack    1024
    
    
    int send_udp_datagram(void) {
    	int err;
    	struct sockaddr_in server;
    
    	server.sin_family = AF_INET;
    	server.sin_port = htons(1337);
    	if (inet_pton(AF_INET, IP_ADDR, &server.sin_addr) != 1) {
    		LOG_ERR("Could not convert IP addr %s\n", IP_ADDR);
    		return -1;
    	}
    
    	int coap_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    	if (coap_socket < 0) {
    		LOG_ERR("Failed to create CoAP socket: %d.\n", errno);
    		return -errno;
    	}
    
    	err = connect(coap_socket, (struct sockaddr *)&server,sizeof(struct sockaddr_in));
    	if (err < 0) {
    		LOG_ERR("Failed to connect UDP socket (err %d)\n", err);
    		return err;
    	}
    
    	const char * payload = "Hello from the nRF7002";
    	
    	err = send(coap_socket, payload, strlen(payload), 0);
    	if (err < 0) {
    		LOG_ERR("Failed to send message via UDP socket (errno %d)\n", -errno);
    		return -errno;
    	}
    	
    	err = sendto(coap_socket, payload, strlen(payload),0, (struct sockaddr *)&server, sizeof(struct sockaddr_in));
    	if (err < 0) {
    		LOG_ERR("Failed to send message via UDP socket (errno %d)\n", -errno);
    		return -errno;
    	}
    	LOG_INF("Message sent");
    	
    
    	close(coap_socket);
    
    	return 0;
    }
    
    
    int udp_server(void) {
    int sockfd;
    	char buffer[MAXLINE];
    	char *hello = "Hello from server";
    	struct sockaddr_in servaddr, cliaddr;
    	
    	// Creating socket file descriptor
    	if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
    		printk("socket creation failed");
    		return -errno;
    	}
    		
    	memset(&servaddr, 0, sizeof(servaddr));
    	memset(&cliaddr, 0, sizeof(cliaddr));
    	
    	// Filling server information
    	servaddr.sin_family = AF_INET; // IPv4
    	servaddr.sin_addr.s_addr = INADDR_ANY;
    	servaddr.sin_port = htons(PORT);
    	
    	// Bind the socket with the server address
    	if ( bind(sockfd, (const struct sockaddr *)&servaddr,
    			sizeof(servaddr)) < 0 )
    	{
    		printk("bind faileed");
    		return -errno;
    	}
    	
    	int len, n;
    	len = sizeof(cliaddr); //len is value/result
    
    	while(true) {		
    		n = recvfrom(sockfd, (char *)buffer, MAXLINE,
    		 			MSG_WAITALL, ( struct sockaddr *) &cliaddr,
    		 			&len);
    		buffer[n] = '\0';
    		printk("Message client : %s\n", buffer);
    			}
    		
    	return 0;
    }
    
    
    void main(void)
    {
    #ifdef CLOCK_FEATURE_HFCLK_DIVIDE_PRESENT
    	/* For now hardcode to 128MHz */
    	nrfx_clock_divider_set(NRF_CLOCK_DOMAIN_HFCLK,
    			       NRF_CLOCK_HFCLK_DIV_1);
    #endif
    	printk("Starting %s with CPU frequency: %d MHz\n", CONFIG_BOARD, SystemCoreClock/MHZ(1));
    k_sleep(K_SECONDS(1));
    send_udp_datagram();
    udp_server();
    }

    Experiment 3:

    I was not able to set the Legacy power mode on the nRF7002-dk using the ncs v2.2

    See the next image:

    So i tried to use the same code and the same configurations (prj.conf) in an new application created with ncs v3. The result was that i was able to set the legacy power mode but the creation of the udp socket was always not successful. I dont why is that. The creation of the udp socket with the same code work fine with the ncs v2.2.

    I will be thankful if you have new information that could help solve this problem.

    Best regards.

    Tareq

Related