2016年11月5日 星期六

作業系統之前的程式 for stm32f4discovery (17) - sd card 初探 by spi

實踐出真知

為什麼我之前特別專注在 spi 上呢? 不是 i2c, 也不是 i2s, 就是因為我要使用 spi sd card, 這才是我真正的目的。sd card 的界面有 sdio 或是 spi, 我選擇了比較簡單的 spi。

spi 已經可以通訊了, 再來要把 spi 和 sd card 插槽連接起來, 這真的難倒我。

spi 的 4 個 pin 我已經了解, 沒有問題, ground 也沒問題, 問題是 3.3v, 5v 那個才是要接的 pin, 又要接在開發板的哪裡呢?

詢問過有經驗的朋友後, 決定把 sd 板的 3.3v 接在 stm32f4 開發板的 vdd 上, 也用了三用電錶確定 vdd 輸出的是 3V 電壓, 我一個軟體人員自然不會這些, 麻煩別人幫我完成這些事情。

5v 據說也可以, sd card slot 有降壓 ic 會把 5v 降到 3.3v。


SD(HC)-memory card and MMC interface conditioning chapter 2 提到 2.7 ~ 3.6 V sd card 的工作電壓

Today many appliances use 2.7 V to 3.6 V operating mode. It enables the use of a fixed
voltage interface and power supply to reduce cost and complexity of the control circuitry.
All further descriptions are related to this high-voltage range: 2.7 V to 3.6 V supply voltage
operated interfaces.

使用《作業系統之前的程式 for stm32f4discovery (16) - spi》提過的 spi1 來連接 sd card, 在該篇文章中, 我已經打通了 spi1 的通訊, 把它接過來這邊就可以了。

和《作業系統之前的程式 for stm32f4discovery (16) - spi》不一樣的是 cs (NSS) 需要接起來, 接到 sd card 的 SDCS, 但是設定 spi 時, 還是設定 soft nss。

stm32f4discovery 開發板 (msater) sd card (slave)
NSS: PA4 SDCS
SCK: PA5 SCK
MISO: PA6 MISO
MOSI: PA7 MOSI
ground ground
vdd3.3v



stm32f4discovery 線路圖可以參考 stm32f4discovery 線路圖, 我看了 vdd, 5v, 3.3v 的這些部份, 當然還是看不懂, 有個朋友為我說明其中概念, 這是認識 ee 人的好處, 要不然會看得很辛苦。

硬體接線搞定了, 再來剩下軟體的問題, spi 沒問題, sd card 的初始化還真的很複雜, 最後找了 STM32 不完原手冊的範例:

4)正点原子miniSTM32F103rct开发板资料:
基础资料下载总连接:http://pan.baidu.com/s/1qXYP1b2
手把手教你学STM32》参考视频(下载战舰B,C,D盘即可):http://pan.baidu.com/s/1eSAwPrW
B盘独立压缩包: http://pan.baidu.com/s/1i5GwEqT 视频盘,《手把手教你学STM32-M3》视频
C盘独立压缩包:http://pan.baidu.com/s/1miPJYeW 视频盘,《手把手教你学STM32-M3》视频
D盘独立压缩包:http://pan.baidu.com/s/1i4UZ4Lf 视频盘,《手把手教你学STM32-M3》视频  

UCOS/EMWIN/LWIP视频下载链接:

MiniSTM32 V2.0开发板资料(适合3.0之前所有版本):http://pan.baidu.com/s/1o7Hs8OU
<<原子教你玩STM32>>系列视频教程(30集):http://pan.baidu.com/s/1dD3Uvg1
STM32学习短视频(STM32解读/工具使用/开发板/模块测试):http://pan.baidu.com/s/1kT1GpRT
STM32学习从0开始(13讲): http://pan.baidu.com/s/1nvETqQ1

這個網站的 stm 相關開發板有很豐富的資源, 還有教學影片, 他們為了賣開發板做了這麼多的努力, 真的不簡單。這次的 SD card 程式碼參考了 STM32 不完原手冊的範例, 我修改為符合 stm32f4discovery 開發板後在 stm32f4discovery 執行。這是最麻煩的部份, 目前似乎沒有書籍專為 stm32f4discovery  來撰寫, 書籍大都需要搭配某塊開發板, 而我使用的開發板和這些書籍寫的都不同, 把範例改到可以正確執行還蠻麻煩的。


電子書可以下載, 想知道 sd card 初始化流程可以看看, 我只想套用這段程式碼, 站在巨人的肩膀真的輕鬆不少。由於我打通了 stm32f4discovery 的 spi1, 只要單純把 spi init 的程式碼換成我那段成功的部份就可以了, 當然, 還有 spi1 讀寫資料的部份也要一併置換。

這次能完成這個實驗要感謝很多人, 特別是 telegram 群組的 Yen-Chin Lee, 他給我很多意見以及相關資訊。

接上電源後, 開始跑程式了, 我很有信心, 一開始的 SD_Initialize() 應該會過才是, 但 ... 沒有, 我懷疑是硬體沒接好, 轉頭一看, 果然 3.3 v 的線沒插好, 再試一次, 還是不行, 再轉頭一看, 下方的 spi1 線鬆開了, 再來一次, 果然順利把 SD_Initialize() 執行完畢, 我就說是硬體沒接好吧! 這是難得的幸運, 一次就好, 之前的努力沒有白費, 真是讓人開心。



不過再來該做什麼呢? 把 CID, CSD 讀出來確認 sd card 真的有認到, 說不定 SD_Initialize() 只是運氣好過了, 而無法正確讀到 sd card 資訊。

在和 linux 抓到的 cid, csd 對照後, 除了最後的 CRC 不同外, 其他都一樣, 爽阿!

linux 下的 cid, csd 資訊
root@ds:/sys/block/mmcblk0# cat /sys/block/mmcblk0/device/cid
275048534430344720b0003fb4008c01
root@ds:/sys/block/mmcblk0# cat /sys/block/mmcblk0/device/csd
400e00325b5900001de77f800a400001

從 stm32f4discovery 開發板讀到, usart2 印出的結果
cid:
275048534430344720B0003FB4008CFB
csd:
400E00325B5900001DE77F800A4000D5

確定了, cid, csd 都是對的, 不過要把 spi 降速會比較穩,spi 設定在高速時不太穩, 有時候會卡在 spi read function。

Internal SD Card Information
NameFieldLinux attribute*Description
Manufacturer IDMIDmanfidAssigned by SD-3C, LLC.
OEM/Application IDOIDoemidIdentifies the card OEM and/or the card contents. Assigned by SD-3C, LLC.
Product NamePNMname5 characters long (ASCII)
Product RevisionPRVhwrev, fwrevTwo binary coded decimal (BCD) digits. Each is four bits. The PRV is in the form x.y. The PRV can also be found by using the hwrev and fwrev, where x=hwrev and y=fwrev
Serial NumberPSNserialThis 32 bit field is intended to be read as an unsigned integer
Manufacture Date CodeMDTdateManufacture date is stored in the form yym (offset from 2000)
CRC7 checksumCRC7 bit code used for checking errors in the card register

再來 dump sd card 的第 0 個 sector 內容, 確定可以正確讀到 sector 0 的資料。

list 1 . dump section 0 data
 1 üÿInit complete! Hello World!
 2 Init sd
 3 Init sd ok
 4 get cid ok
 5 cid:
 6 275048534430344720B0003FB4008CFB
 7 oid: PH
 8 pnm: SD04G
 9 get csd ok
10 csd:
11 400E00325B5900001DE77F800A4000D5
12 sd_size: 7839744
13 dump sector 0: 
14 
15 FA 31 C0 8E D8 8E D0 BC 00 7C 89 E6 06 57 8E C0 
16 FB FC BF 00 06 B9 00 01 F3 A5 EA 1F 06 00 00 52 
17 52 B4 41 BB AA 55 31 C9 30 F6 F9 CD 13 72 13 81 
18 FB 55 AA 75 0D D1 E9 73 09 66 C7 06 8D 06 B4 42 
19 EB 15 5A B4 08 CD 13 83 E1 3F 51 0F B6 C6 40 F7 
20 E1 52 50 66 31 C0 66 99 E8 66 00 E8 21 01 4D 69 
21 73 73 69 6E 67 20 6F 70 65 72 61 74 69 6E 67 20 
22 73 79 73 74 65 6D 2E 0D 0A 66 60 66 31 D2 BB 00 
23 7C 66 52 66 50 06 53 6A 01 6A 10 89 E6 66 F7 36 
24 F4 7B C0 E4 06 88 E1 88 C5 92 F6 36 F8 7B 88 C6 
25 08 E1 41 B8 01 02 8A 16 FA 7B CD 13 8D 64 10 66 
26 61 C3 E8 C4 FF BE BE 7D BF BE 07 B9 20 00 F3 A5 
27 C3 66 60 89 E5 BB BE 07 B9 04 00 31 C0 53 51 F6 
28 07 80 74 03 40 89 DE 83 C3 10 E2 F3 48 74 5B 79 
29 39 59 5B 8A 47 04 3C 0F 74 06 24 7F 3C 05 75 22 
30 66 8B 47 08 66 8B 56 14 66 01 D0 66 21 D2 75 03 
31 66 89 C2 E8 AC FF 72 03 E8 B6 FF 66 8B 46 1C E8 
32 A0 FF 83 C3 10 E2 CC 66 61 C3 E8 62 00 4D 75 6C 
33 74 69 70 6C 65 20 61 63 74 69 76 65 20 70 61 72 
34 74 69 74 69 6F 6E 73 2E 0D 0A 66 8B 44 08 66 03 
35 46 1C 66 89 44 08 E8 30 FF 72 13 81 3E FE 7D 55 
36 AA 0F 85 06 FF BC FA 7B 5A 5F 07 FA FF E4 E8 1E 
37 00 4F 70 65 72 61 74 69 6E 67 20 73 79 73 74 65 
38 6D 20 6C 6F 61 64 20 65 72 72 6F 72 2E 0D 0A 5E 
39 AC B4 0E 8A 3E 62 04 B3 07 CD 10 3C 0A 75 F1 CD 
40 18 F4 EB FD 00 00 00 00 00 00 00 00 00 00 00 00 
41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 02 
43 03 01 0C 18 D8 CC 00 20 00 00 00 80 77 00 00 00 
44 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
45 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
46 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA 

