本文档分析了基于Realtek RTL8189 WiFi芯片的SDIO初始化完整流程,从硬件初始化到SDIO通信建立,包括CID,CSD,CCCR等关键信息的处理.
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 # 工具函数接口
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;
}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;
}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
};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
}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;
}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; // 是否禁用卡检测
}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; // 最大传输速率
}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
}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;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复制内存
};// 读操作
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;
}// 读取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);
}// 申请中断
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;
}// SDIO中断处理函数
static void rtt_sdio_irq_handler(struct rt_sdio_function * rt_func)
{
// 调用上层注册的中断处理函数
wifi_irq_handler(wifi_sdio_func);
}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;
}// 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;
}// 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;
}// 原始数据发送
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;
}// 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;
}
}- GPIO配置: 配置WiFi电源控制GPIO
- 硬件复位: 执行WiFi芯片复位序列
- SDIO总线初始化: 初始化SDIO控制器
- 设备ID匹配: 通过SDIO设备ID识别Realtek芯片
- 功能探测: 探测SDIO功能1 (WiFi功能)
- 信息获取: 读取CID,CSD,CCCR等关键信息
- 数据结构初始化: 创建和初始化SDIO相关数据结构
- 总线操作注册: 注册SDIO总线操作接口
- 中断处理初始化: 初始化SDIO中断处理机制
- 内存映射: 建立SDIO内存映射关系
- WiFi芯片初始化: 初始化RTL8189 WiFi芯片
- 固件加载: 加载WiFi固件
- 模式配置: 配置STA/AP/STA+AP工作模式
- 网络栈初始化: 初始化网络协议栈
- 网络扫描: 扫描可用WiFi网络
- 连接建立: 建立与目标AP的连接
- 数据传输: 建立双向数据传输通道
- 事件监控: 监控WiFi连接状态变化
- WEXT接口: 提供标准WEXT用户接口
- 事件回调: 提供WiFi事件回调机制
- 配置管理: 提供WiFi参数配置接口
- 状态查询: 提供WiFi状态查询接口
- 地址掩码: 使用
ADDR_MASK (0x10000)和LOCAL_ADDR_MASK (0x00000)区分不同地址空间 - 寄存器访问: 通过
wifi_readb/wifi_writeb等函数访问芯片寄存器
- 中断线程: 通过
sdio_irq_thread处理SDIO中断 - 事件分发: 通过
wifi_indication函数分发WiFi事件
- 动态分配: 使用
aicos_malloc动态分配内存 - 内存释放: 使用
aicos_free释放分配的内存
- 错误检查: 在关键操作点进行错误检查
- 超时处理: 设置合理的超时时间
- 资源清理: 在错误情况下正确清理资源
- 块大小优化: 根据应用需求调整SDIO块大小
- 批量传输: 使用批量传输减少事务开销
- 中断优化: 优化中断处理频率和时间
- 内存池: 使用内存池减少内存分配开销
- 缓存优化: 优化数据缓存策略
- DMA使用: 使用DMA提高数据传输效率
- 电源管理: 实现WiFi芯片的电源管理
- 低功耗模式: 支持低功耗工作模式
- 动态调频: 根据负载动态调整工作频率
本文档基于对Luban-Lite项目中Realtek RTL8189 WiFi驱动的深入分析,详细描述了SDIO初始化的完整流程,为WiFi驱动的开发和调试提供了重要的技术参考.