我们从2011年坚守至今,只想做存粹的技术论坛。  由于网站在外面,点击附件后要很长世间才弹出下载,请耐心等待,勿重复点击不要用Edge和IE浏览器下载,否则提示不安全下载不了

 找回密码
 立即注册
搜索
查看: 708|回复: 4

灯控节点网络驱动编写

[复制链接]

该用户从未签到

4

主题

1

回帖

0

积分

一级逆天

积分
0

终身成就奖

QQ
发表于 2017-4-19 18:44:12 | 显示全部楼层 |阅读模式
灯控节点设备的网卡驱动的编写
驱动是衔接用户软件操作系统和硬件的重要接口,主要有以下几个作用:
(1) 硬件的上电识别
(2) 硬件固件下载,寄存器的初始化
(3) 向上层提供抽象的硬件接口,封装
(4) 向上层提供读写网卡命令寄存器的命令封包 Marvell/cmd.c,封装底层与上层之间数
据交互的函数
(5)执行网卡扫描、关联等操作
本文的难点在于驱动的移植,同一款无线网卡,对于不同的操作系统、不同架构的 CPU、
不同的接口,其相应的驱动也不同[25]。 Marvell 88w8686 提供了基于 Linux 操作系统的 SPI 口
驱动,没有提供无操作系统的驱动。本文在参考 rt-thread 提供的 SPI 驱动和 Marvell 提供的裁
剪 Linux 操作系统驱动的基础上,基于 SDIO 接口下载了 88w8686 固件、设计和移植了驱动
程序。上层调用与主机驱动,主机驱动和底层固件的基本关系框架如下图所示:
Applications
TCP UDP
IP
以太网驱动 802.11扩展单元
硬件接口驱动
硬件接口
硬件接口驱动
通用驱动接口
数据服务
(Tx/Rx 缓冲区管理 )
802.11 MAC


WLAN 驱动
硬件接口驱动层
WLAN Firmware Host Driver
Data Path
Control Path
LWIP
3.9 主机驱动和底层固件的软件架构
硬件接口即 SDIO 接口,网卡通过 SDIO 总线接入 STM32。从硬件方面分析,接口上方
是 HOST 即 STM32,接口下方是设备即无线网卡[26]。 STM32 通过 SDIO 口的 CMD PATH 发
送命令对无线网卡寄存器进行操作,通过 SDIO 口的 DATA PATH 将数据发送到无线网卡 Tx
缓冲区再经由无线网卡发送出去,同时读取网卡的缓冲区获取接收到的数据。 STM32 网卡驱
22
动编写需要实现底层 host 驱动、 SDIO 层、以及 Marvell 网卡驱动。整体调用层次如下图所示:
sdio主机驱动
Sdio协议层
读写网卡寄存

下载固件
if_sdio.c
封装命令包
cmd.c
Marvell驱动层
LWIP协议栈
lbs_rev_pkt/lbs_sendpbuf
sdio_readb/sdio_writeb
stm32_request
网卡驱动
3.10 网卡驱动调用层次
Host 驱动层提供 stm32_request 函数供 sdio 协议层调用,并实现 SDIO 命令和数据传输。
Sdio 协议层调用 SDIO 主机驱动为上层设备提供命令或数据传输的接口函数(sdio_readb/
sdio_writeb 和 sdio_wrtesb/sdio_readsb)。同时本层还完成 SDIO 功能设备的识别、枚举,获取
sdio 功能设备信息、设备 ID 等。 Marvell 驱动层核心函数为 if_sdio_probe。函数根据读取到
的芯片 ID 加载不同的固件及相应的驱动。 If_sdio_probe 首先完成芯片的识别,然后加载
marvell 的 help_firmware(bootloader)文件,并利用 helper 文件下载固件。 Marvell 层同时还
提供了网卡的命令封包 cmd,封装了 if_sdio_card_to_host 和 if_sdio_ host _to_ card 两个函数用
于与底层驱动实现数据交互,网卡数据报/网卡 Event 通告/网络命令数据报及响应都通过这两
个函数完成传输。另外 Marvell 驱动层还完成网络扫描、管理等事务。并完成网络数据报的
收发,提供了与 lwip 接口函数 lbs_sendbuf/lbs_rev_pkt。接下来将详细讲述每一层的实现。
3.4.1 SDIO 底层 host 驱动编写
SDIO 卡是由 MMC(Multi Media Card)设备发展而来,在传输速率和数据安全上有了很
大提升。延续历史传统, SDIO 管理系统仍被称为 MMC 子系统。在 Marvell 面对 Linux 内核
设计的驱动中, 88w8686 相当于一个悬挂在 sdio 总线上的网络设备。驱动主要完成两块功能:
首先是在 sdio 总线上对网卡设备的识别和注册,实现即插即用[27]。其次实现网卡收发数据。
本文在熟悉 Linux 网卡驱动的基础上对其进行裁剪,驱动设计原理基本保持一致。
在 s3cmci.c 文件中完成了 SDIO 底层的 host 驱动。该驱动实现了 SDIO 数据和指令的传
23unsigned int sdio_irqs;
struct stm_ios ios; /*当前 stm 的 io 设置状态*/
u32 ocr; /* 设置当前电压*/
struct stm_card *card; /* 枚举到的 sdio 卡的数据链表 */
const struct stm_bus_ops *bus_ops; /* STM32 主机总线驱动 */

递,对通信的上层提供了一系列数据、命令发送相关的接口函数。同时向 sdio 协议层提供了
stm32_request 函数作为网卡的访问接口,是 SDIO 模块中核心的部分[28]。首先几个重要的数
据结构,接着介绍数据收发的通道实现,然后介绍了几个比较重要的接口函数,最后介绍了
SDIO 各种类型中断的处理。
(1) 几个重要的数据结构
1)stm32_host_ops 结构:该结构裁剪与 linux 的.mmc_host_ops 结构,重新定义了供 STM32
的 sdio 协议层调用的各种接口函数,包括处理 host 的 request(发送或获取 CMD 或 DATA)、
配置硬件参数相关的寄存器、获取卡的读写权限信息、获取卡的状态(是否存在)、使能 SDIO
中断。
2) stm32_host 结构: 该结构裁剪与 linux 的 mmc_host 结构, 是 STM32 的 SDIO 驱动中
至关重要的一个数据结构。承担着 host 底层与通信协议之间交互数据的载体角色。 mmc_host
数据结构内嵌了 mmc_host_ops 结构[29], Host 驱动提供的大部分接口函数都是以 mmc_host
为参数进行各种操作。此处裁剪了 Linux 内核中相应的 mmc_host 数据结构,其数据结构如下:
struct stm32_host {
int index;
const struct stm32_host_ops *ops; /*mmc 主机操作的接口函数*/
unsigned int f_min;
unsigned int f_max; /*设置 sdio 速率*/
u32 ocr_avail; /*sdio 主机电压支持范围*/
unsigned long c 接入点 s; /* SDIO 主控制器的功能属性 */

/* 设置块传输参数 */
unsigned int max_seg_size; /* 块传输最大分片尺寸*/
unsigned short max_hw_segs; /* 块传输最大分片数目 */
unsigned short max_phys_segs; /*最大支持的物理分片数目 */
unsigned int max_req_size; /* 请求最大的数据长度 */
unsigned int max_blk_size; /*一个 mmc 请求块最大尺寸*/
unsigned int max_blk_count; /*最大的请求块数目*/
/* 对应主机相关数据 */

24
struct stm32_host private;/*指向对应的主机控制器*/
} 3
) stm32_host 结构:我们在 stm32_host 结构体内创建一个 mmc_host 结构体的指针,相
当于封装了一个 mmc_host 结构体,来实现载体的核心功能[30],另外添加一些数据命令传输
的设置参数。其数据结构包括一个 mmc_host 结构体的指针、时钟和速率设置、 SDI 控制器设
置、 DMA 相关参数,判断是否选择 DMA、判断 DMA 结束传输、中断相关参数、命令相关
参数、 PIO 传输参数、设置线宽等。
(2) 传输方式
1) DMA 数据传输: DMA 读写允许寄存器和 SDIO 设备之间直接沟通,省去了 CPU 的
干预,因此大大减少了 CPU 的负载,提高了处理效率。这里采用 DMA2 通道 4 实现 DMA 传
输 。 首 先 进 行 DMA 输 入 与 输 出 的 配 置 , 相 应 的 函 数 为 DMA_RxConfiguration() 、
DMA_TxConfiguration(),主要对寄存器地址值、缓冲大小、外围中断允许、存储数据大小、
DMA 模式、优先级进行配置。在数据和命令发送时若选择 DMA 通道,调用函数
stm32_enable_dma()使能 DMA[31]。该函数核心代码及注释如下:
/*开放 CRC 校验失败中断、接收超时中断、传输结束中断*/
u32 imask=SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND;
/*清除中断屏蔽寄存器*/
SDIO_ClearFlag(SDIO_ICR_MASK);
/*使能 DMA 和数据发送*/
SDIO->DCTRL|=(SDIO_DPSM_Enable|(1<<3));
/*配置 SDIO 中断*/
SDIO_ITConfig(imask, ENABLE);
/*监测 DMA 发送是否完成, 若完成则置位 TC4 FLAG,然后不断轮询*/
while (DMA_GetFlagStatus(DMA2_FLAG_TC4) == RESET);
2) FIFO 数据传输: FIFO 数据传输即 PIO(Programming Input / Output Model)传输,对
应于 DMA, PIO 模式的数据读写经过 CPU 对 I/O 端口的操作。实现过程如下: 首先调用
stm32_prepare_pio()根据上层传递下来的读写的标志判断是写操作还是读操作。若为写操作调
用 do_pio_write()函数向 FIFO 中写数据,若为读则调用函数 do_pio_read()准备 FIFO 数据的
接收。写数据时,当 FIFO 发送缓冲区空间大于 3 个 int 数据长度时启动写操作。当 FIFO 有
数据需要读出时会调用中断处理程序,中断处理程序进而调用 do_pio_read()读出数据,因此
需实现使能中断。 由于 PIO 操作占用很大 CPU 资源,因此我们采用 DMA 传输为主。
(3) 接口函数的实现
host 层驱动最主要的功能是向上层通信接口函数,通过调用这些接口函数实现对 host 主
机的各种操作。包括判断设备的存在、读写权限信息的获取、请求的发送、数据请求处理设
25
置、中断设置(使能、屏蔽、清除中断屏蔽寄存器)、数据传输方式选择、命令发送处理等,
判断设备是否插入和获取读写权限信息功能实现很简单,只需要读取相应 GPIO 引脚上的电
平值,分别是卡检测的引脚与卡写保护引脚[32]。
1) 硬件 I/O 的设置:该功能的函数实现是 stm32_set_ios()。该函数将 host 指针指向具体
的 sdio 设备(经过 stm32_probe 函数关联之后的),读取其 stm32_host 数据结构的具体参数值;
根据函数被调用时传递过来的 ios 结构体,调用 stm32_set_clk()函数,通过写波特率寄存器完
成时钟设置;读取 ios 结构体的 power_mode 成员变量,根据电源状态决定时钟信号的开关。
读取 ios 结构体的 bus_width 变量确定该设备数据传输时的线宽。
2) 请求的处理: SDIO 端口的读写都是基于 host 的请求完成的,即 host 首先通过 CMD
PATH 发送不同操作对应的 CMD, SDIO 设备根据 CMD 的类型进行相应操作,同时判断是否
向 host 返回应答。 stm32_request 函数被上层调用完成数据和命令的接收和发送,是 host 驱动
的核心实现。首先判断 SDIO 设备是否存在[33],若存在则调用 stm32_send_request()函数发送,
若不存在则调用 stm32_request_done()终止发送请求。 stm32_request 函数核心代码如下:
if (stm32_card_present(mmc) == 0)
{
dbg("%s: no medium present\n", __func__);
host->mrq->cmd->error = -ENOMEDIUM;
stm_request_done(mmc, mrq);
}
else
stm32_send_request(mmc);
3) 请求的发送: stm32_send_request()会根据传递的参数判断发送的是命令还是数据,若
是数据请求,则通过调用 stm32_setup_data()函数实现对数据请求进行设置,若设置返回异常,
这将 cmd 的 error 结构成员设定为 res 类型,然后调用 stm_request_done()函数结束请求。若返
回正常则调用 DMA_TxConfiguration()函数,对 DMA 的发送进行配置。然后使能 DMA 数据
发送中断服务函数,进入中断处理。若是命令请求,则调用 stm32_send_command()函数发送。
stm32_send_command()函数会首先判断是否有数据,有则进行安装。因为所有最后调用
stm32_enable_irq ()函数重新使能中断。 stm32_send_request()函数代码如下:
if (cmd->data)
{
int res = stm32_setup_data(host, cmd->data);
host->dcnt++;
if (res)
{
26
printk( "setup data error %d\n", res); / *res 返回异常* /
cmd->error = res;
cmd->data->error = res; /*结束请求*/
mmc_request_done(mmc, mrq);
return; /*到此结束程序*/
}
DMA_TxConfiguration((u32 *)data->sg,total_len);
}

/* 若程序运行到此处,证明该请求为命令请求*/
stm32_send_command(host, cmd);
stm32_enable_irq(host, true);/*使能中断*/
4) 处理数据请求时相应的设置:该功能由 stm32_setup_data()函数通过配置 DCON(数据
控制寄存器)实现,
本课题选择 DMA 传输,放弃 PIO 传输方案,完成了数据接收和发送时的 DMA 配置。
过程如下:
a.首先会对请求进行一个判断,若非数据处理请求则对 SDI 寄存器(数据控制)进行清
零。
b.然后读取 data 数据结构中的 blksz 判断是单模块还是多模块处理,即判断 data->blksz &
3 是否为 0, blksz 对应 SDI 块尺寸寄存器 BLKSIZE[1:0],若两位都为 0 则为多模块,否则为
多模块。此处为单模块,因此若此时处理模块数大于 1,则返回异常。
c.接下来完成重置 SDIO 数据结构 SDIO_DataInitStructure,重置参数包括数据超时、数据
长度、数据块尺寸、传输模式。然后通过函数 IO_Data _Config ()将配置写入数据寄存器;
d.设置 SDI 寄存器线宽位,使 SDIO 总线宽度为 4bit,即宽总线模式。
e.开放 CRC校验失败中断、接收超时中断、传输结束中断。然后通过函数 enable_imask(host,
imask)使能中断。
f.完成数据发送和接收时 DMA 的配置,首先读取 data 数据结构的 flags 成员变量中数据
写的位,判断若接收数据,调用 DMA_RxConfiguration()函数完成 DMA 接收的配置, 接收时
先使能 DMA 和数据状态机。若发送数据,调用 DMA_TxConfiguration()函数配置。
g.中断设置:中断设置主要包括中断使能函数 stm32_enable_irq()、中断屏蔽函数
stm32_disable_irq()、中断屏蔽寄存器清零函数 clear_imask(),通过调用 SDIO_ITConfig()函数。
实现语句如下:
SDIO_ITConfig(~imask&mask,DISABLE); /* 对 要 屏 蔽 的 中 断 */
SDIO_ITConfig(imask|mask,ENABLE); /*对要使能的中断*/
SDIO->MASK&= SDIO_IT_SDIOIT; /*清除中断屏蔽寄存器*/
27
5) 中断服务程序
中断的设置是 host 驱动至关重要的一个环节。 SDIO 数据的传输是基于中断完成的: host
每次通过函数 stm32_request()发送命令发起数据的传输,在发送完成后等待中断处理,此时
会调用相应中断服务函数 stm32_irq(),该函数处理所有命令、数据传输过程中产生的中断请求。
主要包括设备中断、命令传输产生的中断与数据传输产生的中断。具体包括命令超时中断、
命令发送成功中断、 命令 CRC 校验失败中断、 命令响应完成中断、数据发送超时中断、数据
发送结束中断、数据 CRC 校验失败中断。由于代码量太大,此处仅选择几个具有代表性的中
断处理进行分析[34]。
SDIO 设备中断:读取 SDI 数据状态寄存器,若检查到 SDIO 设备中断且 SDIO 设备中断
位被使能,则首先清除标准位,然后调用 stm_signal_sdio_irq()函数处理中断, 核心代码如下:
if (stm_sta & SDIO_IT_SDIOIT) {
if (SDIO_IT_SDIOIT & stm_IMSK) / *判断是否期待的中断* /
{
printk("card sdio interupt!\n");
stm_clear= SDIO_IT_SDIOIT;
SDIO->ICR=stm_clear; / *清除标准位* /
stm_signal_sdio_irq(host->mmc); /*开启中断处理线程*/
return;
} }
stm_signal_sdio_irq()函数调用 sdio_irq_thread()线程处理函数开启中断处理线程,对由
SDIO 控制器引起中断进行处理。
该线程具体调用挂起中断函数 process_sdio_pending_irqs() ,process_sdio_pending_irqs()进
而通过调用函数 mmc_io_rw_direct()把所有参数直接传递给 stm32_io_rw_direct_host(),完成对
悬挂设备产生的中断处理。
命令响应完成中断:首先清除命令响应完成中断标志位。当 HOST 收到带有 rsp 应答的
命令响应时会产生命令响应完成中断, rsp 应答的产生有两种情况:一种是命令响应得到应答,
另 一 情 况 是 命 令 传 输 完 成 。 第 一 种 情 况 下 立 即 结 束 传 输 。 第 二 种 情 况 下 调 用
stm32_enable_dma()函数完成数据的发送。核心代码如下:
if (stm_sta & SDIO_IT_CMDREND) /*查询状态位 命令响应完成*/
{
stm_clear |= SDIO_IT_CMDREND;
/*若收到的是带有应答的命令响应*/
if (host->complete_what == COMPLETION_RSPFIN)
28
{
host->status = "ok: command response received";
/*结束传输*/
goto close_transfer;
}
/*若收到的是传输完成的响应*/
if (host->complete_what ==COMPLETION_XFERFINISH_RSPFIN)
{
host->complete_what = COMPLETION_XFERFINISH;
/*命令响应*/
if(data->flags&MMC_DATA_WRITE)
{
/*发送数据*/
stm32_enable_dma();
return;
}
}
}
6) 设备与驱动的匹配
最终实现 SDIO 设备驱动的加载,要同时完成 SDIO 设备驱动的加载和 SDIO 设备结构的
加载,然后根据 ID 等信息完成两者的匹配。在完成了设备的注册、初始化、枚举和 host 驱
动 SDI 控制器加载前提上,接下来就要进行设备与驱动的匹配。当 SDIO 设备挂接到 SDIO
设备总线上时,会调用设备总线指定的匹配函数进行匹配[35]。同理当加载一个新的 SDIO 设
备对象的驱动时,会调用驱动所属的总线指定的匹配函数进行匹配。匹配工作主要通过调用
函数 sdio_device_id *sdio_match_device()实 现。该函数进而调 sdio_match_one()函数,
sdio_match_one()通过对获取到 sdio_driver 设备驱动中的 id 与 id_table 进行匹配实现 sdio 总线
上设备与驱动的匹配,匹配成功则返回设备号,同时调用 SDIO 总线的或者驱动的 probe 函数
完成设备的初始化、网络接口的注册、以及设备访问接口的注册等。 例如当完成新的 SDIO
设备驱动的注册后,会调用 sdio_bus_probe()探测函数在其挂接的总线上进行探测,找出总线
上处于未绑定状态的设备[36]。然后将该设备的驱动指针指向新的驱动。完成设备与驱动的结
合。sdio_bus_probe()调用 if_sdio_probe()函数,实参为设备与驱动匹配成功后返回的 ID与 SDIO
设备驱动的 func。 if_sdio_probe()属于 marvell 层核心函数,会在网卡驱动部分详细讲述。
7) 设备的枚举
中断设备上电后系统会调用平台探测函数 stm32_probe()函数进行设备的枚举,该函数主
29
要工作是创建一个内嵌 stm32_host 的数据结构,获取探测到的 SDIO 设备,将其添加到内核。
最后调用 mmc_rescan()函数完成 SDIO 设备的检测。主要实现如下:
a.创建一个名为 host 的 stm32_host 结构体指针,以准备下一步对成员变量进行赋值
b.实例一个 mmc_host 指针,将其指向探测到的 SDIO 设备,用于与上步 stm32_host 数据
结构的指针进行关联。
c.创建一个指向 SDIO设备的 stm32_host指针,将该指针关联到上文讲到的中断服务程序。
d.调用 init_stm32_struct()函数注册主机接口, 由函数 init_stm32_struct()实现。 完成对 sdio
设备数据结构内容的填充,回调函数的设置。包括设置请求的回调函数、调用传递 I/O 时钟、
数据线宽、供电电压等引脚的物理参数的回调函数、设置卡状态(当前卡或缺省卡)的回调
函数、设置中断参数的回调函数。需要注意的一点是 sdio 设备在初始化的时候,时钟频率不
能大于 400KHZ,之后可根据需要设置成高速模式。 SDIO_CK>24MHz 时,应开启 bypass 模
式, sdio 设备的 SPI mode 上限为 25MHz。
e.调用 mmc_alloc_host()函数实例一个 mmc_host 数据结构(里面嵌套一个 stm32_host 结
构),为该结构体指针分配一定空间的内存。实际大小为 mmc_host 与 stm32_host 的和。
f.调用 mmc_priv()函数实现 stm32_host 与 mmc_host 实例化对象的关联。
g.初始化 stm32_host,为结构体成员变量赋值。
h.使能 SDIO 设备中断,为 SDIO 设备注册中断,并设置相关中断参数
i.初始化 mmc_host
在枚举之前的准备阶段,需切断设备的电源,待 sdio 复位后再重新上电。在获取设备端
口号之后即成功完成初始化。具体流程图如图 3.11 所示:
准备
(断开模块电
源)
注册主机接口
init_STM32_struct
&stm32_ops;
分配mmc_host,内嵌
stm32_host 结构
mmc = mmc_alloc_host();
注册中断服务及使能中断
gpstm32_host=host;
EnableIrq(host->irq);
设置时钟频率与分频
host->clk_rate =128000000;//50Mhz
host->clk_div=1;
注册主机操作接口函数
mmc->ops = &stm32_ops;
mmc->ocr_avail= MMC_VDD_32_33 | MMC_VDD_33_34;
设置块传输参数
返回设备指针
上电复位
3.11 sdio 设备枚举图
30
3.4.2 SDIO 协议层的实现
(1) STM32 的 SDIO 配置
SDIO 通信通过设置 STM32 芯片的 SDIO 适配器,实现了命令发送与数据发送的隔离以
及对寄存器的操作。 SDIO 适配器包括两个模块: AHB 总线接口和 SD 卡接口。 AHB 接口主
要包括一组适配器寄存器和 FIFO 缓冲栈, SD 卡接口主要实现了与 SDIO 设备、SD 卡的连接。
即包括 Control unit(控制单元)、 Command path(命令通道)、 Data path(数据通道)。 Control
unit 主要实现控制 SDIO 设备的时钟频率(直接供给 STM32 的时钟还是经过分频)以及设置
SDIO 适配器模块供电的开启和关闭[37],以上操作都是基于配置适配器中一组寄存器参数。
Command path 即命令通道,连接 CMD 线。 Data path 最多可连接 8 根数据线,最多可同时连
接 8 个 1-bit 传输的 SDIO 设备。 灯控节点只使用 data[3-0]4 根数据线,用于数据的传输。适
配器结构如下图所示:
Control unit
Command path
Data path
Adapter
registers
FIFO
HCLK/2 SDIOCLK
SDIO[7:0]
SDIO_CM
D
SDIO_CL
K
SDIO
adapter
To AHB
interface
3.12 适配器结构图
1) SDIO 寄存器
SDIO通信的实现以及对 SDIO设备的控制都是通过 SDIO驱动对 SDIO寄存器的操作
来完成的。上图左边阴影部分即为 AHB 接口模块, Adapter registers 包含了 SD 卡的所有寄存
器。 SDIO 设备在包含 SD 卡寄存器的基础上增加了对应最多 7 个 func 的寄存器。其大小为
128K 字节,对应功能号为 func[7:0], func[0]为 CIA(Common I/O Area)寄存器,主要用来保存
SDIO 设备的基本特性和信息,可以通过操作 CIA 修改这些寄存器。其中基本信息保存在
0x1000 ~0x17fff 地址中, 初始化时通过读取基本信息完成设备的匹配。
2) SDIO 控制单元
31
我们通过操作 SDIO 寄存器来配置 SDIO 控制单元。 SDIO 控制即电源控制与时钟控
制,时钟控制分为 Bypass 模式和分频模式。分频模式下 SDIO 设备的时钟频率由 div 参数决
定:sdio_clk=sdio_clk/div。控制单元结构如下图所示:
Clock
management
Power management
Adapter
registers
Control unit
To command and data
path
SDIO_CLK
3.13 控制单元结构图
3) SDIO 命令
SDIO 的数据操作也是 HOST 首先通过命令通道发送发起各种请求。 SDIO 协议中有多达
11 种命令,涵盖了一组 ACMD 命令、读写操作命令、基本命令。 STM32 的命令通道如下图
所示:
STATUS
flag
Command
timer
Control
To control unit logic
CMD
Argument
Shift
register
CMD
response
registers
To AHB interface
CRC SDIO_CMDout
Adatpter registers SDIO_CMDin
3.14 命令通道结构图
32
SDIO 命令的设置和发送主要通过操作 SDIO_CMD 和 SDIO_ARG 两个寄存器实现。
SDIO_CMD 负责命令的选择与添加,主要负责命令功能的区分(SDIO_CMD 中有 6 个
bit 长度用来区分命令,最多可识别 64 个不同的 command)、命令是否等待响应的标识、以及
响应的类型标识。 SDIO_ARG 负责命令参数的选择。
4) 命令状态的转换:配置完两个寄存器后就可以调用发送命令的函数,将命令通过命令
通道发送出去,该通道工作在半双工状态,可以在单位时钟周期内完成命令的收发或者响应
的传输。命令总长度为 48bit,主要由命令的类型和相应命令的参数、 CRC 校验码组成。命令
组装完成后直接通过移位寄存器,如图中的 Shift register。移位寄存器负责将命令的并行模式
转换为串行模式,然后以 bit 为单位进行传送。最后 CRC 模块负责生成之前位的 CRC 校验码,
并附加到最后部分[32]。然后通知主控模块发送出去。最后根据命令类型选择 idle 状态还是
response 等待状态。进入等待状态时会有几种情况,第一种情况是在 CMD 寄存器中的中断位
被置 1,此时会等待直到 SDIO 设备完成命令后产生相应的中断请求。第二种情况是 CMD 寄
存器中的悬挂位被置 1,此时会一直处于悬挂状态。直到有数据传输时数据通道产生一个
CMDPend 信号,数据计算器通知状态机进入数据发送模式,状态机检测到 CMDPend 位的变
化后停止等待并关闭命令通道。利用命令时钟的计时等待 64 个 SDIO 时钟单位。若在计时范
围内未收到 SDIO 设备发回的应答,则设置超时 flag 并返回 idle 状态。命令通道的状态标识
位主要有以下几个:
CMDREND: 当响应 CRC 校验成功时置位
CCRCFAIL:当响应的 CRC 校验失败时置位
CMDSENT: 当不需要响应的命令发送后置位
CTIMEOUT:当响应等待超时时置位
CMDACT: 当命令发送进行时置位
命令通道的状态转换如下图所示:
33
Idle
Wait
Receive
Wait_CPL
Send
Pend
收到CE-ATAmoshi的响应并
没有中断设置和等待
CEATA结束信号的使能
On reset
CPSM
使能、 悬挂命

CPSM disabled
使能、 命令开始
CPSMdisabled or no
response
Command
超时
等待响应
收到
CE-ATA模式下的
响应, 乜有中断或
CEATA命令结束信号
收到
CE-ATA命令结束信号  
回复

使用道具 举报

该用户从未签到

12

主题

7221

回帖

100

积分

游客

积分
100

终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

QQ
发表于 2017-4-19 19:49:01 | 显示全部楼层
回复

使用道具 举报

该用户从未签到

3

主题

3952

回帖

4658

积分

二级逆天

积分
4658

社区居民忠实会员最爱沙发终身成就奖优秀斑竹奖

QQ
发表于 2017-4-19 20:22:44 | 显示全部楼层
回复

使用道具 举报

该用户从未签到

11

主题

1125

回帖

0

积分

二级逆天

积分
0

社区居民终身成就奖优秀斑竹奖

QQ
发表于 2017-4-19 20:58:25 | 显示全部楼层
回复

使用道具 举报

  • TA的每日心情
    奋斗
    前天 09:25
  • 签到天数: 58 天

    [LV.5]常住居民I

    60

    主题

    1万

    回帖

    8377

    积分

    二级逆天

    积分
    8377

    终身成就奖特殊贡献奖原创先锋奖社区居民灌水天才奖优秀斑竹奖宣传大使奖忠实会员最爱沙发社区劳模

    QQ
    发表于 2017-4-20 09:53:16 | 显示全部楼层
    比较热的资料,谢谢分享!!!
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    论坛开启做任务可以
    额外奖励金币快速赚
    积分升级了


    Copyright ©2011-2024 NTpcb.com All Right Reserved.  Powered by Discuz! (NTpcb)

    本站信息均由会员发表,不代表NTpcb立场,如侵犯了您的权利请发帖投诉

    平平安安
    TOP
    快速回复 返回顶部 返回列表