【免费下载链接】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)被驱动调用,完成两项工作:
- 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: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 封装了完整的构建链路,前置条件:
核心命令:
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 家族内不同芯片的兼容性。
验证与调试要点
延伸:从示例走向真实产品
本示例的代码结构本身就是一套可复用的嵌入式网络固件骨架:
- 协议扩展: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),仅供参考
网硕互联帮助中心




评论前必须登录!
注册