Skip to content

Instantly share code, notes, and snippets.

@nickfox-taterli
Created October 4, 2025 15:06
Show Gist options
  • Select an option

  • Save nickfox-taterli/fa734689608c4951b25a5dd2041b72f2 to your computer and use it in GitHub Desktop.

Select an option

Save nickfox-taterli/fa734689608c4951b25a5dd2041b72f2 to your computer and use it in GitHub Desktop.
SDIO初始化流程分析 - 立创衡山派SDIO网卡

概述

本文档分析了基于Realtek RTL8189 WiFi芯片的SDIO初始化完整流程,从硬件初始化到SDIO通信建立,包括CID,CSD,CCCR等关键信息的处理.

1. 项目结构分析

1.1 核心文件结构

bsp/peripheral/wireless/realtek/
├── realtek_wifi_drv.c     # 主驱动程序入口
├── platform/
│   ├── sdio/
│   │   ├── wifi_io.c      # SDIO操作实现
│   │   ├── wifi_io.h      # SDIO接口定义
│   │   ├── include/card.h # SDIO卡结构定义
│   │   └── core/
│   │       └── sdio_irq.h # SDIO中断处理
│   └── rtwlan_bsp/
│       ├── rtwlan_bsp.c   # BSP层实现
│       └── rtwlan_bsp.h   # BSP接口定义
└── api/wifi/
    ├── wifi_conf.c        # WiFi配置管理
    ├── wifi_util.c        # WiFi工具函数
    └── wifi_util.h        # 工具函数接口

2. SDIO初始化流程

2.1 驱动初始化入口

2.1.1 主驱动入口 (realtek_wifi_drv.c)

int realtek_init(void)
{
    // 1. 配置WiFi电源控制GPIO
    wifi_power_pin = hal_gpio_name2pin(AIC_DEV_REALTEK_WLAN0_PWR_GPIO);
    if (wifi_power_pin > 0)
        hal_gpio_direction_output(GPIO_GROUP(wifi_power_pin),
                                  GPIO_GROUP_PIN(wifi_power_pin));

    // 2. 执行硬件复位
    realtek_reset();

    // 3. 注册SDIO驱动
    printf("wifi device id == 0x%x\n", realtek_drv.id->product);
    sdio_register_driver(&realtek_drv);

    return 0;
}

2.1.2 硬件复位函数

int realtek_reset(void)
{
    unsigned int g, p;

    /* power on pin */
    g = GPIO_GROUP(wifi_power_pin);
    p = GPIO_GROUP_PIN(wifi_power_pin);

    /* reset sequence */
    hal_gpio_set_value(g, p, 0);  // 拉低复位
    aicos_msleep(10);              // 延时10ms
    hal_gpio_set_value(g, p, 1);  // 拉高复位
    aicos_msleep(10);              // 延时10ms

    return 0;
}

2.2 SDIO设备探测

2.2.1 SDIO设备ID识别

struct rt_sdio_device_id realtex_id[]= {
#if defined(AIC_USING_RTL8733_WLAN0)
    { 1, 0x024c, 0xB733},  // RTL8733芯片ID
#elif defined(AIC_USING_RTL8189_WLAN0)
    { 1, 0x024c, 0xf179},  // RTL8189芯片ID
#endif
};

2.2.2 SDIO设备探测回调

static rt_int32_t realtek_probe(struct rt_mmcsd_card *card)
{
#ifdef REALTEK_WLAN_INTF_SDIO
    return (wifi_sdio_probe(card));
#else
    return 0;
#endif
}

2.3 SDIO功能初始化

2.3.1 SDIO功能初始化主流程 (wifi_io.c)

int wifi_sdio_probe(struct rt_mmcsd_card *card)
{
    /* 1. 保存系统SDIO卡和功能信息 */
    rtt_mmc_card = card;                    // 保存系统SDIO卡信息
    rtt_sdio_func = card->sdio_function[1]; // 获取SDIO功能1 (WiFi功能)

    /* 2. 创建RTL专用SDIO功能结构体 */
    wifi_sdio_func = aicos_malloc(MEM_DEFAULT, sizeof(struct sdio_func));
    if (wifi_sdio_func == NULL)
        return -ENOMEM;
    
    // 复制系统SDIO功能信息到RTL专用结构体
    copy_rtt_sdio_func(wifi_sdio_func, rtt_sdio_func);

    /* 3. 创建RTL专用SDIO卡结构体 */
    wifi_mmc_card = aicos_malloc(MEM_DEFAULT, sizeof(struct mmc_card));
    if (wifi_mmc_card == NULL)
        return -ENOMEM;
    
    // 复制系统SDIO卡信息到RTL专用结构体
    copy_rtt_mmc_card(wifi_mmc_card, rtt_mmc_card);
    
    // 建立关联关系
    wifi_mmc_card->sdio_func[1] = wifi_sdio_func;
    wifi_sdio_func->card = wifi_mmc_card;

    /* 4. 启用SDIO功能并设置块大小 */
    sdio_enable_func(rtt_sdio_func);
    sdio_set_block_size(rtt_sdio_func, 512);

    /* 5. 启动WiFi模块 */
    if(wifi_on(1)<0) {
        pr_err("ERROR: Wifi on failed!\n");
    }

    return 0;
}

2.4 CID,CSD,CCCR关键信息处理

2.4.1 CCCR (Common Card Configuration Register) 信息处理

static void copy_rtt_mmc_card(struct mmc_card *card, struct rt_mmcsd_card *rt_card)
{
    // 复制CCCR信息
    card->cccr.sdio_vsn = rt_card->cccr.sdio_version;   // SDIO版本号
    card->cccr.sd_vsn = rt_card->cccr.sd_version;       // SD版本号
    card->cccr.multi_block = rt_card->cccr.multi_block; // 是否支持多块传输
    card->cccr.low_speed = rt_card->cccr.low_speed;     // 是否为低速卡
    card->cccr.wide_bus = rt_card->cccr.bus_width;      // 是否支持宽总线
    card->cccr.high_power = rt_card->cccr.power_ctrl;   // 是否为高功耗卡
    card->cccr.high_speed = rt_card->cccr.high_speed;   // 是否为高速卡
    card->cccr.disable_cd = rt_card->cccr.cd_disable;   // 是否禁用卡检测
}

2.4.2 CIS (Common Tuple Information) 信息处理

static void copy_rtt_mmc_card(struct mmc_card *card, struct rt_mmcsd_card *rt_card)
{
    // 复制CIS信息
    card->cis.vendor = rt_card->cis.manufacturer;        // 制造商ID
    card->cis.device = rt_card->cis.product;             // 产品ID
    card->cis.blksize = rt_card->cis.func0_blk_size;     // 功能0块大小
    card->cis.max_dtr = rt_card->cis.max_tran_speed;     // 最大传输速率
}

2.4.3 SDIO功能信息处理

static void copy_rtt_sdio_func(struct sdio_func *func, struct rt_sdio_function *rt_func)
{
    // 复制SDIO功能信息
    func->max_blksize = rt_func->max_blk_size;    // 最大块大小
    func->cur_blksize = rt_func->cur_blk_size;    // 当前块大小
    func->enable_timeout = rt_func->enable_timeout_val; // 启用超时时间
    func->num = rt_func->num;                     // 功能号
    func->vendor = rt_func->manufacturer;         // 厂商ID
    func->device = rt_func->product;              // 产品ID
}

3. SDIO通信机制

3.1 SDIO总线操作接口

3.1.1 SDIO总线操作结构体

