Skip to content

m5stack_atoms3_lite/esp32s3/procpu: GPIO interrupts freeze the board when Wi-Fi is used #91007

Closed
@JZimnol

Description

@JZimnol

Describe the bug

Using GPIO (button) interrupts on m5stack_atoms3_lite/esp32s3/procpu freezes the board when Wi-Fi interface is being used. When the interrupts are configured and enabled before Wi-Fi connection is established, they work fine. After invoking net_mgmt(NET_REQUEST_WIFI_CONNECT, ...) the board freezes if the button is being pressed.
This has been tested on 8f2f97ce320ae184e3b2f572436a3758580205fe and the newest main.

Regression

  • This is a regression.

Steps to reproduce

To reproduce the behavior, you can use simple application based on the button sample:

main.c

#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/net/wifi_mgmt.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/util.h>

LOG_MODULE_REGISTER(app, LOG_LEVEL_INF);

static K_SEM_DEFINE(wifi_connected, 0, 1);
static struct net_mgmt_event_callback wifi_mgmt_cb;
#define WIFI_MGMT_EVENTS                                                                           \
	(NET_EVENT_WIFI_CONNECT_RESULT | NET_EVENT_WIFI_DISCONNECT_RESULT |                        \
	 NET_EVENT_WIFI_IFACE_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:
		LOG_INF("Wi-Fi connect result event received");
		k_sem_give(&wifi_connected);
		break;
	case NET_EVENT_WIFI_DISCONNECT_RESULT:
		LOG_INF("Wi-Fi disconnect result event received");
		break;
	case NET_EVENT_WIFI_IFACE_STATUS:
		LOG_INF("Wi-Fi interface status event received");
		break;
	default:
		break;
	}
}

static void wifi_connect(void)
{
	net_mgmt_init_event_callback(&wifi_mgmt_cb, wifi_mgmt_event_handler, WIFI_MGMT_EVENTS);
	net_mgmt_add_event_callback(&wifi_mgmt_cb);

	struct net_if *iface = net_if_get_first_wifi();

	// Replace with your Wi-Fi SSID and password
	static const char *wifi_ssid = "<SSID>";
	static const char *wifi_key = "<KEY>";

	__ASSERT(strlen(wifi_ssid) < WIFI_SSID_MAX_LEN, "SSID too long, check buffer size.");
	__ASSERT(strlen(wifi_key) < WIFI_PSK_MAX_LEN, "WiFi key too long, check buffer size.");
	struct wifi_connect_req_params cnx_params = {
		.band = WIFI_FREQ_BAND_UNKNOWN,
		.channel = WIFI_CHANNEL_ANY,
		.ssid = wifi_ssid,
		.ssid_length = strlen(wifi_ssid),
		.psk = wifi_key,
		.psk_length = strlen(wifi_key),
		.security = WIFI_SECURITY_TYPE_PSK,
		.mfp = WIFI_MFP_OPTIONAL,
	};

	if (net_mgmt(NET_REQUEST_WIFI_CONNECT, iface, &cnx_params,
		     sizeof(struct wifi_connect_req_params))) {
		LOG_ERR("Connection request failed");
		k_sleep(K_FOREVER);
	}
	LOG_INF("Connection requested, SSID: %s, Key: %s", cnx_params.ssid, cnx_params.psk);

	k_sem_take(&wifi_connected, K_FOREVER);
	LOG_INF("Wi-Fi connected successfully");
}

#define SW0_NODE DT_ALIAS(sw0)
#if !DT_NODE_HAS_STATUS_OKAY(SW0_NODE)
#error "Unsupported board: sw0 devicetree alias is not defined"
#endif
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios, {0});
static struct gpio_callback button_cb_data;

static void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
	printk("Button pressed at %" PRIu32 "\n", k_cycle_get_32());
}

static void button_setup(void)
{
	int ret;

	if (!gpio_is_ready_dt(&button)) {
		LOG_ERR("Error: button device %s is not ready", button.port->name);
		return;
	}

	ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
	if (ret != 0) {
		LOG_ERR("Error %d: failed to configure %s pin %d", ret, button.port->name,
			button.pin);
		return;
	}

	ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE);
	if (ret != 0) {
		LOG_ERR("Error %d: failed to configure interrupt on %s pin %d", ret,
			button.port->name, button.pin);
		return;
	}

	gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
	gpio_add_callback(button.port, &button_cb_data);
	LOG_INF("Set up button at %s pin %d", button.port->name, button.pin);

	LOG_INF("Press the button");
}

int main(void)
{
	wifi_connect();
	button_setup();

	return 0;
}

NOTE: replace <SSID> and <KEY> in wifi_connect().

prj.conf

CONFIG_GPIO=y
CONFIG_LOG=y
CONFIG_NETWORKING=y
CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y
CONFIG_NET_DHCPV4_LOG_LEVEL_INF=y
CONFIG_NET_LOG=y

Build and flash

  • west build -p auto -S wifi-ipv4 -b m5stack_atoms3_lite/esp32s3/procpu
  • west flash && west espressif monitor -b 115200

Testing

To test it, you can do the following:

  • run the sample with replaced <SSID> and <KEY>, after connecting to the Wi-Fi, press the built-in button on the board - the application freezes
  • comment the wifi_connect(); line in main() to run the sample without the Wi-Fi, after flashing press the button to see that the interrupts work fine
  • optionally, in the main() you can first initialize buttons, do k_sleep(K_SECONDS(10)); to delay the wifi_initialization and check that the interrupts work, then invoke wifi_connect(); to see that after connecting, the board freezes when the button is pressed

Relevant log output

Impact

Major – Severely degrades functionality; workaround is difficult or unavailable.

Environment

  • OS: Linux
  • Zephyr: newest main
  • toolchain: zephyr-sdk-0.17.0

Additional Context

No response

Metadata

Metadata

Assignees

Labels

area: Wi-FiWi-FibugThe issue is a bug, or the PR is fixing a bugpriority: lowLow impact/importance bug

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions