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 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

  • Hi Tareq,

    Thank you for providing the results of your experiments. I'll get back to you when I get new information related to this issue, probably during next week.

    Best regards,
    Dejan

  • Hi Tareq,

    We would need to investigate this issue further. Please note that looking into this issue might require longer time. I'll get back to you when I get new information. 

    Best regards,
    Dejan

  • Hi Tareq,

    Could you provide wireless sniffer capture for all experiments?

    Best regards,
    Dejan

Reply Children
  • Hi Tareq,

    Could you try using Wi-Fi Shell sample (from NCS v2.3.0) instead of STA? Please use 4 steps shown below and provide results.

    1) Compile shell sample with zperf
    2) Connect to AP
    3) Setup TWT
    4) Run UDP RX

    Best regards,
    Dejan

  • Hi Dejan,

    Thank you for your reply.

    I have used the Shell sample from NCS v2.3.0 to test the TWT with UDP Server.

    1) Compile shell sample with zperf: Done successfully

    2) Connect to AP: Done successfully
    3) Setup TWT: Done successfully with twt quick_setup 10 5000

    4) Run UDP RX: Socket creation failed!

    As you can see in the screenshoot the creation of the UDP-Socket always fails. 

    This is the case when the NCS v2.3.0 or the NCS v2.3.0-rc. But when using the same code with the NCS v2.2 the UDP Server works fine!

    Here is the code i am using for the test:

    /*
     * Copyright (c) 2022 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    /** @file
     * @brief WiFi shell sample main function
     */
    #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>
    //#include <zephyr/net/net_config.h>
    
    // For buttons and LEDs
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/drivers/gpio.h>
    
    
    
    #define PORT	 1337
    #define MAXLINE 1024
    #define IP_ADDR "192.168.178.24"
    #define Receive_Stack    1024
    
    /* size of stack area used by each thread */
    #define STACKSIZE 2048
    
    /* scheduling priority used by each thread */
    #define PRIORITY 7
    
    //STEP 1
    /* SW0_NODE is the devicetree node identifier for the node with alias "sw0" */
    #define SW0_NODE	DT_ALIAS(sw0) 
    static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);
    
    //STEP 1
    /* LED0_NODE is the devicetree node identifier for the node with alias "led0". */
    #define LED0_NODE	DT_ALIAS(led0)
    static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
    
    //Swtich_state variables struct
    typedef struct 
    {
        int state; // 1 for on, 0 for off
    } States;
    States udpSocket;
    	
    
    /* STEP 5 - Define the callback function */
    void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
    {
        gpio_pin_toggle_dt(&led);
    }	
    
    /* STEP 6 - Define a variable of type static struct gpio_callback */
    static struct gpio_callback button_cb_data;
    
    
    int send_udp_datagram(const struct shell *shell, size_t argc,
                    char *argv[]) {
    	shell_fprintf(shell, SHELL_ERROR, "Enterd Ip address: %s: \n", argv[1]);
    	
    	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) {
    	if (inet_pton(AF_INET, argv[1], &server.sin_addr) != 1) {
    		//LOG_ERR("Could not convert IP addr %s\n", IP_ADDR);
    		LOG_ERR("Could not convert IP addr %s\n", argv[1]);
    		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;
    	k_yield();
    }
    
    
    int udp_server(void) {
    	int sockfd;
    	char buffer[MAXLINE];
    	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));
    	memset(&buffer, 0, sizeof(buffer));
    	// 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);
    		// n = recv(sockfd, (char *)buffer, sizeof(buffer),
    		//  			MSG_DONTWAIT);
    		buffer[n] = '\0';
    		//printk("Message client : %s\n", buffer);
    		printk("%s\n", buffer);
    		if(buffer[0]== 'q' || gpio_pin_get_dt(&button) == 1)
    		{	
    			close(sockfd);
    			break;
    		}
    		//memset(&buffer, 0, sizeof(buffer));
    		
    			}
    		
    		printk("Close the socket\n");
    		if(udpSocket.state==0)
    		{
    			close(sockfd);
    		}
    		k_yield();
    	return 0;
    }
    
    int sett(void)
    {
    	//resceiveSwitch = 1;
    	//k_thread_resume(udp_server_tid);
    	printf("Start receive\n");
    	//udp_server(button1.state);
    	//return 0;
    	k_yield();
    }
    int unsett(void)
    {
    	//resceiveSwitch = 0;
    	//k_thread_suspend(udp_server_tid);
    	printf("what would you like me to do?\n");
    	//return 0;
    	k_yield();
    }
    
    //K_THREAD_DEFINE(send_udp_datagram_id, STACKSIZE, send_udp_datagram, NULL, NULL, NULL,PRIORITY, 0, 0);
    K_THREAD_DEFINE(udp_server_tid, STACKSIZE, udp_server, NULL, NULL, NULL,6, 0, 0);
    
    int start_udp_server_as_aThread(void)
    {	
    	udpSocket.state =1;
    	printf("Start receive\n");
    	k_thread_resume(udp_server_tid);	
    }
    int stop_udp_server_as_aThread(void)
    {	
    	udpSocket.state =0;
    	printf("Stop receive\n");
    	k_thread_suspend(udp_server_tid);
    }
    
    	
    	
    //K_THREAD_DEFINE(sett_id, STACKSIZE, sett, NULL, NULL, NULL,PRIORITY, 0, 2000);
    //K_THREAD_DEFINE(unsett_id, STACKSIZE, unsett, NULL, NULL, NULL,PRIORITY, 0, 0);
    
    void main(void)
    {	
    	k_thread_suspend(udp_server_tid);
    	
    	// #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));
    
    	// #ifdef CONFIG_NET_CONFIG_SETTINGS
    	// /* Without this, DHCPv4 starts on first interface and if that is not Wi-Fi or
    	//  * only supports IPv6, then its an issue. (E.g., OpenThread)
    	//  *
    	//  * So, we start DHCPv4 on Wi-Fi interface always, independent of the ordering.
    	//  */
    	// /* TODO: Replace device name with DTS settings later */
    	// const struct device *dev = device_get_binding("wlan0");
    
    	// net_config_init_app(dev, "Initializing network");
    	// #endif
    	
    	int ret;
    	//STEP 2
    	if (!device_is_ready(led.port)) {
    		return;
    	}
    	//STEP 2
    	if (!device_is_ready(button.port)) {
    		return;
    	}
    	//STEP 3
    	ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
    	if (ret < 0) {
    		return;
    	}
    	//STEP 3
    	ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
    	if (ret < 0) {
    		return;
    	}
    	
    
    	/* STEP 4 - Configure the interrupt on the button's pin */
    	ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE );
    
    	/* STEP 7 - Initialize the static struct gpio_callback variable   */
        gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin)); 	
    
    	/* STEP 8 - Add the callback function by calling gpio_add_callback()   */
    	 gpio_add_callback(button.port, &button_cb_data);
    
    
    	//Shell create and rigester for udp functions
    	SHELL_STATIC_SUBCMD_SET_CREATE(
            g_udp_cmds,
            SHELL_CMD_ARG(send_data, NULL,
                "Send udp message\n",
                send_udp_datagram, 0, 0),
            SHELL_CMD_ARG(recv_data, NULL,
                "Start udp receive function\n To stop the receiveing send 'q' from the client or push the Button 1",
                udp_server, 0, 0),
    			SHELL_CMD_ARG(recv_data_th, NULL,
                "start udp recv thread\n",
                start_udp_server_as_aThread, 0, 0),
    			SHELL_CMD_ARG(stop_recv_data_th, NULL,
                "stop udp recv thread\n",
                stop_udp_server_as_aThread, 0, 0),
            SHELL_SUBCMD_SET_END
            );
     
        SHELL_CMD_REGISTER(udp, &g_udp_cmds, "start or stop udp recv", NULL);
    
    #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();
    //k_yield();
    }
    
    
    
    
    
    
    
    

    prj.conf

    #
    # Copyright (c) 2022 Nordic Semiconductor ASA
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    CONFIG_WIFI=y
    CONFIG_WIFI_NRF700X=y
    
    # WPA supplicant
    CONFIG_WPA_SUPP=y
    CONFIG_NET_L2_WIFI_SHELL=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_IPV6=y
    CONFIG_NET_IPV4=y
    CONFIG_NET_UDP=y
    CONFIG_NET_TCP=y
    CONFIG_NET_DHCPV4=y
    CONFIG_DNS_RESOLVER=y
    
    CONFIG_NET_STATISTICS=y
    CONFIG_NET_STATISTICS_WIFI=y
    CONFIG_NET_STATISTICS_USER_API=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=1
    
    CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=4
    CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=5
    CONFIG_NET_MAX_CONTEXTS=5
    CONFIG_NET_CONTEXT_SYNC_RECV=y
    
    CONFIG_INIT_STACKS=y
    
    CONFIG_NET_L2_ETHERNET=y
    CONFIG_NET_SHELL=y
    
    CONFIG_NET_CONFIG_SETTINGS=y
    #CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
    #CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8::2"
    #Just temporalaly until it gets a new IP from the Wifi AP
    CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.168.188.150"
    #CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.165.100.1"
    CONFIG_NET_SOCKETS_POLL_MAX=4
    
    # Memories
    CONFIG_MAIN_STACK_SIZE=4096
    CONFIG_SHELL_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
    #CONFIG_DEBUG=y
    CONFIG_WPA_SUPP_LOG_LEVEL_INF=y
    
    # Kernel options
    CONFIG_ENTROPY_GENERATOR=y
    
    # Logging
    CONFIG_LOG=y
    CONFIG_PRINTK=y
    CONFIG_SHELL=y
    CONFIG_SHELL_GETOPT=y
    CONFIG_DEVICE_SHELL=y
    CONFIG_POSIX_CLOCK=y
    CONFIG_DATE_SHELL=y
    CONFIG_NET_CONFIG_AUTO_INIT=n
    
    CONFIG_WIFI_MGMT_EXT=y
    CONFIG_WIFI_CREDENTIALS=y
    CONFIG_WIFI_CREDENTIALS_BACKEND_SETTINGS=y
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    CONFIG_NVS=y
    CONFIG_SETTINGS=y
    CONFIG_SETTINGS_NVS=y

    Have you tested the TWT feature with udp server on the Wi-Fi Shell sample (from NCS v2.3.0)?

    Did that work successfully?

    If yes, can you provide me with the code that you have used for the test ? and also with the name of the AP that you have used in your test setup.

    Thanks in advance!

    Best regards,

    Tareq

  • Hi Tareq,

    You set CONFIG_POSIX_API=n in your prj.conf which gives default value 4 for maximum number of open file descriptors. You could try increasing maximum number of open file descriptors CONFIG_POSIX_MAX_FDS to 16 or enabling CONFIG_POSIX_API in your prj.conf.

    Best regards,
    Dejan

  • Hi Dejan,

    Thank you for your replay.

    I got this Error when setting the CONFIG_POSIX_MAX_FDS = 16

    [0/1] Re-running CMake...
    Loading Zephyr default modules (Zephyr base (cached)).
    -- Application: /home/tareq/Projects/Einvorment-test-repo/Test-shell
    -- Cache files will be written to: /home/tareq/.cache/zephyr
    -- Zephyr version: 3.2.99 (/home/tareq/ncs/v2.3.0/zephyr)
    -- Found west (found suitable version "0.14.0", minimum required is "0.7.1")
    -- Board: nrf7002dk_nrf5340_cpuapp
    -- Found host-tools: zephyr 0.15.2 (/home/tareq/ncs/toolchains/v2.3.0/opt/zephyr-sdk)
    -- Found toolchain: zephyr 0.15.2 (/home/tareq/ncs/toolchains/v2.3.0/opt/zephyr-sdk)
    -- Found BOARD.dts: /home/tareq/ncs/v2.3.0/nrf/boards/arm/nrf7002dk_nrf5340/nrf7002dk_nrf5340_cpuapp.dts
    -- Generated zephyr.dts: /home/tareq/Projects/Einvorment-test-repo/Test-shell/build/zephyr/zephyr.dts
    -- Generated devicetree_generated.h: /home/tareq/Projects/Einvorment-test-repo/Test-shell/build/zephyr/include/generated/devicetree_generated.h
    -- Including generated dts.cmake file: /home/tareq/Projects/Einvorment-test-repo/Test-shell/build/zephyr/dts.cmake
    Parsing /home/tareq/ncs/v2.3.0/zephyr/Kconfig
    Loaded configuration '/home/tareq/ncs/v2.3.0/nrf/boards/arm/nrf7002dk_nrf5340/nrf7002dk_nrf5340_cpuapp_defconfig'
    Merged configuration '/home/tareq/Projects/Einvorment-test-repo/Test-shell/prj.conf'
    Merged configuration '/home/tareq/Projects/Einvorment-test-repo/Test-shell/build/zephyr/misc/generated/extra_kconfig_options.conf'
    
    warning: Experimental symbol NET_SOCKETPAIR is enabled.
    
    
    /home/tareq/Projects/Einvorment-test-repo/Test-shell/prj.conf:22: warning: attempt to assign the value '16' to the undefined symbol POSIX_MAX_FDS 
    
    error: Aborting due to Kconfig warnings
    
    CMake Error at /home/tareq/ncs/v2.3.0/zephyr/cmake/modules/kconfig.cmake:328 (message):
      command failed with return code: 1
    Call Stack (most recent call first):
      /home/tareq/ncs/v2.3.0/nrf/cmake/modules/kconfig.cmake:29 (include)
      /home/tareq/ncs/v2.3.0/zephyr/cmake/modules/zephyr_default.cmake:108 (include)
      /home/tareq/ncs/v2.3.0/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:66 (include)
      /home/tareq/ncs/v2.3.0/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:97 (include_boilerplate)
      CMakeLists.txt:9 (find_package)
    
    
    -- Configuring incomplete, errors occurred!
    See also "/home/tareq/Projects/Einvorment-test-repo/Test-shell/build/CMakeFiles/CMakeOutput.log".
    See also "/home/tareq/Projects/Einvorment-test-repo/Test-shell/build/CMakeFiles/CMakeError.log".
    FAILED: build.ninja 
    /home/tareq/ncs/toolchains/v2.3.0/usr/local/lib/python3.8/site-packages/cmake/data/bin/cmake --regenerate-during-build -S/home/tareq/Projects/Einvorment-test-repo/Test-shell -B/home/tareq/Projects/Einvorment-test-repo/Test-shell/build
    ninja: error: rebuilding 'build.ninja': subcommand failed
    FATAL ERROR: command exited with status 1: /home/tareq/ncs/toolchains/v2.3.0/usr/local/bin/cmake --build /home/tareq/Projects/Einvorment-test-repo/Test-shell/build

    I can not enable  CONFIG_POSIX_API because when i enable it i will have to disable CONFIG_NET_SOCKETS_POSIX_NAMES which will cause a lot of errors in the code!

    Do you have another solution for that problem?

    Have you tested the TWT feature with UDP server on the Wi-Fi Shell sample (from NCS v2.3.0)?

    Did that work successfully?

    Thanks in advance!

    Best regards,

    Tareq

  • Hi Tareq,

    STA sample should now work with UDP Rx and TWT. Please have a look at TWT test with STA.

    Best regards,
    Dejan

Related