和用 hexdump 做比較, 當然是一樣的。

hexdump -Cv -n 512 /dev/sdb
 1 00000000  fa 31 c0 8e d8 8e d0 bc  00 7c 89 e6 06 57 8e c0  
 2 00000010  fb fc bf 00 06 b9 00 01  f3 a5 ea 1f 06 00 00 52 
 3 00000020  52 b4 41 bb aa 55 31 c9  30 f6 f9 cd 13 72 13 81 
 4 00000030  fb 55 aa 75 0d d1 e9 73  09 66 c7 06 8d 06 b4 42 
 5 00000040  eb 15 5a b4 08 cd 13 83  e1 3f 51 0f b6 c6 40 f7 
 6 00000050  e1 52 50 66 31 c0 66 99  e8 66 00 e8 21 01 4d 69 
 7 00000060  73 73 69 6e 67 20 6f 70  65 72 61 74 69 6e 67 20 
 8 00000070  73 79 73 74 65 6d 2e 0d  0a 66 60 66 31 d2 bb 00 
 9 00000080  7c 66 52 66 50 06 53 6a  01 6a 10 89 e6 66 f7 36 
10 00000090  f4 7b c0 e4 06 88 e1 88  c5 92 f6 36 f8 7b 88 c6 
11 000000a0  08 e1 41 b8 01 02 8a 16  fa 7b cd 13 8d 64 10 66 
12 000000b0  61 c3 e8 c4 ff be be 7d  bf be 07 b9 20 00 f3 a5 
13 000000c0  c3 66 60 89 e5 bb be 07  b9 04 00 31 c0 53 51 f6 
14 000000d0  07 80 74 03 40 89 de 83  c3 10 e2 f3 48 74 5b 79 
15 000000e0  39 59 5b 8a 47 04 3c 0f  74 06 24 7f 3c 05 75 22
16 000000f0  66 8b 47 08 66 8b 56 14  66 01 d0 66 21 d2 75 03 
17 00000100  66 89 c2 e8 ac ff 72 03  e8 b6 ff 66 8b 46 1c e8 
18 00000110  a0 ff 83 c3 10 e2 cc 66  61 c3 e8 62 00 4d 75 6c 
19 00000120  74 69 70 6c 65 20 61 63  74 69 76 65 20 70 61 72 
20 00000130  74 69 74 69 6f 6e 73 2e  0d 0a 66 8b 44 08 66 03 
21 00000140  46 1c 66 89 44 08 e8 30  ff 72 13 81 3e fe 7d 55
22 00000150  aa 0f 85 06 ff bc fa 7b  5a 5f 07 fa ff e4 e8 1e 
23 00000160  00 4f 70 65 72 61 74 69  6e 67 20 73 79 73 74 65 
24 00000170  6d 20 6c 6f 61 64 20 65  72 72 6f 72 2e 0d 0a 5e 
25 00000180  ac b4 0e 8a 3e 62 04 b3  07 cd 10 3c 0a 75 f1 cd
26 00000190  18 f4 eb fd 00 00 00 00  00 00 00 00 00 00 00 00 
27 000001a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 
28 000001b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 80 02 
29 000001c0  03 01 0c 18 d8 cc 00 20  00 00 00 80 77 00 00 00 
30 000001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 
31 000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 
32 000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa 
33 00000200

linux 抓到的 blocks 是 7839744 也和 list 1. L12 計算的是一樣的值。這個值是說這張 sd card 有幾個 sector, 而每一個 sector 是 512 byte。

linux sd card info
[10848.308565] sd 1:0:0:0: Attached scsi generic sg1 type 0
[10849.270876] sd 1:0:0:0: [sdb] 7839744 512-byte logical blocks: (4.01 GB/3.74 GiB)

source code:
https://github.com/descent/stm32f4_prog/tree/master/spi_sdcard

突破這關後, 再來的 fat 檔案系統是純軟體, 對我來說就沒有那麼難了, 我煩惱的是要自己寫, 還是用現成的 library? 該讓我自己站在巨人的肩膀了, 造了那麼多輪子也是會累的。

me:
spi cpol, cpha 在 sd card 上一定要設成某個值嗎?
還是都可以:
ex:
SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;

Yen-Chin Lee:
SPI mode 0  或是 mode 3 都可以, mode 0 比較合適

不過暫時不急著搞 fat, 要先來玩玩我好久好久之前就想做的事情
fat 我搞定了, 而且也完成我想做的事情了。

ref:

About the module - pairs in 8x2 pin header are connected, which leaves 8 pins. And of those 2 are gnd and 2 are vcc (3,3 and 5 V). The schematic on the module suggests SPI pins correspond to SD interface as follows:
miso->dat0
gnd->gnd
sck->clk
3.3V->vcc
gnd->cmd
mosi->dat3
cs->dat2


沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。