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

  • 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