你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32的SDIO(转)

[复制链接]
zero99 发布时间:2017-6-7 14:48
对STM32的SDIO——SD卡输入/输出模块摸索了一下,今天只看了POWERUP这个函数的实现。对SDIO编写驱动,需要参考SD卡的协议,我手上的SD卡协议是ver2.00的物理层简化协议。协议主要规定了主机(这里就是STM32)向SD卡写入的各种控制指令,以及SD卡的初始化过程状态转移图。了解SD卡从初始化状态转移图开始。
2 j8 E8 `7 S0 A1 _! b2 z: G: l
762a233def5431e8b8d9420dd94a878f.jpg - V9 M! X6 j$ l2 V  Z3 e

" C0 M( k2 U, C+ z这个图看起来有点复杂,感觉无从下手,其实仔细瞧瞧就跟我们数电学的状态转移图差不多,框框里面是各种操作,箭头指向下一步操作,直线引出去的部分就是状态发生跳转的条件。首先上电(power-on),然后发出CMD0,再接着发送CMD8,有应答(response)判断为Ver2.00或更新的SDMC,无应答(noresponse)判断为ver2.00或者更新版SDMC(电压不匹配(voltage mismatch) )或ver1.XSDMC或不是SDMC。若判断为前一种情况,则问询是否为有效应答(validresponse),如果不是,判断为无效卡,否则判断为有效卡且开始循环发送ACMD41指令直至SD卡发出powerup应答。然后判断CCS(card capacitystatus——卡容量状态)位,为1则判断为ver2.00或者更新的大容量卡(high capacity SD memorycard),否则判断为ver2.00或者更新的标准卡(sandard capacity SD memorycard)。至此,power on工作结束。
3 m! r% P0 e. L
( h7 M0 J1 d0 Q1 G

- U% U2 W- _! C$ N3 \& ~上文只是对状态图进行了一个解读,真正要控制还是需要知道各个CMD如何发送。SD卡协议提供了几个CMD的格式以及其响应值的格式(如果有相应的话)。下面就对函数的具体编写进行下总结。1 W' z* D% |! Y! d7 h+ Q/ @$ o9 o
- ~$ P0 }! `+ F4 K
(1)初始化SDIO
1 E  o! [' [8 D9 J利用SDIO_Init中的结构体初始化SDIO接口。该结构体有以下几个成员函数:SDIO_ClockDiv、SDIO_ClockEdge、SDIO_ClockBypass、SDIO_ClockPowerSave、SDIO_BusWide、SDIO_HardwareFlowControl。其中比较重要的是SDIO_ClockDiv成员,它确定了SDIO的分频系数,在不使用旁路时钟(ByPass)的时候SDIO_CLK=HCLK/(SDIO_ClockDiv+2),我们在这里将SDIO_CLK设置为400kHZ,就是通过设置分频系数实现的。初始化完成后,就进行第一步,也就是poweron,调用SDIO_SetPowerState函数即可。最后别忘记使能SDIO的时钟。
& i0 Q) ~  ~; G6 Y4 R
9 i7 N/ m. |, u$ x# o8 }% z# _(2)发送CMD0& m: D8 E3 Q, A
由STM32向SD卡发送指令可以直接调用SDIO_SendCommand函数,该函数包含一个结构体,该结构体有以下几个成员:SDIO_Argument、SDIO_CmdIndex、SDIO_Response、SDIO_Wait、SDIO_CPSM。跟我们编程密切相关的一个是SDIO_Argument——参数,许多带有响应的命令都需要通过设置参数来实现,由于CMD0没有响应,所以此处设为0x00即可。SDIO_CmdIndex成员是该结构体核心——指令指数。也就是说,如果我要发送CMD0,SDIO_CmdIndex=0,如果发送ACMD41,SDIO_CmdIndex=41,但是注意此处SDIO_CmdIndex的值是等于指令,而且是指令的十进制形式,但是我们在给SDIO_CmdIndex赋值时必须转换成十六进制。SDIO_Wait设置等待中断。填写好结构体后检测是否正确受到CMD0,然后才能进行下一步。为了保证程序正确,这样的检测在每一个指令发送周期都是必须的。& l+ D$ O' O# l6 A

' A. r) [3 Y0 {1 V4 v(3)发送CMD8
# Y0 D/ p3 F, L6 F, x; ~1 w4 L用同样类似的方式发送CMD8。注意此时CMD8是带有响应的指令,接收到指令后sd返回该SDIO_Argument的值,所以对SDIO_Argument要进行特殊设置,设置后SDIO->ARG寄存器便有了该值。SDIO_Response——把应答模式设置成短应答,这是根据参考指南设置的。同样地,在填写完结构体后检查是否接收到命令。根据SD协议初始化流程图,此时如果有响应则SD遵循2.00协议,否则说明是1.x或者mmc。无论是哪一种情况,都发送CMD55来检测。3 Q. s6 o/ a7 G3 a" Y# Z) ]( Y5 w' Y

$ s, k2 n* r" a1 M- V% Y( a(4)发送CMD55
+ y5 L. E8 F, m7 YCMD55是一个特殊的指令,该指令告诉主机下一个command将会是一个应用指令(applicationcommand),比如要发送ACMD41之前必须先发送CMD55。此处发送CMD55是为了检测卡的类型。不过暂时没没看懂为什么是发送CMD55,因为关于CMD55的解释中并没有提到它能够检测卡类型,只说了它的应答类型是R1。判断是SD卡或者是不支持的卡。
! C% L+ s; I& o5 N( N. T' o& f; L5 Y) j
  h" |  w' }* Z% _(5)进入循环,再次发送CMD55. f" m* J8 d, p; H) t$ K
这次发送CMD55就是为发送ACMD41做准备了。为什么要在循环里发送呢?因为SD协议初始化状态图中发送ACMD的过程是一个反复地,指导检测出powerup为1为止,所以该处的循环条件设置成!validvoltage,validvoltage为OCR的powerup位。需要注意的是例程中的循环条件是(!validvoltage) && (count <SD_MAX_VOLT_TRIAL),也就是说它设置了一个最大检测次数,当超过该检测次数仍然没有powerup时就可以跳出,反馈检测失败的信息,这样程序不会死在此处。
* {8 a6 l- k7 ]! ?
: r! D* d2 V# p7 ^(6)发送ACMD41
( `# q7 t' V$ r2 H- j! ]发送了CMD55后检测到收到指令,紧接着发送ACMD41指令。ACMD41响应类型是R3,该响应返回OCR寄存器的值,稍后我们需要这个寄存器来判断卡容量以及powerup状态。注意此处参数格式规定的是HCS和VoltageWindow共同确定的。填写完结构体后检查是否正确接收指令,然后检测powerup位是不是1,不是的话再次循环,是则根据条件跳出循环。如果达到最大循环次数powerup仍然没置位,则返回卡不可用的信息。( U2 L$ g# `! {1 y

; l4 k' W& u2 A6 J. m; b' Y(7)检测卡的最终类型! J, t, V! d* V- Y
正常上电好后,检测OCR的CCS为,一次来判断卡是SDHC还是SDSC。至此,power on函数功能到此结束。& N; ~; g: `  z$ |$ O
% \/ h" m9 s! }* I- J3 c

7 ?! T  z' p: V( s
赞 收藏 1 评论1 发布时间:2017-6-7 14:48

举报

1个回答
队长shiwo 回答时间:2017-6-27 14:40:11
多谢破总分享,学习SD卡
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版