Skip to content

[bsp][gd32]:gd32vw553h-eval add wifi support#11175

Open
CYFS3 wants to merge 1 commit intoRT-Thread:masterfrom
CYFS3:gd32_wifi
Open

[bsp][gd32]:gd32vw553h-eval add wifi support#11175
CYFS3 wants to merge 1 commit intoRT-Thread:masterfrom
CYFS3:gd32_wifi

Conversation

@CYFS3
Copy link
Contributor

@CYFS3 CYFS3 commented Feb 5, 2026

拉取/合并请求描述:(PR description)

[

为什么提交这份PR (why to submit this PR)

添加wifi支持
image
image
image

需要合并

你的解决方案是什么 (what is your solution)

请提供验证的bsp和config (provide the config and bsp)

  • BSP:
  • .config:
  • action:

]

当前拉取/合并请求的状态 Intent for your PR

必须选择一项 Choose one (Mandatory):

  • 本拉取/合并请求是一个草稿版本 This PR is for a code-review and is intended to get feedback
  • 本拉取/合并请求是一个成熟版本 This PR is mature, and ready to be integrated into the repo

代码质量 Code Quality:

我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:

  • 已经仔细查看过代码改动的对比 Already check the difference between PR and old code
  • 代码风格正确,包括缩进空格,命名及其他风格 Style guide is adhered to, including spacing, naming and other styles
  • 没有垃圾代码,代码尽量精简,不包含#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up
  • 所有变更均有原因及合理的,并且不会影响到其他软件组件代码或BSP All modifications are justified and not affect other components or BSP
  • 对难懂代码均提供对应的注释 I've commented appropriately where code is tricky
  • 代码是高质量的 Code in this PR is of high quality
  • 已经使用formatting 等源码格式化工具确保格式符合RT-Thread代码规范 This PR complies with RT-Thread code specification
  • 如果是新增bsp, 已经添加ci检查到.github/ALL_BSP_COMPILE.json 详细请参考链接BSP自查

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread!

为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。
To ensure your code complies with RT-Thread's coding style, please run the code formatting workflow by following the steps below (If the formatting of CI fails to run).


🛠 操作步骤 | Steps

  1. 前往 Actions 页面 | Go to the Actions page
    点击进入工作流 → | Click to open workflow →

  2. 点击 Run workflow | Click Run workflow

  • 设置需排除的文件/目录(目录请以"/"结尾)
    Set files/directories to exclude (directories should end with "/")
  • 将目标分支设置为 \ Set the target branch to:gd32_wifi
  • 设置PR number为 \ Set the PR number to:11175
  1. 等待工作流完成 | Wait for the workflow to complete
    格式化后的代码将自动推送至你的分支。
    The formatted code will be automatically pushed to your branch.

完成后,提交将自动更新至 gd32_wifi 分支,关联的 Pull Request 也会同步更新。
Once completed, commits will be pushed to the gd32_wifi branch automatically, and the related Pull Request will be updated.

如有问题欢迎联系我们,再次感谢您的贡献!💐
If you have any questions, feel free to reach out. Thanks again for your contribution!

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

📌 Code Review Assignment

🏷️ Tag: components

Reviewers: @Maihuanyi

Changed Files (Click to expand)
  • components/drivers/wlan/dev_wlan_cmd.c
  • components/net/lwip/port/SConscript

🏷️ Tag: libcpu_riscv

Reviewers: @Yaochenger

Changed Files (Click to expand)
  • libcpu/risc-v/common/interrupt_gcc.S

📊 Current Review Status (Last Updated: 2026-02-05 15:23 CST)


📝 Review Instructions

  1. 维护者可以通过单击此处来刷新审查状态: 🔄 刷新状态
    Maintainers can refresh the review status by clicking here: 🔄 Refresh Status

  2. 确认审核通过后评论 LGTM/lgtm
    Comment LGTM/lgtm after confirming approval

  3. PR合并前需至少一位维护者确认
    PR must be confirmed by at least one maintainer before merging

ℹ️ 刷新CI状态操作需要具备仓库写入权限。
ℹ️ Refresh CI status operation requires repository Write permission.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment on lines +28 to +61
#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 */
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 指南使用英文。

Copilot generated this review using guidance from repository custom instructions.
Comment on lines +39 to +72
_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
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. Using linker section attributes in source code (e.g., __attribute__((section(".fast_text")))
  2. Adding comments explaining why each file/function needs to be in RAM
  3. Documenting the performance impact measurements that justified this optimization

链接器脚本添加了 .code_to_sram 段,将特定代码复制到 RAM 以提高性能。但是,段选择过于具体,使用了 *trap_gcc.o**rxl_hwdesc.o* 等通配符。这种与特定目标文件名的紧密耦合很脆弱且难以维护。考虑使用更可维护的方法,例如:

  1. 在源代码中使用链接器段属性(如 __attribute__((section(".fast_text"))))
  2. 添加注释说明为什么每个文件/函数需要在 RAM 中
  3. 记录证明此优化合理性的性能影响测量结果

Copilot uses AI. Check for mistakes.
Comment on lines +46 to +66
# 使用单精度硬件浮点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
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. Documenting this limitation in the BSP README
  2. Warning users that existing code using double-precision may have performance degradation or precision issues
  3. 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 破坏。这迫使所有代码使用单精度浮点。注释解释了原因,但请考虑:

  1. 在 BSP README 中记录此限制
  2. 警告用户现有使用双精度的代码可能出现性能下降或精度问题
  3. 验证 RT-Thread 和 lwIP 不依赖双精度浮点

--no-warn-mismatch 标志抑制了关于 ABI 不匹配的重要链接器警告。这很危险,因为它可以隐藏真正的兼容性问题。考虑请求使用正确架构的更新 WiFi 库。

Copilot uses AI. Check for mistakes.
Comment on lines +156 to +167
// 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;
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 行)
  • 等等

这使调用者无法检测初始化失败,并使调试更加困难。

Suggested change
// 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;

Copilot uses AI. Check for mistakes.
Comment on lines +84 to +95
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++) {
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,导致崩溃。添加适当的错误处理。

Suggested change
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++)
{

Copilot uses AI. Check for mistakes.
{"prot", wifi_debug_set_prot},
{"auto", wifi_debug_set_autoconnect},
#else
{"mode", wifi_debug_set_mode },
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 数组中造成歧义。删除重复条目。

Copilot uses AI. Check for mistakes.
Comment on lines +105 to +109
#ifdef SOC_GD32VW553H
call rt_hw_do_after_save_above
#else
jal rt_hw_do_after_save_above
#endif
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 平台。

Copilot uses AI. Check for mistakes.
Comment on lines +113 to +119
#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 */
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 实现,或使其可配置以支持所有需要它的平台。

Copilot uses AI. Check for mistakes.
Comment on lines +46 to +442
{
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层 */

Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 文档约定。

Copilot generated this review using guidance from repository custom instructions.
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
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import of module os is redundant, as it was previously imported on line 1.

Suggested change
import os

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant