nRF7002Dk send wifi beacon on 3 channel with the samples "raw_tx_packet"

Hi Supporter:

  I want make a wifi position card with nRF7002 which support low power and fast beacon sending. 

  I evaluate it with nRF7002. 

  Now i have some problem about this(Environment:  nrf-sdk main branch, samples\wifi\raw_tx_packet):

1. i want to send the beacon on 3 channel(1,6,11) every 250ms. 

       The code:

uint8_t channel_info[3] = {6,1,11};

static void wifi_send_raw_tx_packets(void)

{......

        for (int i = 0; i < 3; i++) {
            wifi_set_channel(channel_info[i]);
            memcpy(test_frame + sizeof(struct raw_tx_pkt_header),
                   &test_beacon_frame, sizeof(test_beacon_frame));
           
            ret = sendto(sockfd, test_frame, buf_length, 0,
                    (struct sockaddr *)&sa, sizeof(sa));
            if (ret < 0) {
                LOG_ERR("Unable to send beacon frame: %s", strerror(errno));
                num_failures++;
            }

            increment_seq_control();

            k_msleep(CONFIG_RAW_TX_PACKET_SAMPLE_INTER_FRAME_DELAY_MS);
        }

}

The beacon is sending success when it slowly. But when the beacon interval update to 250ms, There have some error:

[00:01:20.487,121] [1;31m<err> wifi_nrf: umac_cmd_alloc: Failed to allocate UMAC cmd[0m
[00:01:20.487,152] [1;31m<err> wifi_nrf: nrf_wifi_fmac_set_channel: umac_cmd_alloc failed[0m
[00:01:20.487,182] [1;31m<err> wifi_nrf: nrf_wifi_channel: set channel failed[0m
[00:01:20.487,182] [1;31m<err> raw_tx_packet: Channel setting failed -1

I thought that the beacon sending is fast, not need wait so long time, ,Could you tell me if it has some better way to implement this feature.

2. The low power is 120uA when the nRF7002DK sleep. I thought that it should be lower power consumption. 

I test the current refer to the document "nRF7002_DK_User_Guide_v1.0.0.pdf". 

I get 3uA when the net shutdown refer to the sample "shutdown"(suspend the debug serial). 

Could you please tell if there have a register description document available for reference

Parents
  • Hi Jay, 
    Could you try to do a quick test of not switching the channel ? To see if you can lower CONFIG_RAW_TX_PACKET_SAMPLE_INTER_FRAME_DELAY_MS

    From the log it seems that it was not able to allocate the memory for the command at OSAL layer. 

  • Hi Hung:

    Thanks for your reply. 

    As your said, I set 

    CONFIG_RAW_TX_PACKET_SAMPLE_INTER_FRAME_DELAY_MS=10
    and not switching the channel. 
    Log details:
    [00:01:12.992,767] [1;31m<err> wifi_nrf: nrf_wifi_fmac_rawtx_done_event_process: tx done called[0m
    [00:01:13.012,023] [1;31m<err> wifi_nrf: nrf_wifi_fmac_rawtx_done_event_process: tx done called[0m
    [00:01:13.029,724] [1;31m<err> wifi_nrf: nrf_wifi_fmac_rawtx_done_event_process: tx done called[0m
    [00:01:13.029,846] [1;31m<err> wifi_nrf: nrf_wifi_fmac_rawtx_done_event_process: tx done called[0m
    [00:01:13.043,914] [1;31m<err> wifi_nrf: nrf_wifi_fmac_rawtx_done_event_process: tx done called[0m
    [00:01:13.056,884] [1;31m<err> wifi_nrf: nrf_wifi_fmac_rawtx_done_event_process: tx done called[0m
    [00:01:13.088,745] [1;31m<err> wifi_nrf: nrf_wifi_fmac_rawtx_done_event_process: tx done called[0m
    [00:01:13.090,972] [1;31m<err> wifi_nrf: nrf_wifi_fmac_rawtx_done_event_process: tx done called[0m
    [00:01:13.121,276] [1;31m<err> wifi_nrf: nrf_wifi_fmac_rawtx_done_event_process: tx done called[0m
    [00:01:13.134,246] [1;31m<err> wifi_nrf: nrf_wifi_fmac_rawtx_done_event_process: tx done called[0m
    [00:01:13.140,533] [1;31m<err> wifi_nrf: nrf_wifi_fmac_rawtx_done_event_process: tx done called[0m
    [00:01:13.142,242] [1;31m<err> wifi_nrf: nrf_wifi_fmac_rawtx_done_event_process: tx done called[0m
    It's so fast, But it is stopped at some point. It cannot resume except restart but no log output. 
    Best regards
  • Hi Jay, 
    Could you provide us the code you used in both cases, when you use channel switching and when you don't ? 

    I assume when you don't do channel switching it was working for CONFIG_RAW_TX_PACKET_SAMPLE_INTER_FRAME_DELAY_MS >10ms ? 

    We are suspecting the issue with channel switching is that it would take about 300ms for the nRF7002 to switch the channel. But I need to double check. 

  • Hi Hung,

    This is my code:

    /*
     * Copyright (c) 2023 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    /** @file
     * @brief Wi-Fi Raw Tx Packet sample
     */
    
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(raw_tx_packet, CONFIG_LOG_DEFAULT_LEVEL);
    
    #include <zephyr/net/socket.h>
    #include <zephyr/net/net_if.h>
    #include <zephyr/net/wifi_mgmt.h>
    #include <zephyr/net/net_event.h>
    #include <zephyr/net/ethernet.h>
    #include <zephyr/net/ethernet_mgmt.h>
    #include <nrf_wifi/fw_if/umac_if/inc/default/fmac_structs.h>
    
    #include "net_private.h"
    #include "wifi_connection.h"
    #include <zephyr/sys/poweroff.h>
    
    #include <nrfx.h>
    #include <hal/nrf_power.h>
    #include <zephyr/device.h>
    #include <zephyr/pm/device.h>
    #include <dk_buttons_and_leds.h>
    
    #define BEACON_PAYLOAD_LENGTH 22
    #define CONTINUOUS_MODE_TRANSMISSION 0
    #define FIXED_MODE_TRANSMISSION 1
    
    #define IEEE80211_SEQ_CTRL_SEQ_NUM_MASK 0xFFF0
    #define IEEE80211_SEQ_NUMBER_INC BIT(4) /* 0-3 is fragment number */
    void exit_shutdown_mode(void);
    void enter_shutdown_mode(void);
    struct beacon {
    	uint16_t frame_control;
    	uint16_t duration;
    	uint8_t da[6];
    	uint8_t sa[6];
    	uint8_t bssid[6];
    	uint16_t seq_ctrl;
    	uint8_t payload[BEACON_PAYLOAD_LENGTH];
    } __packed;
    
    static struct beacon test_beacon_frame = {
    	.frame_control = htons(0X8000),
    	.duration = 0X0000,
    	.da = {0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF},
    	/* Transmitter Address: A0:69:60:E3:52:15 */
    	.sa = {0x68, 0xcc, 0x9c, 0x04, 0x05, 0x06},
    	.bssid = {0x68, 0xcc, 0x9c, 0x04, 0x05, 0x06},
    	.seq_ctrl = 0X4000,
    	/* SSID: NRF_RAW_TX_PACKET_APP */
    	.payload = {
    		0X0C, 0XA2, 0X28, 0X00, 0X00, 0X00, 0X00, 0X00, 0xD0, 0x07,
    		0x02, 0x00, 0x7f, 0x08, 0x24, 0x01, 0x00, 0x04, 0x10, 0x00, 
    		0x00, 0x00
    	}
    };
    
    #ifdef CONFIG_RAW_TX_PACKET_SAMPLE_NON_CONNECTED_MODE
    typedef enum {
    	MSG_TIMER = 0,
    	MSG_BUTTON,
    	MSG_TRIGGER
    }MSG_TYPE;
    
    typedef struct {
    	MSG_TYPE msg_type;
    	uint8_t content[5];
    }data_msg_type_t;
    
    K_MSGQ_DEFINE(my_msgq, sizeof(data_msg_type_t), 10, 4);
    
    static void wifi_set_channel(uint8_t channel)
    {
    	struct net_if *iface;
    	struct wifi_channel_info channel_info = {0};
    	int ret;
    
    	channel_info.oper = WIFI_MGMT_SET;
    
    	iface = net_if_get_first_wifi();
    	if (iface == NULL) {
    		LOG_ERR("Failed to get Wi-Fi iface");
    		return;
    	}
    
    	channel_info.if_index = net_if_get_by_iface(iface);
    	//channel_info.channel = CONFIG_RAW_TX_PACKET_SAMPLE_CHANNEL;
    	channel_info.channel = channel;
    	if ((channel_info.channel < WIFI_CHANNEL_MIN) ||
    		   (channel_info.channel > WIFI_CHANNEL_MAX)) {
    		LOG_ERR("Invalid channel number. Range is (1-233)");
    		return;
    	}
    
    	ret = net_mgmt(NET_REQUEST_WIFI_CHANNEL, iface,
    		       &channel_info, sizeof(channel_info));
    	if (ret) {
    		LOG_ERR(" Channel setting failed %d\n", ret);
    			return;
    	}
    
    	LOG_INF("Wi-Fi channel set to %d", channel_info.channel);
    }
    #endif
    
    static void wifi_set_mode(int mode_val)
    {
    	int ret;
    	struct net_if *iface = NULL;
    	struct wifi_mode_info mode_info = {0};
    
    	mode_info.oper = WIFI_MGMT_SET;
    
    	iface = net_if_get_first_wifi();
    	if (iface == NULL) {
    		LOG_ERR("Failed to get Wi-Fi iface");
    		return;
    	}
    
    	mode_info.if_index = net_if_get_by_iface(iface);
    	mode_info.mode = mode_val;
    
    	ret = net_mgmt(NET_REQUEST_WIFI_MODE, iface, &mode_info, sizeof(mode_info));
    	if (ret) {
    		LOG_ERR("Mode setting failed %d", ret);
    	}
    }
    
    static int setup_raw_pkt_socket(int *sockfd, struct sockaddr_ll *sa)
    {
    	struct net_if *iface = NULL;
    	int ret;
    
    	*sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
    	if (*sockfd < 0) {
    		LOG_ERR("Unable to create a socket %d", errno);
    		return -1;
    	}
    
    	iface = net_if_get_first_wifi();
    	if (!iface) {
    		LOG_ERR("Failed to get Wi-Fi interface");
    		return -1;
    	}
    
    	sa->sll_family = AF_PACKET;
    	sa->sll_ifindex = net_if_get_by_iface(iface);
    
    	/* Bind the socket */
    	ret = bind(*sockfd, (struct sockaddr *)sa, sizeof(struct sockaddr_ll));
    	if (ret < 0) {
    		LOG_ERR("Error: Unable to bind socket to the network interface:%s",
    			strerror(errno));
    		close(*sockfd);
    		return -1;
    	}
    
    	return 0;
    }
    
    static void fill_raw_tx_pkt_hdr(struct raw_tx_pkt_header *raw_tx_pkt)
    {
    	/* Raw Tx Packet header */
    	raw_tx_pkt->magic_num = NRF_WIFI_MAGIC_NUM_RAWTX;
    	raw_tx_pkt->data_rate = CONFIG_RAW_TX_PACKET_SAMPLE_RATE_VALUE;
    	raw_tx_pkt->packet_length = sizeof(test_beacon_frame);
    	raw_tx_pkt->tx_mode = CONFIG_RAW_TX_PACKET_SAMPLE_RATE_FLAGS;
    	raw_tx_pkt->queue = CONFIG_RAW_TX_PACKET_SAMPLE_QUEUE_NUM;
    	/* The byte is reserved and used by the driver */
    	raw_tx_pkt->raw_tx_flag = 0;
    }
    
    int wifi_send_raw_tx_pkt(int sockfd, char *test_frame,
    			size_t buf_length, struct sockaddr_ll *sa)
    {
    	return sendto(sockfd, test_frame, buf_length, 0,
    			(struct sockaddr *)sa, sizeof(*sa));
    }
    
    static int get_pkt_transmit_count(unsigned int *mode_of_transmission,
    					unsigned int *num_tx_pkts)
    {
    #ifdef CONFIG_RAW_TX_PACKET_SAMPLE_TRANSMISSION_MODE_FIXED
    	*mode_of_transmission = 1;
    	*num_tx_pkts = CONFIG_RAW_TX_PACKET_SAMPLE_FIXED_NUM_PACKETS;
    	if (*num_tx_pkts == 0) {
    		LOG_ERR("Can't send %d number of raw tx packets", *num_tx_pkts);
    		return -1;
    	}
    	LOG_INF("Sending %d number of raw tx packets", *num_tx_pkts);
    #else
    	*mode_of_transmission = 0;
    	*num_tx_pkts = UINT_MAX;
    	//*num_tx_pkts = 1;
    	LOG_INF("Sending raw tx packets continuously");
    #endif
    	return 0;
    }
    
    static void increment_seq_control(void)
    {
    	test_beacon_frame.seq_ctrl = (test_beacon_frame.seq_ctrl +
    				      IEEE80211_SEQ_NUMBER_INC) &
    				      IEEE80211_SEQ_CTRL_SEQ_NUM_MASK;
    	if (test_beacon_frame.seq_ctrl > IEEE80211_SEQ_CTRL_SEQ_NUM_MASK) {
    		test_beacon_frame.seq_ctrl = 0X0010;
    	}
    }
    
    uint8_t channel_info[3] = {6,1,11};
    static void wifi_send_raw_tx_packets(void)
    {
    	struct sockaddr_ll sa;
    	int sockfd, ret;
    	struct raw_tx_pkt_header packet;
    	char *test_frame = NULL;
    	unsigned int buf_length, num_pkts, transmission_mode, num_failures = 0;
    
    	ret = setup_raw_pkt_socket(&sockfd, &sa);
    	if (ret < 0) {
    		LOG_ERR("Setting socket for raw pkt transmission failed %d", errno);
    		return;
    	}
    
    	fill_raw_tx_pkt_hdr(&packet);
    
    	ret = get_pkt_transmit_count(&transmission_mode, &num_pkts);
    	if (ret < 0) {
    		close(sockfd);
    		return;
    	}
    
    	test_frame = malloc(sizeof(struct raw_tx_pkt_header) + sizeof(test_beacon_frame));
    	if (!test_frame) {
    		LOG_ERR("Malloc failed for send buffer %d", errno);
    		return;
    	}
    
    	buf_length = sizeof(struct raw_tx_pkt_header) + sizeof(test_beacon_frame);
    	memcpy(test_frame, &packet, sizeof(struct raw_tx_pkt_header));
    	num_pkts = sizeof(channel_info);
    	LOG_INF("This is raw socket length:%d\r\n", buf_length);
    	if (num_pkts == 1) {
    		memcpy(test_frame + sizeof(struct raw_tx_pkt_header),
    		       &test_beacon_frame, sizeof(test_beacon_frame));
    
    		ret = wifi_send_raw_tx_pkt(sockfd, test_frame, buf_length, &sa);
    		if (ret < 0) {
    			LOG_ERR("Unable to send beacon frame: %s", strerror(errno));
    			close(sockfd);
    			free(test_frame);
    			return;
    		}
    	} else {
    		for (int i = 0; i < num_pkts; i++) {
    			wifi_set_channel(channel_info[i]);
    			test_beacon_frame.payload[15] = channel_info[i];
    			memcpy(test_frame + sizeof(struct raw_tx_pkt_header),
    			       &test_beacon_frame, sizeof(test_beacon_frame));
    			
    			ret = sendto(sockfd, test_frame, buf_length, 0,
    					(struct sockaddr *)&sa, sizeof(sa));
    			if (ret < 0) {
    				LOG_ERR("Unable to send beacon frame: %s", strerror(errno));
    				num_failures++;
    			}
    
    			increment_seq_control();
    
    			k_msleep(CONFIG_RAW_TX_PACKET_SAMPLE_INTER_FRAME_DELAY_MS);
    		}
    	}
    
    	LOG_INF("Sent %d packets with %d failures", num_pkts, num_failures);
    
    	/* close the socket */
    	close(sockfd);
    	free(test_frame);
    }
    
    static bool is_mac_addr_set(struct net_if *iface)
    {
    	struct net_linkaddr *linkaddr = net_if_get_link_addr(iface);
    	struct net_eth_addr wifi_addr;
    
    	if (!linkaddr || linkaddr->len != WIFI_MAC_ADDR_LEN) {
    		return false;
    	}
    
    	memcpy(wifi_addr.addr, linkaddr->addr, WIFI_MAC_ADDR_LEN);
    
    	return net_eth_is_addr_valid(&wifi_addr);
    }
    
    static void button_handler_cb(uint32_t button_state, uint32_t has_changed)
    {
    	data_msg_type_t data_msg;
    	int mode = BIT(0) | BIT(2);
    	if ((has_changed & DK_BTN1_MSK) && (button_state & DK_BTN1_MSK)) {
    		data_msg.msg_type = MSG_BUTTON;
    		while (k_msgq_put(&my_msgq, &data_msg, K_NO_WAIT) != 0) {
                /* message queue is full: purge old data & try again */
                k_msgq_purge(&my_msgq);
            }
    	} else if ((has_changed & DK_BTN2_MSK) && (button_state & DK_BTN2_MSK)) {
    		//enter_shutdown_mode();
    	}
    }
    
    static void buttons_init(void)
    {
    	int err;
    
    	err = dk_buttons_init(button_handler_cb);
    	if (err) {
    		LOG_ERR("Buttons initialization failed.\n");
    		return;
    	}
    }
    
    int shutdown_wifi(struct net_if *iface)
    {
    	int ret;
    
    	if (!net_if_is_admin_up(iface)) {
    		return 0;
    	}
    
    	ret = net_if_down(iface);
    	if (ret) {
    		LOG_ERR("Cannot bring down iface (%d)", ret);
    		return ret;
    	}
    
    	LOG_INF("Interface down");
    
    	return 0;
    }
    
    static int wifi_scan(void)
    {
    	struct net_if *iface = net_if_get_default();
    
    	if (net_mgmt(NET_REQUEST_WIFI_SCAN, iface, NULL, 0)) {
    		LOG_ERR("Scan request failed");
    
    		return -ENOEXEC;
    	}
    
    	LOG_INF("Scan requested\n");
    
    	//k_sem_take(&scan_sem, K_MSEC(SCAN_TIMEOUT_MS));
    
    	return 0;
    }
    
    int startup_wifi(struct net_if *iface)
    {
    	int ret;
    
    	if (!net_if_is_admin_up(iface)) {
    		ret = net_if_up(iface);
    		if (ret) {
    			LOG_ERR("Cannot bring up iface (%d)", ret);
    			return ret;
    		}
    
    		LOG_INF("Interface up");
    	}
    	struct wifi_ps_params params = { 0 };
    	params.enabled = WIFI_PS_ENABLED;
    	params.type = WIFI_PS_PARAM_STATE;
    	if (net_mgmt(NET_REQUEST_WIFI_PS, iface, &params, sizeof(params))) {
    		LOG_ERR("PS %s failed. Reason: %s\n",
    			      params.enabled ? "enable" : "disable",
    			      wifi_ps_get_config_err_code_str(params.fail_reason));
    		return;
    	}
    	//wifi_scan();
    	return 0;
    }
    
    
    void enter_shutdown_mode(void)
    {
    	int mode;
    	struct net_if *iface = net_if_get_first_wifi();
    	if (!iface) {
    		LOG_ERR("Failed to get Wi-Fi iface");
    		return;
    	}
    	mode = BIT(0);
    	wifi_set_mode(mode);
    	
    	//net_if_suspend(iface);
    /*	
    	struct wifi_ps_params params = { 0 };
    	params.enabled = WIFI_PS_ENABLED;
    	params.type = WIFI_PS_PARAM_STATE;
    	if (net_mgmt(NET_REQUEST_WIFI_PS, iface, &params, sizeof(params))) {
    		LOG_ERR("PS %s failed. Reason: %s\n",
    			      params.enabled ? "enable" : "disable",
    			      wifi_ps_get_config_err_code_str(params.fail_reason));
    		return;
    	}*/
    	shutdown_wifi(iface);
    }
    
    void exit_shutdown_mode(void)
    {
    	struct net_if *iface = net_if_get_default();
    
    	startup_wifi(iface);
    }
    
    void set_console_state(bool enabled)
    {
    	const struct device *cons = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
    	if (!device_is_ready(cons)) {
    		return 1;
    	}
    	if(enabled)
    		pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME);
    	else{
    		pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND);
    	}
    }
    
    
    static void timeout_handler(struct k_timer *timer_id);
    static K_TIMER_DEFINE(timer, timeout_handler, NULL);
    
    static void timeout_handler(struct k_timer *timer_id)
    {
    	data_msg_type_t data_msg;
    	data_msg.msg_type = MSG_TIMER;
    	while (k_msgq_put(&my_msgq, &data_msg, K_NO_WAIT) != 0) {
            /* message queue is full: purge old data & try again */
            k_msgq_purge(&my_msgq);
        }
    }
    
    #define CONFIG_WIFI_MAC_ADDRESS "68:cc:9c:04:05:06"
    int main(void)
    {
    	int mode;
    	data_msg_type_t data_msg;
    #ifdef CONFIG_RAW_TX_PACKET_SAMPLE_STA_ONLY_MODE
    	mode = BIT(0);
    #elif CONFIG_RAW_TX_PACKET_SAMPLE_STA_TX_INJECTION_MODE
    	mode = BIT(0) | BIT(2);
    #endif
    	
    #ifdef CONFIG_RAW_TX_PACKET_SAMPLE_CONNECTION_MODE
    	int status;
    
    	status = try_wifi_connect();
    	if (status < 0) {
    		return status;
    	}
    #else
    	
    #endif
    	buttons_init();
    	wifi_set_mode(mode);
    	k_timer_start(&timer, K_NO_WAIT, K_MSEC(250));
    	while(1)
    	{
    		//set_console_state(0);
    		if(k_msgq_get(&my_msgq, &data_msg, K_FOREVER) == 0)
    		{
    			//wifi_set_mode(mode);
    			wifi_send_raw_tx_packets();
    		}
    		//sys_poweroff();
    	}
    	return 0;
    }
    

    It is modified based on raw_tx_packet.  

    q: I assume when you don't do channel switching it was working for CONFIG_RAW_TX_PACKET_SAMPLE_INTER_FRAME_DELAY_MS >10ms ? (CONFIG_RAW_TX_PACKET_SAMPLE_INTER_FRAME_DELAY_MS = 10ms when don't switching the channel)

    Best regards

Reply
  • Hi Hung,

    This is my code:

    /*
     * Copyright (c) 2023 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    /** @file
     * @brief Wi-Fi Raw Tx Packet sample
     */
    
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(raw_tx_packet, CONFIG_LOG_DEFAULT_LEVEL);
    
    #include <zephyr/net/socket.h>
    #include <zephyr/net/net_if.h>
    #include <zephyr/net/wifi_mgmt.h>
    #include <zephyr/net/net_event.h>
    #include <zephyr/net/ethernet.h>
    #include <zephyr/net/ethernet_mgmt.h>
    #include <nrf_wifi/fw_if/umac_if/inc/default/fmac_structs.h>
    
    #include "net_private.h"
    #include "wifi_connection.h"
    #include <zephyr/sys/poweroff.h>
    
    #include <nrfx.h>
    #include <hal/nrf_power.h>
    #include <zephyr/device.h>
    #include <zephyr/pm/device.h>
    #include <dk_buttons_and_leds.h>
    
    #define BEACON_PAYLOAD_LENGTH 22
    #define CONTINUOUS_MODE_TRANSMISSION 0
    #define FIXED_MODE_TRANSMISSION 1
    
    #define IEEE80211_SEQ_CTRL_SEQ_NUM_MASK 0xFFF0
    #define IEEE80211_SEQ_NUMBER_INC BIT(4) /* 0-3 is fragment number */
    void exit_shutdown_mode(void);
    void enter_shutdown_mode(void);
    struct beacon {
    	uint16_t frame_control;
    	uint16_t duration;
    	uint8_t da[6];
    	uint8_t sa[6];
    	uint8_t bssid[6];
    	uint16_t seq_ctrl;
    	uint8_t payload[BEACON_PAYLOAD_LENGTH];
    } __packed;
    
    static struct beacon test_beacon_frame = {
    	.frame_control = htons(0X8000),
    	.duration = 0X0000,
    	.da = {0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF},
    	/* Transmitter Address: A0:69:60:E3:52:15 */
    	.sa = {0x68, 0xcc, 0x9c, 0x04, 0x05, 0x06},
    	.bssid = {0x68, 0xcc, 0x9c, 0x04, 0x05, 0x06},
    	.seq_ctrl = 0X4000,
    	/* SSID: NRF_RAW_TX_PACKET_APP */
    	.payload = {
    		0X0C, 0XA2, 0X28, 0X00, 0X00, 0X00, 0X00, 0X00, 0xD0, 0x07,
    		0x02, 0x00, 0x7f, 0x08, 0x24, 0x01, 0x00, 0x04, 0x10, 0x00, 
    		0x00, 0x00
    	}
    };
    
    #ifdef CONFIG_RAW_TX_PACKET_SAMPLE_NON_CONNECTED_MODE
    typedef enum {
    	MSG_TIMER = 0,
    	MSG_BUTTON,
    	MSG_TRIGGER
    }MSG_TYPE;
    
    typedef struct {
    	MSG_TYPE msg_type;
    	uint8_t content[5];
    }data_msg_type_t;
    
    K_MSGQ_DEFINE(my_msgq, sizeof(data_msg_type_t), 10, 4);
    
    static void wifi_set_channel(uint8_t channel)
    {
    	struct net_if *iface;
    	struct wifi_channel_info channel_info = {0};
    	int ret;
    
    	channel_info.oper = WIFI_MGMT_SET;
    
    	iface = net_if_get_first_wifi();
    	if (iface == NULL) {
    		LOG_ERR("Failed to get Wi-Fi iface");
    		return;
    	}
    
    	channel_info.if_index = net_if_get_by_iface(iface);
    	//channel_info.channel = CONFIG_RAW_TX_PACKET_SAMPLE_CHANNEL;
    	channel_info.channel = channel;
    	if ((channel_info.channel < WIFI_CHANNEL_MIN) ||
    		   (channel_info.channel > WIFI_CHANNEL_MAX)) {
    		LOG_ERR("Invalid channel number. Range is (1-233)");
    		return;
    	}
    
    	ret = net_mgmt(NET_REQUEST_WIFI_CHANNEL, iface,
    		       &channel_info, sizeof(channel_info));
    	if (ret) {
    		LOG_ERR(" Channel setting failed %d\n", ret);
    			return;
    	}
    
    	LOG_INF("Wi-Fi channel set to %d", channel_info.channel);
    }
    #endif
    
    static void wifi_set_mode(int mode_val)
    {
    	int ret;
    	struct net_if *iface = NULL;
    	struct wifi_mode_info mode_info = {0};
    
    	mode_info.oper = WIFI_MGMT_SET;
    
    	iface = net_if_get_first_wifi();
    	if (iface == NULL) {
    		LOG_ERR("Failed to get Wi-Fi iface");
    		return;
    	}
    
    	mode_info.if_index = net_if_get_by_iface(iface);
    	mode_info.mode = mode_val;
    
    	ret = net_mgmt(NET_REQUEST_WIFI_MODE, iface, &mode_info, sizeof(mode_info));
    	if (ret) {
    		LOG_ERR("Mode setting failed %d", ret);
    	}
    }
    
    static int setup_raw_pkt_socket(int *sockfd, struct sockaddr_ll *sa)
    {
    	struct net_if *iface = NULL;
    	int ret;
    
    	*sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
    	if (*sockfd < 0) {
    		LOG_ERR("Unable to create a socket %d", errno);
    		return -1;
    	}
    
    	iface = net_if_get_first_wifi();
    	if (!iface) {
    		LOG_ERR("Failed to get Wi-Fi interface");
    		return -1;
    	}
    
    	sa->sll_family = AF_PACKET;
    	sa->sll_ifindex = net_if_get_by_iface(iface);
    
    	/* Bind the socket */
    	ret = bind(*sockfd, (struct sockaddr *)sa, sizeof(struct sockaddr_ll));
    	if (ret < 0) {
    		LOG_ERR("Error: Unable to bind socket to the network interface:%s",
    			strerror(errno));
    		close(*sockfd);
    		return -1;
    	}
    
    	return 0;
    }
    
    static void fill_raw_tx_pkt_hdr(struct raw_tx_pkt_header *raw_tx_pkt)
    {
    	/* Raw Tx Packet header */
    	raw_tx_pkt->magic_num = NRF_WIFI_MAGIC_NUM_RAWTX;
    	raw_tx_pkt->data_rate = CONFIG_RAW_TX_PACKET_SAMPLE_RATE_VALUE;
    	raw_tx_pkt->packet_length = sizeof(test_beacon_frame);
    	raw_tx_pkt->tx_mode = CONFIG_RAW_TX_PACKET_SAMPLE_RATE_FLAGS;
    	raw_tx_pkt->queue = CONFIG_RAW_TX_PACKET_SAMPLE_QUEUE_NUM;
    	/* The byte is reserved and used by the driver */
    	raw_tx_pkt->raw_tx_flag = 0;
    }
    
    int wifi_send_raw_tx_pkt(int sockfd, char *test_frame,
    			size_t buf_length, struct sockaddr_ll *sa)
    {
    	return sendto(sockfd, test_frame, buf_length, 0,
    			(struct sockaddr *)sa, sizeof(*sa));
    }
    
    static int get_pkt_transmit_count(unsigned int *mode_of_transmission,
    					unsigned int *num_tx_pkts)
    {
    #ifdef CONFIG_RAW_TX_PACKET_SAMPLE_TRANSMISSION_MODE_FIXED
    	*mode_of_transmission = 1;
    	*num_tx_pkts = CONFIG_RAW_TX_PACKET_SAMPLE_FIXED_NUM_PACKETS;
    	if (*num_tx_pkts == 0) {
    		LOG_ERR("Can't send %d number of raw tx packets", *num_tx_pkts);
    		return -1;
    	}
    	LOG_INF("Sending %d number of raw tx packets", *num_tx_pkts);
    #else
    	*mode_of_transmission = 0;
    	*num_tx_pkts = UINT_MAX;
    	//*num_tx_pkts = 1;
    	LOG_INF("Sending raw tx packets continuously");
    #endif
    	return 0;
    }
    
    static void increment_seq_control(void)
    {
    	test_beacon_frame.seq_ctrl = (test_beacon_frame.seq_ctrl +
    				      IEEE80211_SEQ_NUMBER_INC) &
    				      IEEE80211_SEQ_CTRL_SEQ_NUM_MASK;
    	if (test_beacon_frame.seq_ctrl > IEEE80211_SEQ_CTRL_SEQ_NUM_MASK) {
    		test_beacon_frame.seq_ctrl = 0X0010;
    	}
    }
    
    uint8_t channel_info[3] = {6,1,11};
    static void wifi_send_raw_tx_packets(void)
    {
    	struct sockaddr_ll sa;
    	int sockfd, ret;
    	struct raw_tx_pkt_header packet;
    	char *test_frame = NULL;
    	unsigned int buf_length, num_pkts, transmission_mode, num_failures = 0;
    
    	ret = setup_raw_pkt_socket(&sockfd, &sa);
    	if (ret < 0) {
    		LOG_ERR("Setting socket for raw pkt transmission failed %d", errno);
    		return;
    	}
    
    	fill_raw_tx_pkt_hdr(&packet);
    
    	ret = get_pkt_transmit_count(&transmission_mode, &num_pkts);
    	if (ret < 0) {
    		close(sockfd);
    		return;
    	}
    
    	test_frame = malloc(sizeof(struct raw_tx_pkt_header) + sizeof(test_beacon_frame));
    	if (!test_frame) {
    		LOG_ERR("Malloc failed for send buffer %d", errno);
    		return;
    	}
    
    	buf_length = sizeof(struct raw_tx_pkt_header) + sizeof(test_beacon_frame);
    	memcpy(test_frame, &packet, sizeof(struct raw_tx_pkt_header));
    	num_pkts = sizeof(channel_info);
    	LOG_INF("This is raw socket length:%d\r\n", buf_length);
    	if (num_pkts == 1) {
    		memcpy(test_frame + sizeof(struct raw_tx_pkt_header),
    		       &test_beacon_frame, sizeof(test_beacon_frame));
    
    		ret = wifi_send_raw_tx_pkt(sockfd, test_frame, buf_length, &sa);
    		if (ret < 0) {
    			LOG_ERR("Unable to send beacon frame: %s", strerror(errno));
    			close(sockfd);
    			free(test_frame);
    			return;
    		}
    	} else {
    		for (int i = 0; i < num_pkts; i++) {
    			wifi_set_channel(channel_info[i]);
    			test_beacon_frame.payload[15] = channel_info[i];
    			memcpy(test_frame + sizeof(struct raw_tx_pkt_header),
    			       &test_beacon_frame, sizeof(test_beacon_frame));
    			
    			ret = sendto(sockfd, test_frame, buf_length, 0,
    					(struct sockaddr *)&sa, sizeof(sa));
    			if (ret < 0) {
    				LOG_ERR("Unable to send beacon frame: %s", strerror(errno));
    				num_failures++;
    			}
    
    			increment_seq_control();
    
    			k_msleep(CONFIG_RAW_TX_PACKET_SAMPLE_INTER_FRAME_DELAY_MS);
    		}
    	}
    
    	LOG_INF("Sent %d packets with %d failures", num_pkts, num_failures);
    
    	/* close the socket */
    	close(sockfd);
    	free(test_frame);
    }
    
    static bool is_mac_addr_set(struct net_if *iface)
    {
    	struct net_linkaddr *linkaddr = net_if_get_link_addr(iface);
    	struct net_eth_addr wifi_addr;
    
    	if (!linkaddr || linkaddr->len != WIFI_MAC_ADDR_LEN) {
    		return false;
    	}
    
    	memcpy(wifi_addr.addr, linkaddr->addr, WIFI_MAC_ADDR_LEN);
    
    	return net_eth_is_addr_valid(&wifi_addr);
    }
    
    static void button_handler_cb(uint32_t button_state, uint32_t has_changed)
    {
    	data_msg_type_t data_msg;
    	int mode = BIT(0) | BIT(2);
    	if ((has_changed & DK_BTN1_MSK) && (button_state & DK_BTN1_MSK)) {
    		data_msg.msg_type = MSG_BUTTON;
    		while (k_msgq_put(&my_msgq, &data_msg, K_NO_WAIT) != 0) {
                /* message queue is full: purge old data & try again */
                k_msgq_purge(&my_msgq);
            }
    	} else if ((has_changed & DK_BTN2_MSK) && (button_state & DK_BTN2_MSK)) {
    		//enter_shutdown_mode();
    	}
    }
    
    static void buttons_init(void)
    {
    	int err;
    
    	err = dk_buttons_init(button_handler_cb);
    	if (err) {
    		LOG_ERR("Buttons initialization failed.\n");
    		return;
    	}
    }
    
    int shutdown_wifi(struct net_if *iface)
    {
    	int ret;
    
    	if (!net_if_is_admin_up(iface)) {
    		return 0;
    	}
    
    	ret = net_if_down(iface);
    	if (ret) {
    		LOG_ERR("Cannot bring down iface (%d)", ret);
    		return ret;
    	}
    
    	LOG_INF("Interface down");
    
    	return 0;
    }
    
    static int wifi_scan(void)
    {
    	struct net_if *iface = net_if_get_default();
    
    	if (net_mgmt(NET_REQUEST_WIFI_SCAN, iface, NULL, 0)) {
    		LOG_ERR("Scan request failed");
    
    		return -ENOEXEC;
    	}
    
    	LOG_INF("Scan requested\n");
    
    	//k_sem_take(&scan_sem, K_MSEC(SCAN_TIMEOUT_MS));
    
    	return 0;
    }
    
    int startup_wifi(struct net_if *iface)
    {
    	int ret;
    
    	if (!net_if_is_admin_up(iface)) {
    		ret = net_if_up(iface);
    		if (ret) {
    			LOG_ERR("Cannot bring up iface (%d)", ret);
    			return ret;
    		}
    
    		LOG_INF("Interface up");
    	}
    	struct wifi_ps_params params = { 0 };
    	params.enabled = WIFI_PS_ENABLED;
    	params.type = WIFI_PS_PARAM_STATE;
    	if (net_mgmt(NET_REQUEST_WIFI_PS, iface, &params, sizeof(params))) {
    		LOG_ERR("PS %s failed. Reason: %s\n",
    			      params.enabled ? "enable" : "disable",
    			      wifi_ps_get_config_err_code_str(params.fail_reason));
    		return;
    	}
    	//wifi_scan();
    	return 0;
    }
    
    
    void enter_shutdown_mode(void)
    {
    	int mode;
    	struct net_if *iface = net_if_get_first_wifi();
    	if (!iface) {
    		LOG_ERR("Failed to get Wi-Fi iface");
    		return;
    	}
    	mode = BIT(0);
    	wifi_set_mode(mode);
    	
    	//net_if_suspend(iface);
    /*	
    	struct wifi_ps_params params = { 0 };
    	params.enabled = WIFI_PS_ENABLED;
    	params.type = WIFI_PS_PARAM_STATE;
    	if (net_mgmt(NET_REQUEST_WIFI_PS, iface, &params, sizeof(params))) {
    		LOG_ERR("PS %s failed. Reason: %s\n",
    			      params.enabled ? "enable" : "disable",
    			      wifi_ps_get_config_err_code_str(params.fail_reason));
    		return;
    	}*/
    	shutdown_wifi(iface);
    }
    
    void exit_shutdown_mode(void)
    {
    	struct net_if *iface = net_if_get_default();
    
    	startup_wifi(iface);
    }
    
    void set_console_state(bool enabled)
    {
    	const struct device *cons = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
    	if (!device_is_ready(cons)) {
    		return 1;
    	}
    	if(enabled)
    		pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME);
    	else{
    		pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND);
    	}
    }
    
    
    static void timeout_handler(struct k_timer *timer_id);
    static K_TIMER_DEFINE(timer, timeout_handler, NULL);
    
    static void timeout_handler(struct k_timer *timer_id)
    {
    	data_msg_type_t data_msg;
    	data_msg.msg_type = MSG_TIMER;
    	while (k_msgq_put(&my_msgq, &data_msg, K_NO_WAIT) != 0) {
            /* message queue is full: purge old data & try again */
            k_msgq_purge(&my_msgq);
        }
    }
    
    #define CONFIG_WIFI_MAC_ADDRESS "68:cc:9c:04:05:06"
    int main(void)
    {
    	int mode;
    	data_msg_type_t data_msg;
    #ifdef CONFIG_RAW_TX_PACKET_SAMPLE_STA_ONLY_MODE
    	mode = BIT(0);
    #elif CONFIG_RAW_TX_PACKET_SAMPLE_STA_TX_INJECTION_MODE
    	mode = BIT(0) | BIT(2);
    #endif
    	
    #ifdef CONFIG_RAW_TX_PACKET_SAMPLE_CONNECTION_MODE
    	int status;
    
    	status = try_wifi_connect();
    	if (status < 0) {
    		return status;
    	}
    #else
    	
    #endif
    	buttons_init();
    	wifi_set_mode(mode);
    	k_timer_start(&timer, K_NO_WAIT, K_MSEC(250));
    	while(1)
    	{
    		//set_console_state(0);
    		if(k_msgq_get(&my_msgq, &data_msg, K_FOREVER) == 0)
    		{
    			//wifi_set_mode(mode);
    			wifi_send_raw_tx_packets();
    		}
    		//sys_poweroff();
    	}
    	return 0;
    }
    

    It is modified based on raw_tx_packet.  

    q: I assume when you don't do channel switching it was working for CONFIG_RAW_TX_PACKET_SAMPLE_INTER_FRAME_DELAY_MS >10ms ? (CONFIG_RAW_TX_PACKET_SAMPLE_INTER_FRAME_DELAY_MS = 10ms when don't switching the channel)

    Best regards

Children
Related