云计算百科
云计算领域专业知识百科平台

在 RP2040 / RP2350 上运行 Mongoose:Pico W 嵌入式 HTTP 服务器与 Wi-Fi 实战指南

  • 嵌入式
  • 网络
  • 通信
  • 物联网

【免费下载链接】mongoose

Embedded web server, with TCP/IP network stack, MQTT and Websocket

项目地址:
https://gitcode.com/gh_mirrors/mon/mongoose

点击查看 免费下载

Mongoose 自带完整的 TCP/IP 协议栈,可以在不依赖 lwIP 的情况下直接驱动 Raspberry Pi Pico W 的 CYW43439 Wi-Fi 芯片。本指南以仓库中 tutorials/rp/pico-w 示例为骨架,讲解如何为 RP2040/RP2350 目标板配置、编译、烧录一个内置 HTTP 服务(含 JSON API)与 Wi-Fi 扫描/连接/AP 状态机的固件,并深入解析驱动与构建链路的源码实现,让你能够在此基础上快速改造出自己的联网固件。

示例概览与目录结构

tutorials/rp/pico-w 是一个可同时面向 RP2040(Pico W)与 RP2350(Pico 2 W)构建的完整示例。与常见的“Pico W + lwIP”方案不同,这里使用的是 Mongoose 内建的网络栈(MG_ENABLE_TCPIP),配合仓库提供的 pico-w 驱动直接操作 CYW43 无线芯片,代码量更小、移植路径更清晰。

示例目录结构如下:

tutorials/rp/pico-w/
├── CMakeLists.txt # Pico SDK 构建脚本,设置目标板
├── Makefile # 一键 build / flash / clean
├── README.md # 官方使用说明(本文主体来源)
├── main.c # HTTP 服务器入口与 LED 闪烁任务
├── wifi.c # Wi-Fi 配置与扫描/连接状态机
└── mongoose/
├── mongoose_config.h # Mongoose 编译期配置(Pico 专用)
├── mongoose.c # 构建时从仓库根目录复制而来
└── mongoose.h

其中 mongoose.c、mongoose.h 与 pico_sdk_import.cmake 都不是手工维护的文件,而是由 Makefile 在构建时自动从仓库根目录的 mongoose.c / mongoose.h 以及 pico-sdk 中复制生成,保证示例始终与当前仓库代码同步。

主程序:HTTP 服务器 + LED 闪烁任务

main.c 展示了 Mongoose 事件驱动模型在裸机(无 RTOS)环境下的典型写法,核心只有两个函数:

  • blink_task():基于 mg_timer_expired() 每 500 ms 翻转一次 Pico W 板载 LED(CYW43_WL_GPIO_LED_PIN)。注意该 LED 由 CYW43 芯片控制,必须在 Mongoose 完成驱动初始化之后再访问,这也是 main() 中注释强调“do not access the CYW43 LED before Mongoose initializes!”的原因。
  • run_mongoose():初始化事件管理器并启动 HTTP 服务:

struct mg_mgr mgr;
mg_mgr_init(&mgr);
mg_http_listen(&mgr, "http://0.0.0.0", http_ev_handler, NULL);

for (;;) {
mg_mgr_poll(&mgr, 1); // 轮询网络事件,超时 1 ms
blink_task(); // 每轮询一次执行一次闪烁任务
}

mg_http_listen() 是 Mongoose HTTP 服务端的统一入口(声明见 src/http.h,实现见 src/http.c),监听地址 http://0.0.0.0 表示绑定所有接口。HTTP 事件回调 http_ev_handler 中处理 MG_EV_HTTP_MSG 事件,实现两条路由:

  • GET /api/tick:返回 JSON 格式的启动后毫秒时间戳,使用 mg_http_reply() 配合 MG_ESC 安全转义,输出 {"tick":123456};
  • 其他路径:返回纯文本 Hi from Mongoose, tick <tick>。

to_ms_since_boot(get_absolute_time()) 是 Pico SDK 提供的单调时钟,用于计算设备上电后的运行时长,可以作为最简单的“心跳/存活”接口,配合上位机轮询即可验证固件是否在线。

Wi-Fi 配置:STA / AP 双模式与完整状态机

Wi-Fi 凭据与行为全部集中在 wifi.c,文件头部定义了两组宏,是接入自己网络时必须修改的地方:

#define WIFI_NAME "YOUR_WIFI_NETWORK" // SET THIS! STA 模式要连接的网络
#define WIFI_PASS "YOUR_WIFI_PASSWORD" // SET THIS!
#define ENABLE_AP false // 是否开机直接进入 AP 模式
#define WIFI_AP_NAME "YOUR_AP_NETWORK" // AP 模式的 SSID
#define WIFI_AP_PASS "YOUR_AP_PASSWORD" // AP 模式的密码

wifi_setconfig:把配置挂到驱动上

wifi_setconfig() 通过 MG_SET_WIFI_CONFIG 宏(见 mongoose_config.h)被驱动调用,完成两项工作:

  • 填充 struct mg_wifi_data 配置结构(定义见 src/wifi.h),包括:
    • ssid / pass:STA 模式要连接的网络与密码;
    • apssid / appass:AP 模式的 SSID 与密码;
    • apip / apmask:AP 模式的静态地址,示例使用 192.168.111.1/24;
    • apchannel:AP 信道,示例固定为 10;
    • security / apsecurity:安全模式,示例为 0(开放);
    • apmode:是否开机直接进入 AP 模式(由 ENABLE_AP 控制);
  • 把状态机回调 mif_fn 注册到 struct mg_tcpip_if 的 fn 字段,此后驱动产生的 Wi-Fi 事件都会进入该回调。
  • mif_fn:Wi-Fi 扫描 / 连接 / 断开状态机

    mif_fn() 是示例的精华,它用 enum { AP, SCANNING, STOPPING_AP, CONNECTING, READY } 描述了一个完整的用户态状态机,演示了 Mongoose 提供的全部 Wi-Fi 管理 API(声明见 src/wifi.h):

    状态触发事件动作
    AP MG_TCPIP_EV_STATE_CHANGE 且新状态为 MG_TCPIP_STATE_READY 调用 mg_wifi_scan() 扫描周边网络,成功则进入 SCANNING
    SCANNING MG_TCPIP_EV_WIFI_SCAN_RESULT(每个 BSS 一次)/ MG_TCPIP_EV_WIFI_SCAN_END(扫描结束) 打印每个热点的 SSID、信道、MAC、RSSI 与安全类型;扫描结束后 mg_wifi_ap_stop() 停掉 AP,进入 STOPPING_AP
    STOPPING_AP MG_TCPIP_EV_STATE_CHANGE 且新状态为 MG_TCPIP_STATE_DOWN 将 wifi->apmode 置为 false,调用 mg_wifi_connect() 连接选中的网络,进入 CONNECTING
    CONNECTING MG_TCPIP_EV_STATE_CHANGE 且新状态为 MG_TCPIP_STATE_READY 打印 READY!,进入 READY;若收到 MG_TCPIP_EV_WIFI_CONNECT_ERR 则打印连接失败
    READY MG_TCPIP_EV_STATE_CHANGE 且新状态为 MG_TCPIP_STATE_DOWN 模拟断线重连流程:mg_wifi_disconnect() 后再次 mg_wifi_ap_start() 回到 AP 模式

    扫描结果事件携带 struct mg_wifi_scan_bss_data(定义见 src/wifi.h),其中 security 字段是位掩码,通过 MG_WIFI_SECURITY_OPEN / WEP / WPA / WPA2 / WPA3 等宏组合表示热点安全等级,可据此在真实产品中实现“扫描 → 用户选择 → 连接”的配网流程。

    Mongoose 编译期配置:Pico 平台开关

    mongoose_config.h 是与平台相关的构建配置,也是把 Mongoose “裁剪”成嵌入式尺寸的关键:

    #define MG_ARCH MG_ARCH_PICOSDK // 选择 Pico SDK 平台抽象层
    #define MG_OTA MG_OTA_PICOSDK // 启用 Pico SDK 的 OTA 支持
    #define MG_IO_SIZE 2048 // I/O 缓冲大小

    #define MG_ENABLE_TCPIP 1 // 启用内建 TCP/IP 协议栈
    #define MG_ENABLE_DRIVER_PICO_W 1 // 启用 Pico W (CYW43) 网络驱动

    // MAC 地址由驱动在初始化时从 OTP 读取
    // 通过自定义函数注入 Wi-Fi 配置:
    extern void wifi_setconfig(void *, void *);
    #define MG_SET_WIFI_CONFIG(ifp, data) wifi_setconfig(ifp, data)

    几个关键点:

    • MG_ARCH_PICOSDK 对应仓库 src/arch_picosdk.h 提供的时钟、随机数、系统调用等平台适配,是 Pico 系列编译的基础;
    • MG_SET_WIFI_CONFIG 宏将 wifi_setconfig 注入到驱动的初始化宏 MG_TCPIP_DRIVER_INIT 中(见 src/drivers/pico-w.h),驱动初始化时会调用它来完成 Wi-Fi 参数装载;
    • 默认 TCP/IP 静态地址由 src/config.h 中的 MG_TCPIP_IP / MG_TCPIP_MASK / MG_TCPIP_GW 控制,默认值均为 0.0.0.0,含义是“交给 DHCP”。Pico W 驱动会在驱动初始化时读取这些宏并传给 struct mg_tcpip_if。

    驱动实现:Mongoose 如何直接驱动 CYW43

    仓库在 src/drivers/pico-w.c 中提供了完整的 CYW43 驱动,验证了示例中“无 lwIP 也能联网”的实现路径。驱动对外暴露 struct mg_tcpip_driver mg_tcpip_driver_pico_w,包含四个回调:

    • init:调用 cyw43_arch_init() 初始化 Wi-Fi 芯片;若 apmode 为真则直接 mg_wifi_ap_start() 启动 AP,否则进入 STA 模式并调用 mg_wifi_connect() 发起连接(ssid 为空则仅启用 STA 模式不连接);MAC 地址通过 cyw43_wifi_get_mac() 从 OTP 读取。
    • tx:根据当前 apmode 选择 CYW43_ITF_AP 或 CYW43_ITF_STA 接口,调用 cyw43_send_ethernet() 发送以太网帧。
    • poll:轮询时调用 cyw43_arch_poll() 处理芯片事件;若扫描已结束则向上抛出 MG_TCPIP_EV_WIFI_SCAN_END;STA 模式下若 cyw43_wifi_link_status() 返回错误,则抛出 MG_TCPIP_EV_WIFI_CONNECT_ERR。
    • 接收路径:cyw43_cb_process_ethernet() 把芯片收到的每个帧通过 mg_tcpip_qwrite() 写入 Mongoose 的接收队列,完成从无线帧到 TCP/IP 协议栈的交接。

    AP 模式的地址切换逻辑在 wifi_cb() 中完成:当 AP 链路建立(MG_TCPIP_STATE_UP)时,驱动把 ifp->ip 临时切换为 wifi->apip、ifp->mask 切换为 wifi->apmask,并关闭 DHCP 客户端、开启 DHCP 服务器,使 AP 模式下的连接设备可以自动获取 192.168.111.x 网段的地址。

    构建与烧录:CMake 工程与一键 Makefile

    CMake 工程配置

    CMakeLists.txt 是标准的 Pico SDK 工程文件,需要注意:

    # 目标板必须放在 include(pico_sdk_import.cmake) 之前设置
    set(PICO_BOARD pico_w)
    include(pico_sdk_import.cmake)
    …
    add_executable(firmware main.c wifi.c mongoose/mongoose.c)
    target_link_libraries(firmware pico_stdlib hardware_spi pico_rand
    pico_cyw43_driver pico_cyw43_arch_none
    hardware_flash pico_bootrom)
    pico_enable_stdio_usb(firmware 1) # 串口输出走 USB CDC
    # 防止极端优化破坏 OTA 流程
    target_compile_options(firmware PRIVATE -fno-tree-loop-distribute-patterns)

    • pico_cyw43_arch_none 是关键:它选择“不挂接任何 TCP/IP 协议栈”的 CYW43 架构变体,把网络处理完全交给 Mongoose,避免与 lwIP 冲突;
    • pico_cyw43_driver 提供 CYW43 芯片底层驱动,pico_rand 为 TLS/随机数提供硬件熵源,hardware_flash 与 pico_bootrom 服务于 Pico 平台的 OTA 功能(MG_OTA_PICOSDK);
    • -fno-tree-loop-distribute-patterns 用于阻止 GCC 把循环优化成可能破坏 OTA 校验逻辑的 memcpy 内建调用。

    一键构建与烧录

    Makefile 封装了完整的构建链路,前置条件:

  • 安装 picotool(烧录工具);
  • 首次构建时 Makefile 会自动在本地克隆 pico-sdk(版本 2.1.1)并初始化其子模块,无需手工下载 SDK。
  • 核心命令:

    make build flash

    各目标的作用:

    目标说明
    build(默认目标) 生成 build/firmware.uf2;构建前会自动把仓库根目录的 mongoose.c/mongoose.h 复制进 mongoose/ 子目录
    flash 使用 picotool load build/firmware.uf2 -f 把固件烧录到 Pico
    clean 清理 build 目录、SDK 与复制生成的临时文件,恢复到干净状态

    pico_enable_stdio_usb(firmware 1) 把调试输出重定向到 USB 串口,烧录完成后打开串口终端(如 minicom / picocom / Arduino 串口监视器)即可看到 MG_INFO 输出的 Driver: pico-w, MAC: …、Wi-Fi 状态切换、BSS 扫描结果等日志,直接验证固件运行状态。

    切换目标板:从 Pico W 到 Pico 2 W

    官方 README 指出该示例同时支持 RP2040 与 RP2350,切换方法是在 CMakeLists.txt 中修改目标板宏(注意需放在 SDK import 之前):

    set(PICO_BOARD pico2_w)

    然后重新执行 make build flash 即可。构建脚本会依据 PICO_BOARD 选择对应的 SDK 板级定义与启动文件,应用代码(main.c / wifi.c)无需改动,体现了 Mongoose 平台抽象层(MG_ARCH_PICOSDK)对同一 SDK 家族内不同芯片的兼容性。

    验证与调试要点

  • 烧录前检查:确认 wifi.c 中的 WIFI_NAME / WIFI_PASS 已改成真实网络,否则 STA 连接会失败(状态机将停留在 CONNECTING 并打印 Wi-Fi connect failed)。
  • 串口观察:上电后应依次看到硬件初始化日志、驱动 MAC 打印、Access Point READY!(若 ENABLE_AP=true)或 READY!(STA 连接成功)。
  • HTTP 验证:连接同一网络后,用浏览器或 curl 访问设备的 DHCP 地址(STA 模式下由路由器分配):curl http://<设备IP>/api/tick 应返回类似 {"tick":12345} 的 JSON。
  • AP 模式测试:将 ENABLE_AP 改为 true,设备开机即广播 WIFI_AP_NAME 指定的 SSID,接入后浏览器访问 http://192.168.111.1 即可看到 HTTP 响应。
  • 延伸:从示例走向真实产品

    本示例的代码结构本身就是一套可复用的嵌入式网络固件骨架:

    • 协议扩展:http_ev_handler 中按 mg_match() 分发 URI 的模式,可以自然扩展出更多 REST 接口;若需要 MQTT,可参考仓库 tutorials/mqtt 下的示例,将 mg_http_listen() 替换为 mg_mqtt_connect() 即可复用同一套 TCP/IP 栈;
    • 配网流程:mif_fn 中“AP 模式 → 扫描 → 停止 AP → 连接 STA → 断线回退 AP”的完整状态机,正是消费级设备常见配网方案的雏形,可直接改造为“网页配网 + 断线自动回退”;
    • OTA 升级:MG_OTA_PICOSDK 已在配置中启用,CMakeLists.txt 也链接了 hardware_flash 与 pico_bootrom,为后续接入 Mongoose 的 OTA 功能预留了完整底座。

    总而言之,tutorials/rp/pico-w 是“Mongoose 内建 TCP/IP 栈 + Pico W 无线芯片”组合的最小可运行参考实现:从改两处宏接入自家 Wi-Fi,到 make build flash 一键烧录,再到阅读 src/drivers/pico-w.c 理解 CYW43 驱动原理,一条链路清晰完整,适合作为任何基于 RP2040/RP2350 的联网产品固件的起点。

    赞

    分享

    • 嵌入式
    • 网络
    • 通信
    • 物联网

    【免费下载链接】mongoose

    Embedded web server, with TCP/IP network stack, MQTT and Websocket

    项目地址:
    https://gitcode.com/gh_mirrors/mon/mongoose

    点击查看 免费下载

    上一篇:
    坐标转换工具:轻松解决百度、国测局、WGS84坐标系转换难题

    下一篇:
    MagiskHide Props Config终极指南:3步完成Android设备属性配置

    创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 在 RP2040 / RP2350 上运行 Mongoose:Pico W 嵌入式 HTTP 服务器与 Wi-Fi 实战指南
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!