[bsp][gd32]:gd32vw553h-eval add wifi support#11175
[bsp][gd32]:gd32vw553h-eval add wifi support#11175CYFS3 wants to merge 1 commit intoRT-Thread:masterfrom
Conversation
|
👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread! 为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。 🛠 操作步骤 | Steps
完成后,提交将自动更新至 如有问题欢迎联系我们,再次感谢您的贡献!💐 |
📌 Code Review Assignment🏷️ Tag: componentsReviewers: @Maihuanyi Changed Files (Click to expand)
🏷️ Tag: libcpu_riscvReviewers: @Yaochenger Changed Files (Click to expand)
📊 Current Review Status (Last Updated: 2026-02-05 15:23 CST)
📝 Review Instructions
|
There was a problem hiding this comment.
Pull request overview
This pull request adds WiFi support for the GD32VW553H-EVAL board, integrating the internal WiFi hardware capabilities through a custom driver and vendor-provided SDK. The changes span multiple areas including RISC-V interrupt handling, BSP configuration, WiFi driver implementation, and lwIP integration.
Changes:
- Adds WiFi driver (drv_wlan.c/h) implementing RT-Thread WLAN device framework
- Modifies RISC-V interrupt handling to support GD32VW553H-specific requirements
- Updates build system (compiler flags, linker script) to accommodate precompiled WiFi libraries
- Integrates GD32 WiFi management SDK with conditional compilation to exclude conflicting lwIP components
- Updates documentation with WiFi usage instructions
Reviewed changes
Copilot reviewed 12 out of 27 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| libcpu/risc-v/common/interrupt_gcc.S | Adds GD32VW553H-specific interrupt nesting check and changes jal to call instruction |
| bsp/gd32/risc-v/gd32vw553h-eval/board/trap_gcc.S | Modifies CSR context save/restore mechanism with different register indices |
| bsp/gd32/risc-v/gd32vw553h-eval/board/linker_scripts/link.lds | Adds .code_to_sram section for performance-critical WiFi code |
| bsp/gd32/risc-v/gd32vw553h-eval/rtconfig.py | Changes architecture from rv32imafdc to rv32imafc to match precompiled WiFi libraries |
| bsp/gd32/risc-v/gd32vw553h-eval/board/drv_wlan.c | Implements WiFi driver with scan, connect, AP mode support |
| bsp/gd32/risc-v/gd32vw553h-eval/applications/main.c | Integrates WiFi initialization into main application |
| components/net/lwip/port/SConscript | Conditionally excludes sys_arch.c when using GD32 WiFi package |
| components/drivers/wlan/dev_wlan_cmd.c | Code formatting improvements and conditional compilation fixes |
| bsp/gd32/risc-v/gd32vw553h-eval/board/Kconfig | Adds WiFi configuration options |
| bsp/gd32/risc-v/gd32vw553h-eval/README.md | Adds WiFi usage documentation with screenshots |
| #ifdef RT_USING_WIFI | ||
| #define START_TASK_STACK_SIZE 512 | ||
| #define START_TASK_PRIO 4 | ||
|
|
||
| static void application_init(void) | ||
| { | ||
| rt_kprintf("Hello GD32VW553H\n"); | ||
| /* set LED1 pin mode to output */ | ||
| rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT); | ||
| util_init(); | ||
|
|
||
| user_setting_init(); | ||
|
|
||
| if (wifi_init()) { | ||
| rt_kprintf("wifi init failed\r\n"); | ||
| } else { | ||
| // rt_kprintf("wifi init success\r\n"); | ||
| } | ||
| } | ||
|
|
||
| static rt_sem_t init_done_sem = RT_NULL; | ||
|
|
||
| static void start_task(void *param) | ||
| { | ||
| (void)param; | ||
|
|
||
| application_init(); | ||
| // rt_kprintf("Start task completed, exiting.\n"); | ||
|
|
||
| /* Note: In RT-Thread, task should exit by returning, not by calling sys_task_delete(NULL). | ||
| * When the task function returns, RT-Thread will automatically clean up the task. | ||
| */ | ||
|
|
||
| rt_sem_release(init_done_sem); | ||
| } | ||
|
|
||
| #endif /* RT_USING_WIFI */ |
There was a problem hiding this comment.
Using Chinese comments in code violates RT-Thread coding standards. The comments on lines 200-201, as well as comments throughout main.c should be in English per RT-Thread guidelines.
代码中使用中文注释违反 RT-Thread 编码规范。第 200-201 行以及 main.c 中的其他注释应按照 RT-Thread 指南使用英文。
| _sicode = LOADADDR(.code_to_sram); | ||
|
|
||
| .code_to_sram : | ||
| { | ||
| . = ALIGN(4); | ||
| _scode = .; | ||
|
|
||
| *trap_gcc.o* (.text*) | ||
| *port.o* (.text.eclic_mtip_handler) | ||
| *lib_a-memcpy.o* (.text*) | ||
| *wrapper_os.o* (.text.sys_memcpy*) | ||
| *inet_chksum.o* (.text.lwip_standard_chksum) | ||
| /**macsw/modules/ke/ke_event.o* (.rodata.ke_evt_hdlr*) | ||
| *rxl_cntrl.o* (.text.rxl_upload_evt)*/ | ||
| *txl_agg.o* (.text.txl_agg_push_mpdu .text.txl_agg_finish) | ||
| *txl_he.o* (.text.txl_he_tb_prot_trigger .text.txl_he_trigger_push) | ||
| *rxl_hwdesc.o* (.text.rxl_immediate_frame_get .text.rxl_rxcntrl_frame) | ||
|
|
||
|
|
||
| *txl_agg.o* (.text.* .rodata.*) | ||
| *txl_he.o* (.text.* .rodata.*) | ||
| *rxl_hwdesc.o* (.text.* .rodata.*) | ||
|
|
||
| *drv_uart.o* (.text.USART0_IRQHandler .text.GD32_UART_IRQHandler) /* choose UART on condition */ | ||
| *gd32vw55x_usart.o* (.text.usart_interrupt_flag_get .text.usart_interrupt_flag_clear .text.usart_flag_get .text.usart_flag_clear) | ||
| *gd32vw55x_usart.o* (.text.usart_data_receive .text.usart_data_transmit) | ||
| *gd32vw55x_usart.o* (.text.usart_interrupt_enable .text.usart_interrupt_disable) | ||
| *dev_serial.o* (.text.rt_hw_serial_isr) | ||
| *save-restore.o* (.text*) | ||
|
|
||
|
|
||
| . = ALIGN(4); | ||
| _ecode = .; | ||
| } >ram AT>flash |
There was a problem hiding this comment.
The linker script adds a .code_to_sram section that copies specific code to RAM for performance. However, the section selection is overly specific with wildcards like *trap_gcc.o*, *rxl_hwdesc.o*, etc. This tight coupling to specific object file names is fragile and hard to maintain. Consider using a more maintainable approach such as:
- Using linker section attributes in source code (e.g.,
__attribute__((section(".fast_text"))) - Adding comments explaining why each file/function needs to be in RAM
- Documenting the performance impact measurements that justified this optimization
链接器脚本添加了 .code_to_sram 段,将特定代码复制到 RAM 以提高性能。但是,段选择过于具体,使用了 *trap_gcc.o*、*rxl_hwdesc.o* 等通配符。这种与特定目标文件名的紧密耦合很脆弱且难以维护。考虑使用更可维护的方法,例如:
- 在源代码中使用链接器段属性(如
__attribute__((section(".fast_text")))) - 添加注释说明为什么每个文件/函数需要在 RAM 中
- 记录证明此优化合理性的性能影响测量结果
| # 使用单精度硬件浮点ABI以匹配预编译的WiFi库 (libwifi.a, libwpas.a, librf.a) | ||
| # 预编译库架构: rv32imafcbp (包含单精度浮点 'f' 扩展) | ||
| # 原配置: -march=rv32imafdc -mabi=ilp32d (硬件双精度浮点) | ||
| # 修改为: -march=rv32imafc -mabi=ilp32f (硬件单精度浮点) | ||
| # 注意: GCC 8.2.0 不支持 -mpriv-spec 选项,链接时使用 --no-warn-mismatch 忽略特权规范版本差异 | ||
| DEVICE = ' -march=rv32imafc -mcmodel=medany -msmall-data-limit=8 -mabi=ilp32f -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections ' | ||
|
|
||
| # C Compilation Parameters | ||
| CFLAGS = DEVICE + ' -std=gnu11 -DUSE_STDPERIPH_DRIVE -save-temps=obj' | ||
| # Assembly Compilation Parameters | ||
| AFLAGS = DEVICE + '-c'+ ' -x assembler-with-cpp' | ||
| # Linking Parameters | ||
| LFLAGS = DEVICE + ' -nostartfiles -Xlinker --gc-sections --specs=nano.specs --specs=nosys.specs ' + ' -T ' + LINK_FILE + ' -Wl,-Map=' + MAP_FILE | ||
| # 添加 --no-warn-mismatch 以忽略预编译库与当前工具链的特权规范版本差异 | ||
| # 添加 WiFi ROM 符号表 | ||
| import os | ||
| wifi_pkg_path = os.path.join(os.path.dirname(__file__), 'packages', 'gd32vw55x-wifi') | ||
| rom_symbol = os.path.join(wifi_pkg_path, 'rom_export', 'symbol', 'rom_symbol_m.gcc') | ||
| rom_symbol_flag = '' | ||
| if os.path.exists(rom_symbol): | ||
| rom_symbol_flag = ' -Wl,--just-symbols=' + rom_symbol | ||
| LFLAGS = DEVICE + ' -nostartfiles -Xlinker --gc-sections -Xlinker --no-warn-mismatch --specs=nano.specs --specs=nosys.specs ' + rom_symbol_flag + ' -T ' + LINK_FILE + ' -Wl,-Map=' + MAP_FILE |
There was a problem hiding this comment.
The architecture change from rv32imafdc (double-precision float) to rv32imafc (single-precision float) to match precompiled WiFi libraries is a significant ABI break. This forces all code to use single-precision floats. The comment explains the reason, but consider:
- Documenting this limitation in the BSP README
- Warning users that existing code using double-precision may have performance degradation or precision issues
- Verifying that RT-Thread and lwIP don't rely on double-precision floats
The --no-warn-mismatch flag suppresses important linker warnings about ABI mismatches. This is dangerous as it can hide real compatibility issues. Consider requesting updated WiFi libraries with the correct architecture instead.
架构从 rv32imafdc(双精度浮点)改为 rv32imafc(单精度浮点)以匹配预编译的 WiFi 库,这是一个重大的 ABI 破坏。这迫使所有代码使用单精度浮点。注释解释了原因,但请考虑:
- 在 BSP README 中记录此限制
- 警告用户现有使用双精度的代码可能出现性能下降或精度问题
- 验证 RT-Thread 和 lwIP 不依赖双精度浮点
--no-warn-mismatch 标志抑制了关于 ABI 不匹配的重要链接器警告。这很危险,因为它可以隐藏真正的兼容性问题。考虑请求使用正确架构的更新 WiFi 库。
| // rt_kprintf("WiFi scan start\r\n"); | ||
|
|
||
| eloop_event_register(WIFI_MGMT_EVENT_SCAN_DONE, scan_done_callback, NULL, NULL); | ||
| eloop_event_register(WIFI_MGMT_EVENT_SCAN_FAIL, scan_fail_callback, NULL, NULL); | ||
|
|
||
| if (wifi_management_scan(false, NULL)) { | ||
| eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_DONE); | ||
| eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_FAIL); | ||
| rt_kprintf("Wifi scan failed\r\n"); | ||
| } | ||
|
|
||
| return RT_EOK; |
There was a problem hiding this comment.
Error handling in rt_hw_wlan_init returns RT_EOK on all paths even when errors occur. The function should return appropriate error codes when:
- malloc fails (line 84)
- wifi_netlink_scan_results_get fails (line 89)
- wifi_management_scan fails (line 161)
- wifi_management_connect fails (line 204)
- etc.
This prevents callers from detecting initialization failures and makes debugging harder.
rt_hw_wlan_init 中的错误处理在所有路径上都返回 RT_EOK,即使发生错误也是如此。该函数应在以下情况返回适当的错误代码:
- malloc 失败(第 84 行)
- wifi_netlink_scan_results_get 失败(第 89 行)
- wifi_management_scan 失败(第 161 行)
- wifi_management_connect 失败(第 204 行)
- 等等
这使调用者无法检测初始化失败,并使调试更加困难。
| // rt_kprintf("WiFi scan start\r\n"); | |
| eloop_event_register(WIFI_MGMT_EVENT_SCAN_DONE, scan_done_callback, NULL, NULL); | |
| eloop_event_register(WIFI_MGMT_EVENT_SCAN_FAIL, scan_fail_callback, NULL, NULL); | |
| if (wifi_management_scan(false, NULL)) { | |
| eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_DONE); | |
| eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_FAIL); | |
| rt_kprintf("Wifi scan failed\r\n"); | |
| } | |
| return RT_EOK; | |
| rt_err_t result = RT_EOK; | |
| // rt_kprintf("WiFi scan start\r\n"); | |
| eloop_event_register(WIFI_MGMT_EVENT_SCAN_DONE, scan_done_callback, NULL, NULL); | |
| eloop_event_register(WIFI_MGMT_EVENT_SCAN_FAIL, scan_fail_callback, NULL, NULL); | |
| if (wifi_management_scan(false, NULL)) | |
| { | |
| eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_DONE); | |
| eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_FAIL); | |
| rt_kprintf("Wifi scan failed\r\n"); | |
| result = RT_ERROR; | |
| } | |
| return result; |
| if (RT_NULL == results) { | ||
| LOG_E("Failed to allocate memory for scan results\r\n"); | ||
| return; | ||
| } | ||
|
|
||
| if (wifi_netlink_scan_results_get(WIFI_VIF_STA, results)) { | ||
| rt_free(results); | ||
| rt_kprintf("WIFI scan results get failed\r\n"); | ||
| return; | ||
| } | ||
|
|
||
| for (idx = 0; idx < results->result_cnt; idx++) { |
There was a problem hiding this comment.
Missing null pointer check after rt_malloc at line 83. If memory allocation fails, the code will dereference NULL at line 89, causing a crash. Add proper error handling:
results = (struct macif_scan_results *)rt_malloc(sizeof(struct macif_scan_results));
if (RT_NULL == results) {
LOG_E("Failed to allocate memory for scan results\r\n");
rt_wlan_dev_indicate_event_handle(wlan_sta_device.wlan, RT_WLAN_DEV_EVT_SCAN_DONE, RT_NULL);
return;
}第 83 行 rt_malloc 后缺少空指针检查。如果内存分配失败,代码将在第 89 行解引用 NULL,导致崩溃。添加适当的错误处理。
| if (RT_NULL == results) { | |
| LOG_E("Failed to allocate memory for scan results\r\n"); | |
| return; | |
| } | |
| if (wifi_netlink_scan_results_get(WIFI_VIF_STA, results)) { | |
| rt_free(results); | |
| rt_kprintf("WIFI scan results get failed\r\n"); | |
| return; | |
| } | |
| for (idx = 0; idx < results->result_cnt; idx++) { | |
| if (RT_NULL == results) | |
| { | |
| LOG_E("Failed to allocate memory for scan results\r\n"); | |
| rt_wlan_dev_indicate_event_handle(wlan_sta_device.wlan, RT_WLAN_DEV_EVT_SCAN_DONE, RT_NULL); | |
| return; | |
| } | |
| if (wifi_netlink_scan_results_get(WIFI_VIF_STA, results)) | |
| { | |
| rt_free(results); | |
| rt_kprintf("WIFI scan results get failed\r\n"); | |
| rt_wlan_dev_indicate_event_handle(wlan_sta_device.wlan, RT_WLAN_DEV_EVT_SCAN_DONE, RT_NULL); | |
| return; | |
| } | |
| for (idx = 0; idx < results->result_cnt; idx++) | |
| { |
| {"prot", wifi_debug_set_prot}, | ||
| {"auto", wifi_debug_set_autoconnect}, | ||
| #else | ||
| {"mode", wifi_debug_set_mode }, |
There was a problem hiding this comment.
Duplicate "mode" entry at line 87 (also present at line 85). This creates ambiguity in the debug_tab array. Remove the duplicate entry.
第 87 行的 "mode" 条目重复(第 85 行也存在)。这在 debug_tab 数组中造成歧义。删除重复条目。
| #ifdef SOC_GD32VW553H | ||
| call rt_hw_do_after_save_above | ||
| #else | ||
| jal rt_hw_do_after_save_above | ||
| #endif |
There was a problem hiding this comment.
The change from jal to call for SOC_GD32VW553H should be explained. Both instructions invoke rt_hw_do_after_save_above, but jal has a limited range (±1MB) while call (a pseudo-instruction expanding to auipc+jalr) has unlimited range. If this change is necessary for GD32VW553H, please add a comment explaining why. Also verify this doesn't break other RISC-V platforms that might depend on the jal instruction.
此处将 jal 改为 call 应该说明原因。两者都调用 rt_hw_do_after_save_above,但 jal 的范围有限(±1MB),而 call(伪指令,展开为 auipc+jalr)范围无限。如果此更改对 GD32VW553H 必要,请添加注释说明原因。同时验证这不会破坏其他可能依赖 jal 指令的 RISC-V 平台。
| #ifdef SOC_GD32VW553H | ||
| /* Check if we are in interrupt nesting, if so, skip task switching */ | ||
| la t0, rt_interrupt_nest | ||
| lw t1, 0(t0) | ||
| li t3, 1 | ||
| bge t1, t3, 1f | ||
| #endif /* SOC_GD32VW553H */ |
There was a problem hiding this comment.
The interrupt nesting check (lines 113-119) is GD32VW553H-specific but placed in common RISC-V code. This breaks the separation between common and platform-specific code. Consider moving this logic to bsp/gd32/risc-v/gd32vw553h-eval/board/trap_gcc.S or rt_hw_do_after_save_above implementation, or make it configurable for all platforms that need it.
中断嵌套检查(113-119行)是 GD32VW553H 特定的,但放在了通用 RISC-V 代码中。这破坏了通用代码和平台特定代码的分离。考虑将此逻辑移至 bsp/gd32/risc-v/gd32vw553h-eval/board/trap_gcc.S 或 rt_hw_do_after_save_above 实现,或使其可配置以支持所有需要它的平台。
| { | ||
| LOG_D("WiFi device init: %s", wlan->name); | ||
|
|
||
| return RT_EOK; | ||
| } | ||
|
|
||
| /** | ||
| * @brief WiFi mode configuration | ||
| */ | ||
| static rt_err_t gd32_wlan_mode(struct rt_wlan_device *wlan, rt_wlan_mode_t mode) | ||
| { | ||
| LOG_D("Set WiFi mode: %d", mode); | ||
|
|
||
| /* TODO: Set WiFi mode (STA/AP/STA+AP) */ | ||
|
|
||
| return RT_EOK; | ||
| } | ||
|
|
||
| static inline int wifi_freq_to_channel(uint16_t freq) | ||
| { | ||
| if ((freq >= 2412) && (freq <= 2484)) { | ||
| if (freq == 2484) | ||
| return 14; | ||
| else | ||
| return (freq - 2407) / 5; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| static void scan_done_callback(void *eloop_data, void *user_ctx) | ||
| { | ||
| int idx; | ||
| struct macif_scan_results *results = RT_NULL; | ||
| struct mac_scan_result *bss_info = RT_NULL; | ||
| struct rt_wlan_info wlan_info; | ||
| struct rt_wlan_buff buff; | ||
|
|
||
| results = (struct macif_scan_results *)rt_malloc(sizeof(struct macif_scan_results)); | ||
| if (RT_NULL == results) { | ||
| LOG_E("Failed to allocate memory for scan results\r\n"); | ||
| return; | ||
| } | ||
|
|
||
| if (wifi_netlink_scan_results_get(WIFI_VIF_STA, results)) { | ||
| rt_free(results); | ||
| rt_kprintf("WIFI scan results get failed\r\n"); | ||
| return; | ||
| } | ||
|
|
||
| for (idx = 0; idx < results->result_cnt; idx++) { | ||
| bss_info = &results->result[idx]; | ||
|
|
||
| rt_memset(&wlan_info, 0, sizeof(wlan_info)); | ||
|
|
||
| rt_memcpy(&wlan_info.bssid[0], (char *)bss_info->bssid.array, MAC_ADDR_LEN); | ||
| rt_memcpy(wlan_info.ssid.val, (char *)bss_info->ssid.array, bss_info->ssid.length); | ||
| wlan_info.ssid.len = bss_info->ssid.length; | ||
| wlan_info.hidden = bss_info->ssid.length > 0 ? 0 : 1; | ||
|
|
||
| wlan_info.channel = wifi_freq_to_channel(bss_info->chan->freq); | ||
| wlan_info.rssi = bss_info->rssi; | ||
| wlan_info.band = RT_802_11_BAND_2_4GHZ; | ||
|
|
||
| wlan_info.security = SECURITY_UNKNOWN; | ||
|
|
||
| if (bss_info->akm & CO_BIT(MAC_AKM_NONE)) { | ||
| wlan_info.security = SECURITY_OPEN; | ||
| } else if (bss_info->akm == CO_BIT(MAC_AKM_PRE_RSN)) { | ||
| wlan_info.security = SECURITY_WEP_PSK; | ||
| } else if (bss_info->akm & CO_BIT(MAC_AKM_PRE_RSN)) { // WPA | ||
| if (bss_info->pairwise_cipher & CO_BIT(MAC_CIPHER_TKIP)) { | ||
| wlan_info.security = SECURITY_WPA_TKIP_PSK; | ||
| } else if (bss_info->pairwise_cipher & CO_BIT(MAC_CIPHER_CCMP)) { | ||
| wlan_info.security = SECURITY_WPA_AES_PSK; | ||
| } | ||
| } else { // WPA2 | ||
| if ((bss_info->pairwise_cipher & CO_BIT(MAC_CIPHER_TKIP)) && | ||
| (bss_info->pairwise_cipher & CO_BIT(MAC_CIPHER_CCMP))) { | ||
| wlan_info.security = SECURITY_WPA2_MIXED_PSK; | ||
| } else if (bss_info->pairwise_cipher & CO_BIT(MAC_CIPHER_TKIP)) { | ||
| wlan_info.security = SECURITY_WPA2_TKIP_PSK; | ||
| } else if (bss_info->pairwise_cipher & CO_BIT(MAC_CIPHER_CCMP)) { | ||
| wlan_info.security = SECURITY_WPA2_AES_PSK; | ||
| } | ||
| } | ||
|
|
||
| buff.data = &wlan_info; | ||
| buff.len = sizeof(wlan_info); | ||
| rt_wlan_dev_indicate_event_handle(wlan_sta_device.wlan, RT_WLAN_DEV_EVT_SCAN_REPORT, &buff); | ||
| } | ||
|
|
||
| rt_free(results); | ||
| rt_wlan_dev_indicate_event_handle(wlan_sta_device.wlan, RT_WLAN_DEV_EVT_SCAN_DONE, RT_NULL); | ||
|
|
||
| eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_DONE); | ||
| eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_FAIL); | ||
| } | ||
|
|
||
| static void scan_fail_callback(void *eloop_data, void *user_ctx) | ||
| { | ||
| rt_kprintf("WIFI_SCAN: failed\r\n"); | ||
| eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_DONE); | ||
| eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_FAIL); | ||
| } | ||
|
|
||
| /** | ||
| * @brief WiFi scan | ||
| */ | ||
| static rt_err_t gd32_wlan_scan(struct rt_wlan_device *wlan, struct rt_scan_info *scan_info) | ||
| { | ||
| // rt_kprintf("WiFi scan start\r\n"); | ||
|
|
||
| eloop_event_register(WIFI_MGMT_EVENT_SCAN_DONE, scan_done_callback, NULL, NULL); | ||
| eloop_event_register(WIFI_MGMT_EVENT_SCAN_FAIL, scan_fail_callback, NULL, NULL); | ||
|
|
||
| if (wifi_management_scan(false, NULL)) { | ||
| eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_DONE); | ||
| eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_FAIL); | ||
| rt_kprintf("Wifi scan failed\r\n"); | ||
| } | ||
|
|
||
| return RT_EOK; | ||
| } | ||
|
|
||
| static void sta_conn_success_cb(void *eloop_data, void *user_ctx) | ||
| { | ||
| LOG_D("WIFI_JOIN_SUCCESS"); | ||
| rt_kprintf("WiFi connected successfully\r\n"); | ||
|
|
||
| eloop_event_unregister(WIFI_MGMT_EVENT_CONNECT_SUCCESS); | ||
| eloop_event_unregister(WIFI_MGMT_EVENT_CONNECT_FAIL); | ||
|
|
||
| rt_wlan_dev_indicate_event_handle(wlan_sta_device.wlan, RT_WLAN_DEV_EVT_CONNECT, RT_NULL); | ||
| } | ||
|
|
||
| static void sta_conn_fail_cb(void *eloop_data, void *user_ctx) | ||
| { | ||
| LOG_D("WIFI_JOIN_FAILED"); | ||
| rt_kprintf("WiFi connection failed\r\n"); | ||
|
|
||
| eloop_event_unregister(WIFI_MGMT_EVENT_CONNECT_SUCCESS); | ||
| eloop_event_unregister(WIFI_MGMT_EVENT_CONNECT_FAIL); | ||
|
|
||
| rt_wlan_dev_indicate_event_handle(wlan_sta_device.wlan, RT_WLAN_DEV_EVT_CONNECT_FAIL, RT_NULL); | ||
| } | ||
|
|
||
| /** | ||
| * @brief WiFi join (connect to AP) | ||
| */ | ||
| static rt_err_t gd32_wlan_join(struct rt_wlan_device *wlan, struct rt_sta_info *sta_info) | ||
| { | ||
| LOG_D("WiFi join SSID: %s", sta_info->ssid.val); | ||
| // rt_kprintf("WiFi join start\r\n"); | ||
|
|
||
| // 先注销可能存在的旧回调 | ||
| eloop_event_unregister(WIFI_MGMT_EVENT_CONNECT_SUCCESS); | ||
| eloop_event_unregister(WIFI_MGMT_EVENT_CONNECT_FAIL); | ||
|
|
||
| if (wifi_management_connect(sta_info->ssid.val, sta_info->key.val, 0) < 0) { | ||
| rt_kprintf("WiFi join failed\r\n"); | ||
| return -RT_ERROR; | ||
| } | ||
|
|
||
| eloop_event_register(WIFI_MGMT_EVENT_CONNECT_SUCCESS, sta_conn_success_cb, NULL, NULL); | ||
| eloop_event_register(WIFI_MGMT_EVENT_CONNECT_FAIL, sta_conn_fail_cb, NULL, NULL); | ||
|
|
||
| return RT_EOK; | ||
| } | ||
|
|
||
| /** | ||
| * @brief WiFi softap start | ||
| */ | ||
| static rt_err_t gd32_wlan_softap(struct rt_wlan_device *wlan, struct rt_ap_info *ap_info) | ||
| { | ||
| LOG_D("WiFi softap start SSID: %s", ap_info->ssid.val); | ||
|
|
||
| wifi_ap_auth_mode_t auth_mode; | ||
| char *ssid = ap_info->ssid.val; | ||
| char *passwd = ap_info->key.val; | ||
| uint32_t channel = ap_info->channel; | ||
| uint32_t hidden = ap_info->hidden; | ||
|
|
||
| if (wifi_management_concurrent_get() == 0) { | ||
| wifi_management_concurrent_set(1); | ||
| } | ||
|
|
||
| switch (ap_info->security) | ||
| { | ||
| case SECURITY_OPEN: | ||
| passwd = RT_NULL; | ||
| auth_mode = AUTH_MODE_OPEN; | ||
| break; | ||
|
|
||
| case SECURITY_WEP_PSK: | ||
| case SECURITY_WEP_SHARED: | ||
| auth_mode = AUTH_MODE_WEP; | ||
| break; | ||
|
|
||
| case SECURITY_WPA_TKIP_PSK: | ||
| case SECURITY_WPA_AES_PSK: | ||
| auth_mode = AUTH_MODE_WPA; | ||
| break; | ||
|
|
||
| case SECURITY_WPA2_TKIP_PSK: | ||
| case SECURITY_WPA2_AES_PSK: | ||
| auth_mode = AUTH_MODE_WPA2; | ||
| break; | ||
|
|
||
| case SECURITY_WPA2_MIXED_PSK: | ||
| auth_mode = AUTH_MODE_WPA_WPA2; | ||
| break; | ||
|
|
||
| case SECURITY_UNKNOWN: | ||
| auth_mode = AUTH_MODE_UNKNOWN; | ||
| break; | ||
|
|
||
| default: | ||
| rt_kprintf("Unsupported AP security mode %d, set to OPEN\r\n", ap_info->security); | ||
| auth_mode = AUTH_MODE_OPEN; | ||
| break; | ||
| } | ||
|
|
||
| if (wifi_management_ap_start(ssid, passwd, channel, auth_mode, hidden) < 0) { | ||
| rt_kprintf("WiFi softap start failed\r\n"); | ||
| return -RT_ERROR; | ||
| } | ||
|
|
||
| rt_wlan_dev_indicate_event_handle(wlan_ap_device.wlan, RT_WLAN_DEV_EVT_AP_START, RT_NULL); | ||
|
|
||
| return RT_EOK; | ||
| } | ||
|
|
||
| /** | ||
| * @brief WiFi disconnect | ||
| */ | ||
| static rt_err_t gd32_wlan_disconnect(struct rt_wlan_device *wlan) | ||
| { | ||
| LOG_D("WiFi disconnect"); | ||
|
|
||
| wifi_management_disconnect(); | ||
|
|
||
| rt_wlan_dev_indicate_event_handle(wlan_sta_device.wlan, RT_WLAN_DEV_EVT_DISCONNECT, RT_NULL); | ||
|
|
||
| return RT_EOK; | ||
| } | ||
|
|
||
| /** | ||
| * @brief WiFi AP disconnect station | ||
| */ | ||
| static rt_err_t gd32_wlan_ap_stop(struct rt_wlan_device *wlan) | ||
| { | ||
| LOG_D("WiFi AP stop"); | ||
|
|
||
| if (wifi_management_concurrent_get() == 0) { | ||
| wifi_management_concurrent_set(1); | ||
| } | ||
|
|
||
| if (wifi_management_ap_stop() < 0) { | ||
| rt_kprintf("WiFi AP stop failed\r\n"); | ||
| return -RT_ERROR; | ||
| } | ||
|
|
||
| rt_wlan_dev_indicate_event_handle(wlan_ap_device.wlan, RT_WLAN_DEV_EVT_AP_STOP, RT_NULL); | ||
| return RT_EOK; | ||
| } | ||
|
|
||
| /** | ||
| * @brief WiFi AP deauthenticate station | ||
| */ | ||
| static rt_err_t gd32_wlan_ap_deauth(struct rt_wlan_device *wlan, rt_uint8_t mac[]) | ||
| { | ||
| LOG_D("WiFi AP deauth station"); | ||
|
|
||
| if (wifi_management_concurrent_get() == 0) { | ||
| wifi_management_concurrent_set(1); | ||
| } | ||
|
|
||
| if (wifi_management_ap_delete_client(mac) < 0) { | ||
| rt_kprintf("WiFi AP deauth station failed\r\n"); | ||
| return -RT_ERROR; | ||
| } | ||
|
|
||
| return RT_EOK; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Get WiFi RSSI | ||
| */ | ||
| static rt_err_t gd32_wlan_scan_stop(struct rt_wlan_device *wlan) | ||
| { | ||
| LOG_D("WiFi scan stop"); | ||
|
|
||
| /* TODO: Stop WiFi scan */ | ||
|
|
||
| return RT_EOK; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Get WiFi channel | ||
| */ | ||
| static int gd32_wlan_get_rssi(struct rt_wlan_device *wlan) | ||
| { | ||
| int rssi = 0; | ||
|
|
||
| /* TODO: Get current RSSI value */ | ||
|
|
||
| return rssi; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Set WiFi channel | ||
| */ | ||
| static rt_err_t gd32_wlan_set_channel(struct rt_wlan_device *wlan, int channel) | ||
| { | ||
| LOG_D("Set WiFi channel: %d", channel); | ||
|
|
||
| /* TODO: Set WiFi channel */ | ||
|
|
||
| return RT_EOK; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Get WiFi channel | ||
| */ | ||
| static int gd32_wlan_get_channel(struct rt_wlan_device *wlan) | ||
| { | ||
| int channel = 1; | ||
|
|
||
| /* TODO: Get current WiFi channel */ | ||
|
|
||
| return channel; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Set WiFi country code | ||
| */ | ||
| static rt_err_t gd32_wlan_set_country(struct rt_wlan_device *wlan, rt_country_code_t country_code) | ||
| { | ||
| LOG_D("Set WiFi country code: %d", country_code); | ||
|
|
||
| /* TODO: Set WiFi country code */ | ||
|
|
||
| return RT_EOK; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Get WiFi country code | ||
| */ | ||
| static rt_country_code_t gd32_wlan_get_country(struct rt_wlan_device *wlan) | ||
| { | ||
| /* TODO: Get WiFi country code */ | ||
|
|
||
| return RT_COUNTRY_CHINA; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Set WiFi MAC address | ||
| */ | ||
| static rt_err_t gd32_wlan_set_mac(struct rt_wlan_device *wlan, rt_uint8_t mac[]) | ||
| { | ||
| LOG_D("Set WiFi MAC: %02x:%02x:%02x:%02x:%02x:%02x", | ||
| mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); | ||
|
|
||
| /* TODO: Set WiFi MAC address */ | ||
|
|
||
| return RT_EOK; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Get WiFi MAC address | ||
| */ | ||
| static rt_err_t gd32_wlan_get_mac(struct rt_wlan_device *wlan, rt_uint8_t mac[]) | ||
| { | ||
| return RT_EOK; | ||
| } | ||
|
|
||
| /** | ||
| * @brief WiFi receive callback | ||
| */ | ||
| static int gd32_wlan_recv(struct rt_wlan_device *wlan, void *buff, int len) | ||
| { | ||
| /* 不需要实现 - GD32 SDK LwIP 内部处理数据接收 */ | ||
| /* 数据接收流程:*/ | ||
| /* 硬件中断 -> MAC层 -> net_if_input() -> lwip tcpip_input() -> 协议栈处理 */ | ||
|
|
||
| return RT_EOK; | ||
| } | ||
|
|
||
| /** | ||
| * @brief WiFi send | ||
| */ | ||
| static int gd32_wlan_send(struct rt_wlan_device *wlan, void *buff, int len) | ||
| { | ||
| /* 不需要实现 - GD32 SDK LwIP 内部处理数据发送 */ | ||
| /* 数据发送流程:*/ | ||
| /* 应用层 -> lwIP协议栈 -> netif->linkoutput() -> net_if_output() -> MAC层 */ | ||
|
|
There was a problem hiding this comment.
Using Chinese comments in code violates RT-Thread coding standards. Comments on lines 46-51, 200-201 should be in English. Also, comments on lines 427-442 should follow RT-Thread documentation conventions.
代码中使用中文注释违反 RT-Thread 编码规范。第 46-51、200-201 行的注释应使用英文。另外,427-442 行的注释应遵循 RT-Thread 文档约定。
| LFLAGS = DEVICE + ' -nostartfiles -Xlinker --gc-sections --specs=nano.specs --specs=nosys.specs ' + ' -T ' + LINK_FILE + ' -Wl,-Map=' + MAP_FILE | ||
| # 添加 --no-warn-mismatch 以忽略预编译库与当前工具链的特权规范版本差异 | ||
| # 添加 WiFi ROM 符号表 | ||
| import os |
拉取/合并请求描述:(PR description)
[
为什么提交这份PR (why to submit this PR)
添加wifi支持



需要合并
你的解决方案是什么 (what is your solution)
请提供验证的bsp和config (provide the config and bsp)
]
当前拉取/合并请求的状态 Intent for your PR
必须选择一项 Choose one (Mandatory):
代码质量 Code Quality:
我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:
#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up