typedef struct _SDIO_BUS_OPS{
    int (*bus_probe)(void);                           // 总线探测
    int (*bus_remove)(void);                          // 总线移除
    int (*enable)(struct sdio_func*func);             // 启用功能
    int (*disable)(struct sdio_func *func);           // 禁用功能
    int (*reg_driver)(struct sdio_driver*);           // 注册驱动
    void (*unreg_driver)(struct sdio_driver *);       // 注销驱动
    int (*claim_irq)(struct sdio_func *func, void(*handler)(struct sdio_func *)); // 申请中断
    int (*release_irq)(struct sdio_func*func);        // 释放中断
    void (*claim_host)(struct sdio_func*func);        // 主机控制权获取
    void (*release_host)(struct sdio_func *func);     // 主机控制权释放
    unsigned char (*readb)(struct sdio_func *func, unsigned int addr, int *err_ret); // 读字节
    unsigned short (*readw)(struct sdio_func *func, unsigned int addr, int *err_ret); // 读字
    unsigned int (*readl)(struct sdio_func *func, unsigned int addr, int *err_ret);   // 读长字
    void (*writeb)(struct sdio_func *func, unsigned char b,unsigned int addr, int *err_ret); // 写字节
    void (*writew)(struct sdio_func *func, unsigned short b,unsigned int addr, int *err_ret); // 写字
    void (*writel)(struct sdio_func *func, unsigned int b,unsigned int addr, int *err_ret);   // 写长字
    int (*memcpy_fromio)(struct sdio_func *func, void *dst,unsigned int addr, int count); // 从IO复制内存
    int (*memcpy_toio)(struct sdio_func *func, unsigned int addr,void *src, int count);     // 向IO复制内存
} SDIO_BUS_OPS;

3.1.2 SDIO总线操作实现

SDIO_BUS_OPS rtw_sdio_bus_ops = {
    rtt_sdio_bus_probe,           // 总线探测
    rtt_sdio_bus_remove,          // 总线移除
    rtt_sdio_enable_func,         // 启用功能
    rtt_sdio_disable_func,        // 禁用功能
    NULL,                         // 注册驱动
    NULL,                         // 注销驱动
    rtt_sdio_claim_irq,           // 申请中断
    rtt_sdio_release_irq,         // 释放中断
    rtt_sdio_claim_host,          // 获取主机控制权
    rtt_sdio_release_host,        // 释放主机控制权
    rtt_sdio_readb,              // 读字节
    rtt_sdio_readw,              // 读字
    rtt_sdio_readl,              // 读长字
    rtt_sdio_writeb,             // 写字节
    rtt_sdio_writew,             // 写字
    rtt_sdio_writel,             // 写长字
    rtt_sdio_memcpy_fromio,      // 从IO复制内存
    rtt_sdio_memcpy_toio,        // 向IO复制内存
};

3.2 SDIO数据读写操作

3.2.1 基础读写函数

// 读操作
int wifi_read(struct sdio_func *func, u32 addr, u32 cnt, void *pdata)
{
    int err;
    
    // 获取SDIO主机控制权
    rtt_sdio_claim_host(func);
    
    // 执行数据读取
    err = rtt_sdio_memcpy_fromio(func, pdata, addr, cnt);
    if (err) {
        pr_err("%s: FAIL(%d)! ADDR=%#x Size=%d\n", __func__, err, addr, cnt);
    }
    
    // 释放SDIO主机控制权
    rtt_sdio_release_host(func);
    
    return err;
}

// 写操作
int wifi_write(struct sdio_func *func, u32 addr, u32 cnt, void *pdata)
{
    int err;
    u32 size;
    
    // 获取SDIO主机控制权
    rtt_sdio_claim_host(func);
    
    // 执行数据写入
    size = cnt;
    err = rtt_sdio_memcpy_toio(func, addr, pdata, size);
    if (err) {
        pr_err("%s: FAIL(%d)! ADDR=%#x Size=%d(%d)\n", __func__, err, addr, cnt, size);
    }
    
    // 释放SDIO主机控制权
    rtt_sdio_release_host(func);
    
    return err;
}

3.2.2 寄存器读写函数

// 读取8位寄存器
u8 wifi_readb(struct sdio_func *func, u32 addr)
{
    int err;
    u8 ret = 0;
    
    rtt_sdio_claim_host(func);
    ret = rtt_sdio_readb(func, ADDR_MASK | addr, &err);
    rtt_sdio_release_host(func);
    if (err)
        pr_err("%s: FAIL!(%d) addr=0x%05x\n", __func__, err, addr);
    
    return ret;
}

// 写入8位寄存器
void wifi_writeb(struct sdio_func *func, u32 addr, u8 val)
{
    int err;
    
    rtt_sdio_claim_host(func);
    rtt_sdio_writeb(func, val, ADDR_MASK | addr, &err);
    rtt_sdio_release_host(func);
    if (err)
        pr_err("%s: FAIL!(%d) addr=0x%05x val=0x%02x\n", __func__, err, addr, val);
}

3.3 SDIO中断处理

3.3.1 中断申请和释放

// 申请中断
static int rtt_sdio_claim_irq(struct sdio_func *func, void (*handler)(struct sdio_func *))
{
    wifi_irq_handler = handler;  // 保存中断处理函数
    return sdio_attach_irq(rtt_sdio_func, rtt_sdio_irq_handler);
}

// 释放中断
static int rtt_sdio_release_irq(struct sdio_func *func)
{
    sdio_detach_irq(rtt_sdio_func);
    wifi_irq_handler = NULL;    // 清空中断处理函数
    return 0;
}

3.3.2 中断处理线程

// SDIO中断处理函数
static void rtt_sdio_irq_handler(struct rt_sdio_function * rt_func)
{
    // 调用上层注册的中断处理函数
    wifi_irq_handler(wifi_sdio_func);
}

4. WiFi模块初始化

4.1 WiFi启动流程

4.1.1 WiFi启动主函数 (wifi_conf.c)

int wifi_on(rtw_mode_t mode)
{
    int ret = 1;
    int timeout = 20;
    int idx;
    int devnum = 1;
    static int event_init = 0;

    // 检查WiFi是否已经运行
    if(rltk_wlan_running(WLAN0_IDX)) {
        pr_info("WIFI is already running\n");
        return 1;
    }

    // 初始化事件回调
    if(event_init == 0){
        init_event_callback_list();
        event_init = 1;
    }

    // 设置WiFi模式
    wifi_mode = mode;

    if(mode == RTW_MODE_STA_AP)
        devnum = 2;  // 双模式需要2个设备

    // 初始化WiFi设备
    for(idx=0; idx<devnum; idx++){
        ret = rltk_wlan_init(idx, mode);
        if(ret <0)
            return ret;
    }

    // 启动WiFi设备
    for(idx=0; idx<devnum; idx++){
        device_mutex_lock(RT_DEV_LOCK_WLAN);
        ret = rltk_wlan_start(idx);
        if(ret == 0) _wifi_is_on = 1;
        device_mutex_unlock(RT_DEV_LOCK_WLAN);
        if(ret <0){
            pr_info("ERROR: Start WIFI Failed!\n");
            rltk_wlan_deinit();
            return ret;
        }
    }

    // 等待WiFi启动完成
    while(1) {
        if(rltk_wlan_running(devnum-1)) {
            pr_info("WIFI initialized\n");
            wifi_set_country_code();  // 设置国家代码
            break;
        }
        if(timeout == 0) {
            pr_info("ERROR: Init WIFI timeout!\n");
            break;
        }
        rtw_msleep_os(1000);
        timeout--;
    }

    return ret;
}

4.2 WiFi配置管理

4.2.1 网络连接配置

// WiFi连接配置
static int wifi_connect_local(rtw_network_info_t *pWifi)
{
    int ret = 0;

    if(!pWifi) return -1;
    
    // 根据安全类型设置加密参数
    switch(pWifi->security_type){
        case RTW_SECURITY_OPEN:
            ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_NONE, NULL, 0, 0, 0, 0, NULL, 0);
            break;
        case RTW_SECURITY_WEP_PSK:
        case RTW_SECURITY_WEP_SHARED:
            ret = wext_set_auth_param(WLAN0_NAME, IW_AUTH_80211_AUTH_ALG, IW_AUTH_ALG_SHARED_KEY);
            if(ret == 0)
                ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_WEP, NULL, pWifi->key_id, 1, 0, 0, pWifi->password, pWifi->password_len);
            break;
        case RTW_SECURITY_WPA_TKIP_PSK:
        case RTW_SECURITY_WPA2_TKIP_PSK:
            ret = wext_set_auth_param(WLAN0_NAME, IW_AUTH_80211_AUTH_ALG, IW_AUTH_ALG_OPEN_SYSTEM);
            if(ret == 0)
                ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_TKIP, NULL, 0, 0, 0, 0, NULL, 0);
            if(ret == 0)
                ret = wext_set_passphrase(WLAN0_NAME, pWifi->password, pWifi->password_len);
            break;
        case RTW_SECURITY_WPA_AES_PSK:
        case RTW_SECURITY_WPA2_AES_PSK:
        case RTW_SECURITY_WPA2_MIXED_PSK:
            ret = wext_set_auth_param(WLAN0_NAME, IW_AUTH_80211_AUTH_ALG, IW_AUTH_ALG_OPEN_SYSTEM);
            if(ret == 0)
                ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_CCMP, NULL, 0, 0, 0, 0, NULL, 0);
            if(ret == 0)
                ret = wext_set_passphrase(WLAN0_NAME, pWifi->password, pWifi->password_len);
            break;
        default:
            ret = -1;
            pr_info("WIFICONF: security type(0x%x) is not supported.\r\n", pWifi->security_type);
            break;
    }
    
    // 设置SSID
    if(ret == 0)
        ret = wext_set_ssid(WLAN0_NAME, pWifi->ssid.val, pWifi->ssid.len);
    
    return ret;
}

5. RTL8189通信机制

5.1 通信接口层

5.1.1 WEXT接口实现

// WEXT接口实现 - wifi_util.c
int wext_set_ssid(const char *ifname, const __u8 *ssid, __u16 ssid_len)
{
    struct iwreq iwr;
    int ret = 0;

    memset(&iwr, 0, sizeof(iwr));
    iwr.u.essid.pointer = (void *) ssid;
    iwr.u.essid.length = ssid_len;
    iwr.u.essid.flags = (ssid_len != 0);

    if (iw_ioctl(ifname, SIOCSIWESSID, &iwr) < 0) {
        pr_info("ioctl[SIOCSIWESSID] error");
        ret = -1;
    }

    return ret;
}

int wext_get_bssid(const char*ifname, __u8 *bssid)
{
    struct iwreq iwr;
    int ret = 0;

    memset(&iwr, 0, sizeof(iwr));

    if (iw_ioctl(ifname, SIOCGIWAP, &iwr) < 0) {
        pr_info("ioctl[SIOCSIWAP] error");
        ret = -1;
    } else {
        memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN);
    }

    return ret;
}

5.2 数据传输机制

5.2.1 原始数据传输

// 原始数据发送
int wext_send_rawdata(const char *ifname, const char* frame_buf, unsigned int frame_len)
{
    struct iwreq iwr;
    int ret = 0;
    
    memset(&iwr, 0, sizeof(iwr));
    iwr.u.data.pointer = (void*)frame_buf;
    iwr.u.data.length = frame_len;
    
    if (iw_ioctl(ifname, SOICSIWDIRSEND, &iwr) < 0) {
        pr_info("ioctl[SOICSIWDIRSEND] error");
        ret = -1;
    }
    
    return ret;
}

// 原始数据接收控制
int wext_enable_rawdata_recv(const char *ifname, void *fun)
{
    struct iwreq iwr;
    int ret = 0;
    
    memset(&iwr, 0, sizeof(iwr));
    iwr.u.data.pointer = fun;
    
    if (iw_ioctl(ifname, SIOCSIWRAWENABLE, &iwr) < 0) {
        pr_info("ioctl[SIOCSIWRAWENABLE] error");
        ret = -1;
    }
    
    return ret;
}

5.3 事件处理机制

5.3.1 WiFi事件处理

// WiFi事件指示函数
void wext_wlan_indicate(unsigned int cmd, union iwreq_data *wrqu, char *extra)
{
    unsigned char null_mac[6] = {0};

    switch(cmd) {
        case SIOCGIWAP:
            // 处理连接/断开事件
            if(wrqu->ap_addr.sa_family == ARPHRD_ETHER) {
                if(!memcmp(wrqu->ap_addr.sa_data, null_mac, sizeof(null_mac)))
                    wifi_indication(WIFI_EVENT_DISCONNECT, wrqu->ap_addr.sa_data, sizeof(null_mac)+ 2, 0);
                else
                    wifi_indication(WIFI_EVENT_CONNECT, wrqu->ap_addr.sa_data, sizeof(null_mac), 0);
            }
            break;

        case IWEVCUSTOM:
            // 处理自定义事件
            if(extra) {
                if(!memcmp(IW_EXT_STR_FOURWAY_DONE, extra, strlen(IW_EXT_STR_FOURWAY_DONE)))
                    wifi_indication(WIFI_EVENT_FOURWAY_HANDSHAKE_DONE, extra, strlen(IW_EXT_STR_FOURWAY_DONE), 0);
                else if(!memcmp(IW_EXT_STR_RECONNECTION_FAIL, extra, strlen(IW_EXT_STR_RECONNECTION_FAIL)))
                    wifi_indication(WIFI_EVENT_RECONNECTION_FAIL, extra, strlen(IW_EXT_STR_RECONNECTION_FAIL), 0);
                // 其他事件处理...
            }
            break;
            
        case SIOCGIWSCAN:
            // 处理扫描结果
            if(wrqu->data.pointer == NULL)
                wifi_indication(WIFI_EVENT_SCAN_DONE, NULL, 0, 0);
            else
                wifi_indication(WIFI_EVENT_SCAN_RESULT_REPORT, wrqu->data.pointer, wrqu->data.length, 0);
            break;
            
        default:
            break;
    }
}

6. 完整初始化流程总结

6.1 硬件初始化阶段

  1. GPIO配置: 配置WiFi电源控制GPIO
  2. 硬件复位: 执行WiFi芯片复位序列
  3. SDIO总线初始化: 初始化SDIO控制器

6.2 SDIO设备识别阶段

  1. 设备ID匹配: 通过SDIO设备ID识别Realtek芯片
  2. 功能探测: 探测SDIO功能1 (WiFi功能)
  3. 信息获取: 读取CID,CSD,CCCR等关键信息

6.3 驱动初始化阶段

  1. 数据结构初始化: 创建和初始化SDIO相关数据结构
  2. 总线操作注册: 注册SDIO总线操作接口
  3. 中断处理初始化: 初始化SDIO中断处理机制
  4. 内存映射: 建立SDIO内存映射关系

6.4 WiFi模块启动阶段

  1. WiFi芯片初始化: 初始化RTL8189 WiFi芯片
  2. 固件加载: 加载WiFi固件
  3. 模式配置: 配置STA/AP/STA+AP工作模式
  4. 网络栈初始化: 初始化网络协议栈

6.5 通信建立阶段

  1. 网络扫描: 扫描可用WiFi网络
  2. 连接建立: 建立与目标AP的连接
  3. 数据传输: 建立双向数据传输通道
  4. 事件监控: 监控WiFi连接状态变化

6.6 应用接口阶段

  1. WEXT接口: 提供标准WEXT用户接口
  2. 事件回调: 提供WiFi事件回调机制
  3. 配置管理: 提供WiFi参数配置接口
  4. 状态查询: 提供WiFi状态查询接口

7. 关键技术点

7.1 SDIO地址映射

  • 地址掩码: 使用ADDR_MASK (0x10000)LOCAL_ADDR_MASK (0x00000)区分不同地址空间
  • 寄存器访问: 通过wifi_readb/wifi_writeb等函数访问芯片寄存器

7.2 中断处理机制

  • 中断线程: 通过sdio_irq_thread处理SDIO中断
  • 事件分发: 通过wifi_indication函数分发WiFi事件

7.3 内存管理

  • 动态分配: 使用aicos_malloc动态分配内存
  • 内存释放: 使用aicos_free释放分配的内存

7.4 错误处理

  • 错误检查: 在关键操作点进行错误检查
  • 超时处理: 设置合理的超时时间
  • 资源清理: 在错误情况下正确清理资源

8. 性能优化建议

8.1 SDIO优化

  1. 块大小优化: 根据应用需求调整SDIO块大小
  2. 批量传输: 使用批量传输减少事务开销
  3. 中断优化: 优化中断处理频率和时间

8.2 内存优化

  1. 内存池: 使用内存池减少内存分配开销
  2. 缓存优化: 优化数据缓存策略
  3. DMA使用: 使用DMA提高数据传输效率

8.3 功耗优化

  1. 电源管理: 实现WiFi芯片的电源管理
  2. 低功耗模式: 支持低功耗工作模式
  3. 动态调频: 根据负载动态调整工作频率

本文档基于对Luban-Lite项目中Realtek RTL8189 WiFi驱动的深入分析,详细描述了SDIO初始化的完整流程,为WiFi驱动的开发和调试提供了重要的技术参考.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment