W6300-EVB-Pico 上で HTTPリクエストがあったタイミングで、ページ内容の更新やスリープからの復帰などの処理を行いたい場合があります。
この記事では、WIZnet チップのソケットイベント(接続/切断/受信/タイムアウト)を割り込みで検知する方法 をまとめます。
割り込みマスクの設定
まずは、どのイベントで割り込みを発生させるかのフラグを設定します。
各ソケットごとに以下の割り込みフラグが用意されています。
| フラグ | 説明 |
|---|---|
SIK_CONNECTED |
接続確立時 |
SIK_DISCONNECTED |
切断時 |
SIK_RECEIVED |
データ受信時 |
SIK_TIMEOUT |
タイムアウト時 |
※ SIK_SENT も定義されていますが、このフラグを有効にすると動作が不安定になりました。
これらのフラグは、ctlsocket() 関数で設定します。
ctlsocket(ソケット番号, CS_SET_INTMASK, &マスク);
たとえば、ソケット0で上記すべてのイベントを有効にする場合は以下のようにします。
sockint_kind mask = (SIK_CONNECTED | SIK_DISCONNECTED | SIK_RECEIVED | SIK_TIMEOUT);
ctlsocket(0, CS_SET_INTMASK, &mask);
複数ソケットを同時に設定したい場合は、ループで一括設定が可能です。
for (uint8_t sock = 0; sock < HTTP_SOCKET_MAX_NUM; sock++) {
ctlsocket(sock, CS_SET_INTMASK, &mask);
}
WIZnet チップ全体の割り込みを有効化
続いて、チップ本体のソケット割り込みを有効にします。
有効化すると、ソケットでイベントが発生した際に INT ピン が Low になります。
ctlwizchip(CW_SET_INTRMASK, &ソケットマスク);
ソケットマスク には、割り込みを有効にしたいソケット番号をビットで指定します。
例えば、ソケット0〜3をすべて有効にする場合は以下の通りです。
uint32_t chip_intr = 0;
for (uint8_t sock = 0; sock < HTTP_SOCKET_MAX_NUM; sock++) {
chip_intr |= (1 << sock) << 8; // ソケットごとにビットをセット
}
ctlwizchip(CW_SET_INTRMASK, &chip_intr);
GPIO割り込みハンドラの登録
次に、RP2040 側で GPIO 割り込みを設定し、コールバック関数を登録します。
gpio_set_irq_enabled_with_callback(PIN_INT, GPIO_IRQ_EDGE_FALL, true, &interrupt_callback);
PIN_INT は、wizchip_spi.h の中であらかじめ定義されています。W6300-EVB-Pico の場合、GPIO15 に INT ピンが接続されています。
割り込みコールバック関数の実装
実際にどのソケットで何が起きたかは、ctlsocket() の CS_GET_INTERRUPT を使って取得できます。
void interrupt_callback(uint gpio, uint32_t events) {
uint8_t sock;
sockint_kind sock_intr;
for (sock = 0; sock < HTTP_SOCKET_MAX_NUM; sock++) {
if (ctlsocket(sock, CS_GET_INTERRUPT, &sock_intr) == SOCK_OK) {
if (sock_intr & SIK_CONNECTED) {
printf("Socket %d: CONNECTED\n", sock);
// ここでページ更新やスリープ解除などを実行
}
if (sock_intr & SIK_DISCONNECTED) {
printf("Socket %d: DISCONNECTED\n", sock);
}
if (sock_intr & SIK_RECEIVED) {
printf("Socket %d: RECEIVED\n", sock);
}
if (sock_intr & SIK_TIMEOUT) {
printf("Socket %d: TIMEOUT\n", sock);
}
// フラグをクリア
ctlsocket(sock, CS_CLR_INTERRUPT, &sock_intr);
}
}
}
全体のコード
以下に、HTTP サーバーと割り込み処理を組み合わせた全体のコード例を示します。
/**
Copyright (c) 2021 WIZnet Co.,Ltd
SPDX-License-Identifier: BSD-3-Clause
Modified by namo02268, 2025
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "port_common.h"
#include "wizchip_conf.h"
#include "wizchip_spi.h"
#include "socket.h"
#include "httpServer.h"
#define ETHERNET_BUF_MAX_SIZE (1024 * 2)
#define HTTP_SOCKET_MAX_NUM 4
#define index_page "<!DOCTYPE html>"\
"<html lang=\"en\">"\
"<head>"\
"<meta charset=\"UTF-8\">"\
"<title>Interrupt Test</title>"\
"</head>"\
"<body>"\
"<h1>Hello, World!</h1>"\
"</body>"\
"</html>"
static wiz_NetInfo g_net_info = {
.mac = {0x00, 0x08, 0xDC, 0x12, 0x34, 0x56}, // MAC address
.ip = {192, 168, 0, 30}, // IP address
.sn = {255, 255, 255, 0}, // Subnet Mask
.gw = {192, 168, 0, 1}, // Gateway
.dns = {8, 8, 8, 8}, // DNS server
.dhcp = NETINFO_STATIC
};
static uint8_t g_http_send_buf[ETHERNET_BUF_MAX_SIZE] = {
0,
};
static uint8_t g_http_recv_buf[ETHERNET_BUF_MAX_SIZE] = {
0,
};
static uint8_t g_http_socket_num_list[HTTP_SOCKET_MAX_NUM] = {0, 1, 2, 3};
// 割り込みコールバック関数
void interrupt_callback(uint gpio, uint32_t events) {
uint8_t sock;
sockint_kind sock_intr;
for (sock = 0; sock < HTTP_SOCKET_MAX_NUM; sock++) {
if (ctlsocket(sock, CS_GET_INTERRUPT, &sock_intr) == SOCK_OK) {
if (sock_intr & SIK_CONNECTED) {
printf("Socket %d: CONNECTED\n", sock);
// ここでページ更新やスリープ解除などを実行
}
if (sock_intr & SIK_DISCONNECTED) {
printf("Socket %d: DISCONNECTED\n", sock);
}
if (sock_intr & SIK_RECEIVED) {
printf("Socket %d: RECEIVED\n", sock);
}
if (sock_intr & SIK_TIMEOUT) {
printf("Socket %d: TIMEOUT\n", sock);
}
// フラグをクリア
ctlsocket(sock, CS_CLR_INTERRUPT, &sock_intr);
}
}
}
int main() {
stdio_init_all();
sleep_ms(3000);
wizchip_spi_initialize();
wizchip_cris_initialize();
wizchip_reset();
wizchip_initialize();
wizchip_check();
network_initialize(g_net_info);
httpServer_init(g_http_send_buf, g_http_recv_buf, HTTP_SOCKET_MAX_NUM, g_http_socket_num_list);
print_network_information(g_net_info);
reg_httpServer_webContent("index.html", index_page);
// ソケット割り込みマスク設定
uint8_t sock = 0;
sockint_kind mask = (SIK_CONNECTED | SIK_DISCONNECTED | SIK_RECEIVED | SIK_TIMEOUT);
for(sock=0; sock<HTTP_SOCKET_MAX_NUM; sock++) {
ctlsocket(sock, CS_SET_INTMASK, &mask);
}
// チップ全体の割り込みマスク設定
uint32_t chip_intr = 0;
for(sock = 0; sock < HTTP_SOCKET_MAX_NUM; sock++) {
chip_intr |= ((1 << sock) << 8);
}
ctlwizchip(CW_SET_INTRMASK, &chip_intr);
// GPIO 割り込み登録
gpio_set_irq_enabled_with_callback(PIN_INT, GPIO_IRQ_EDGE_FALL, true, &interrupt_callback);
while (1) {
for (uint8_t i = 0; i < HTTP_SOCKET_MAX_NUM; i++) {
httpServer_run(i);
}
}
}
使用しているコードは、WIZnet社が公開しているBSD 3-Clauseライセンスのサンプルコードをもとに改変しています。オリジナルのソースコードは WIZnet GitHub Repository で公開されています。