目錄
- 前言
- 一:操作CS創世 SD NAND的常用命令
- 1.查看SD設備
- 2.掛載分區
- 3.卸載分區
- 4.分區管理
- 5.格式化分區
- 6.簡單讀寫
- 二:SD底層協議簡要介紹
- 三:對CS創世 SD NAND進行讀寫操作的三大方式
- 1. 使用dd命令
- 2. 使用塊設備的標準接口
- 3. 使用ioctl產生系統調用
- 四:CS創世 SD NAND的驅動框架介紹
- 1. MMC/SD驅動在linux中的結構層次
- 2. SD驅動中核心的數據結構舉例
- 3. host層函數調用關系解析
- 4. 卡的檢測
- 5. 掃描流程
- 6. 數據的讀寫
- 五:CS創世 SD NAND啟動
- 君正平臺
- 1. 制作SD啟動卡
- 2. 選擇啟動方式
- 3. 驗證SD啟動
- 瑞芯微平臺
- 1. 制作SD啟動卡
- 2. 選擇啟動方式
- 3. 驗證SD啟動
- 六、結語
前言
今天就瑞芯微平臺和北京君正平臺下的linux系統中關于CS創世 SD NAND的使用做一些經驗的分享,如有不正,請批評指正;
采用的開發板是RK3568和x2600e,ubuntu版本是20.04,交叉編譯工具鏈是aarch64-linux-gnu-
和mips-linux-gnu-
。
下面將從五個板塊來進行介紹,分別是操作CS創世 SD NAND的常用命令、SD底層協議簡要介紹、對CS創世 SD NAND進行讀寫操作的三大方式、SD的驅動框架介紹以及CS創世 SD NAND啟動,前三個板塊沒有瑞芯微和君正平臺之分,只要是跑linux系統,差別不大,第四塊以RK平臺為例,第五塊同時以君正平臺和RK平臺為例。
一:操作CS創世 SD NAND的常用命令
1.查看SD設備
使用lsblk
或fdisk -l
命令可以查看到sd設備節點,一般為/dev/mmcblkX
或/dev/sdX
,eg:/dev/mmcblk0
;
2.掛載分區
mount 設備分區 掛載點 eg:mount /dev/mmcblk0p1 /mnt/sdcard
3.卸載分區
umount 設備分區/掛載點 eg:umount /dev/mmcblk0p1 或 umount /mnt/sdcard
4.分區管理
fdisk 設備節點eg:fdisk /dev/mmcblk0
。進入交互頁面后常用命令:
p 打印分區表
n 創建新分區
d 刪除分區
t 更改分區類型
w 將更改寫入磁盤并退出
q 不保存更改退出
m 顯示幫助菜單
l 列出已知的分區類型
v 驗證分區表
g 創建新的空GPT分區表
o 創建新的空DOS分區表
在進行分區管理前請務必備份重要數據,因為在更改生效后會丟失原來數據;
5.格式化分區
格式化為FAT32:mkfs.vfat 設備分區;eg: mkfs.vfat /dev/mmcblk0p1
格式化為ext4:mkfs.ext4 設備分區;eg:mkfs.ext4 /dev/mmcblk0p2
6.簡單讀寫
cp,cat,echo等命令。eg:
復制文件:cp /usr/data/1.txt /mnt/sdcard/2.txt
查看文件內容:cat /mnt/sdcard/test.c
寫文件:echo "測試內容" > /mnt/sdcard/test.txt
二:SD底層協議簡要介紹
由于CS創世 SD NAND和SD卡遵守相同協議,并且標準協議中使用SD卡來描述,因此以下用詞使用SD卡代替CS創世 SD NAND。文本以雷龍發展提供的工業級CS創世 SD NAND FLASH為例,介紹讀寫方式準備協議的理論知識,僅做簡要介紹以及提醒一些需要注意的點,完整的協議內容較多,詳細請參考SD2.0協議標準完整版;
SD驅動中最重要的部分就是初始化,這里描述一下初始化流程,(需要區別四類卡,SDHC卡,SDSC卡,SD1.X卡,mmc卡)先是給SD卡上電,通常這一步在將卡插入卡槽就會自動完成,然后是發送CMD0進行軟復位,進入空閑模式,再發送CMD8,主機詢問SD卡是否支持電壓范圍,(SD1.X和mmc卡不會對CMD8產生響應,只有SDHC和SDSC卡會對CMD8回復R1響應);如果不響應再區分SD1.X和mmc卡,發送ACMD41(先發送CMD55告訴SD卡接下來發送的是應用命令),如果不響應就說明是mmc卡(此時發送CMD1激活mmc卡,mmc卡響應后即完成mmc卡的初始化),如果回復R1相應就說明是V1.X卡;
收到R1響應再區分SDHC和SDSC,然后發送ACMD41,主機告訴SD卡支持高容量,根據返回的R3響應中的OCR寄存器來判斷是標準還是高容量,只有當busy位置1時CCS位才有效,CCS位為1是高容量V2.0卡(即SDHC卡),CCS位為0是標準V2.0卡(即SDSC卡),至此區分出了V1.X,標準V2.0,高容量V2.0卡,這三種卡接下來的步驟一致:
發送CMD2獲取CID寄存器的值,SD卡會回復R2響應,再發送CMD3,SD卡獲得相對地址,流程圖如下圖所示:
然后是數據傳輸模式,初始化完成后進行數據傳輸就相對簡單了,只需要發送對應的命令即可,流程圖如下:
下面附上常用命令以及響應的圖:
最后提醒幾個需要注意的點:
- 第一是上電之后有一個時間段叫“供電上升時間”,這個是電壓上升到操作的總線電平以及等到能發送第一條命令的時間,這個時間需要在1ms,74個時鐘周期以及供電上升時間這三者中取最大值,其實這點在驅動源碼中也有體現,在mmc_power_up函數(drivers/mmc/core/core.c)如下圖所示,同時在協議的6.4.1章節也有說明,這個時間如果沒有等待而直接開始發送命令進行初始化,可能也能通過初始化,但是在后面的數據傳輸階段就有概率會出現問題了,如果沒有注意到這個供電上升時間,那么其實出現了異常是很難定位問題的;
- 第二是SD卡的兩種數據包格式,分別是常規數據和寬位數據,常規數據是指普通的8bit字節數據,發送規則是先發低字節再發高字節,每個字節是先發高位后發低位;而寬位數據一般指SD卡存儲寄存器,規則是先發高位,后發低位, 這點在解析SD卡寄存器時需要格外注意,否則就會發現解析的數據明顯不符規范;
三:對CS創世 SD NAND進行讀寫操作的三大方式
CS創世 SD NAND作為一種存儲設備,不外乎就是讀和寫,同時這也是最重要的,熟悉讀寫方式對于使用CS創世 SD NAND開發非常有幫助,因此在這一塊會詳細介紹;
1. 使用dd命令
- 使用前先掛載分區的文件系統(常用于寫入普通文件)
sudo dd if=輸入文件 of=輸出文件 bs=塊大小 status=狀態信息 其他選項參數···
eg:
sudo dd if=/mnt/sdcard/test.doc of=backup.doc bs=1M count=1
//將/mnt/sdcard/test.doc的前1M字節寫入backup.doc;
- 使用前不掛載分區的文件系統(常用于寫入鏡像文件,備份或擦除整個CS創世 SD NAND等)
sudo dd if=輸入設備 of=輸出設備 bs=塊大小 status=狀態信息 其他選項參數
eg:
sudo dd if=sd_back_up.img of=/dev/mmcblk0 bs=4M status=progress
//將sd_back_up.img以4MB的塊大小寫入/dev/mmcblk0,同時顯示進度和速度
sudo dd if=/dev/mmcblk1p1 of=/root/zboot.img bs=4M status=progress
//將mmcblk1p1設備中的所有數據讀取到/root/zboot.img文件下
如果要對讀取的數據進行限制,只讀取部分數據,那么使用參數skip或者count
sudo dd if=/dev/sdX of=/path/to/output.img bs=4M skip=10 status=progress
//skip:跳過前10個塊再開始讀取數據
sudo dd if=/dev/sdX of=/path/to/output.img bs=4M count=20 status=progress
//count:只讀取20個塊的數據
也可以結合skip和count,實現從特定位置讀取指定數量的數據;
注意:若使用前不掛載分區,那么在寫入之前請備份CS創世 SD NAND內重要數據,因為不掛載是繞過文件系統對原始存儲設備直接操作,會完全忽略文件系統結構,很可能會覆蓋已有數據,甚至可能會損壞文件系統,嚴重的話只能重新格式化;
如果是先掛載了分區,那么dd命令會通過文件系統進行操作,相對安全;
2. 使用塊設備的標準接口
通過文件io或標準io進行讀寫,無論是掛載文件系統還是不掛載文件系統,都能使用文件io或標準io對CS創世 SD NAND進行操作,區別是前者通過文件系統較為安全且效率稍低而后者直接操作硬件存儲設備效率更高同時對于數據的寫入需要更加注意防止覆蓋重要數據,下面分別提供兩個示例;
第一個示例:使用標準io(fopen,fwrite,fread,fseek,fclose
等)在已掛載文件系統的CS創世 SD NAND上進行讀寫,總所周知,在linux里流傳著一句話,那就是“一切皆文件”,在這種情況下操作掛載點的文件其實與操作一般文件基本無異;示例實現的功能是在SD卡掛載目錄/mnt/sdcard/目錄下創建test_data.txt文件,然后再往里面寫入4次0~255,然后再將數據讀取出來驗證是否寫入成功并打印測試結果;
編譯命令是aarch64-linux-gnu-gcc test2.c -o test2
,編譯成功后使用sftp root@ip
將test2發送至開發板運行測試,運行結果以及程序見下面兩張圖;
第二個示例:使用文件io(open,write,read,lseek,close
)對未掛載文件系統的CS創世 SD NAND直接操作;實現的功能是從CS創世 SD NAND的第1000塊開始寫入512字節數據,數據內容為0255,0255,寫入后再把數據讀取出來比較是否成功并打印結果;
編譯命令是:aarch64-linux-gnu-gcc test.c -o test
,編譯成功后使用sftp root@ip
將test2發送至開發板運行測試,運行結果和程序也如下面兩張圖所示
3. 使用ioctl產生系統調用
陷入內核進行處理,前兩種方式都容易實現,而且不需要關注底層發送的命令,而ioctl可以對CS創世 SD NAND進行精細的命令控制來約束NAND的行為,并且在ioctl使用過程中還有一些需要注意的點,如果想要對CS創世 SD NAND進行最為底層的命令操作,那么ioctl必定是是首選,因此著重介紹這種方式;
使用ioctl來對CS創世 SD NAND發送命令,其中最為重要的就是填充struct mmc_ioc_cmd
結構體,結構體的詳細定義位于kernel/include/uapi/linux/mmc/ioctl.h,其中關于flags即命令標志位掩碼的定義位于/include/linux/mmc/core.h文件中的struct mmc_command結構體中,下面對struct mmc_ioc_cmd
結構體的各成員作詳細介紹,如下圖所示:
介紹完struct mmc_ioc_cmd
結構體后細心的小伙伴會發現了這里面幾乎所有的參數都好填充,唯獨flags,命令標志位掩碼的定義在core.h中,如下圖所示:
那么在編寫ioctl的程序時,填充flags需要用到core.h里面的內容,總所周知,linux里面的隔離是很嚴重的,在應用層調用內核層的定義,這是不允許的,編譯會報錯,之前剛開發的時候因為這個編譯報錯還折騰了不少時間,最終的解決辦法就是把這些標志位的宏定義復制到自己寫的應用程序中,這樣就沒有報錯了,下面提供一份程序
程序較長,文件名是init.c(見附件),編譯命令是:aarch64-linux-gnu-gcc init.c -o init
,編譯成功后使用sftp root@ip(若有adb功能也可使用adb push)將可執行程序init發送至開發板進行運行測試,文件中包含ioctl使用的詳細解釋,下面三張圖是運行結果截圖(前兩張)以及使用邏輯分析儀抓取的命令(第三張圖),波形文件名是:init.TLW,見附件,兩者都與程序一致,運行過程中沒有報錯,這就是使用ioctl向CS創世 SD NAND發送底層命令的詳細過程;
關于ioctl的使用,有下面幾點需要格外注意,這些都是小編親身走過的坑,所謂前人栽樹,后人乘涼, 也算方便大家“乘涼”了哈哈;
第一是如果進行的是寫操作,例如發送CMD24,CMD25等命令,那么struct mmc_ioc_cmd
結構體的write_flag必須要賦值為非零值,如果是0值,那么很容易導致發送命令失敗,得到“errno=110 (Connection timed out)”的錯誤信息,這個錯誤信息相對常見,意為連接超時,分析函數調用鏈可知:在__mmc_blk_ioctl_cmd
(drivers/mmc/core/block.c)函數中有
根據write_flag的值會進一步增加MMC_DATA_WRITE或MMC_DATA_READ的標志再傳到驅動中,因此發送寫命令時請務必給write_flag賦非零值;
第二是在SD卡初始化完成后,開始數據傳輸前,需要發送ACMD6定義數據總線的寬度,分析源碼可知:在mmc_sd_init_card
(drivers/mmc/core/sd.c)函數中有如下圖所示部分
SD和主機通常都是同時支持4位數據總線寬度的,在不修改SD驅動的情況下,主機控制器是4位總線寬度,所以如果不發送ACMD6,那么卡會保持默認的1位總線寬度,此時主機和NAND的總線寬度不一致,就會出現“errno=84 (Invalid or incomplete multibyte or wide character)”的錯誤信息,含義是無效或不完整的多字節或寬字符,解決辦法有兩種,一種是修改驅動源碼,將主機控制器的總線寬度固定為1位,此時可以不發送ACMD6,主機和 CS創世 SD NAND都使用1位數據總線通信,第二種是發送ACMD6通知卡改變總線寬度為4位,兩者都用4位總線傳輸數據,ACMD6的參數說明如下圖,很明顯要第二種方式更簡單,因此如果遇到errno=84的錯誤碼,檢查一下主機和CS創世 SD NAND的總線寬度是否一致;
第三是頻率問題,如果使用ioctl發送cmd時,檢查了命令和各項參數都沒有錯,也沒犯上面兩種錯誤,但是運行程序發現就是會報各種錯,例如下圖(運行的是示例程序init)
那么很大概率就是頻率太高,CS創世 SD NAND接受不了,此時需要降頻,如下圖
降低頻率后再次運行,運行結果見下圖
只要多加注意以上三點,相信使用ioctl就沒有什么大問題;
四:CS創世 SD NAND的驅動框架介紹
以瑞芯微平臺的RK3568驅動源碼為例
1. MMC/SD驅動在linux中的結構層次
通常在linux系統中,MMC/SD設備都是被抽象成塊設備來處理,在kernel的頂層目錄下的drivers/mmc目錄下通常有三個文件夾分別是core、card和host,有些驅動會將core和card合并成一個core,例如RK3568就是只有core和host,這個驅動框架就是以RK平臺的SD驅動來介紹的,下面解釋三個文件夾的作用;
1.card層: 要把操作的數據以塊設備的處理方式寫到存儲設備上或從存儲設備上讀取;因為CS創世 SD NAND屬于塊設備,那么必然要提供塊設備的驅動程序,這部分就是解決了一個問題,即如何將你的CS創世 SD NAND實現為塊設備的。
2.core 層:則是將數據以何種格式,何種方式在 MMC/SD主機控制器與MMC/SD卡的記 憶體(即塊設備)之間進行傳遞,這種格式、方式被稱之為規范或協議.
這部分完成了不同協議和規范的實現,抽離出不同SD主機控制器的共性,并為HOST 層的驅動提供了接口函數
3.host 層: 是這個文件夾屬于 Linux 內核中 MMC/SD 子系統 的 硬件驅動層,直接負責與 MMC/SD 主機控制器(Host Controller) 的硬件交互。它的核心作用是向上提供統一的接口供 Core 層 調用(如發送命令、讀寫數據),向下為不同廠商的 Host 控制器提供驅動實現,將上層(Core 層)的協議請求轉換為具體的寄存器操作、時鐘控制、DMA 傳輸等硬件行為。
core層根據協議規范來構造各種命令,那么命令是怎么發送給CS創世 SD NAND呢?通過主機控制器。
主機控制器通過設置SD需要的gpio資源,注冊中斷資源,使能控制器等等,然后再向上面的核心層增加一個host,這樣核心層就能調用具體的硬件操作函數來和SD卡通信了;
card和core是封裝好的共性以及規范,通常是不需要修改的,而host層是直接與硬件打交道,需要控制底層寄存器的,不同的host控制器硬件資源也不一樣,因此驅動CS創世 SD NAND,host層才是應該需要修改開發的,MMC/SD驅動在linux中的結構層次見下圖:
2. SD驅動中核心的數據結構舉例
(CS創世 SD NAND和SD卡在驅動中使用的數據結構和調用的函數是一致的,并且有不少數據結構命名或函數功能注釋翻譯過來用SD卡描述更貼切,因此下面描述用詞使用SD卡代替CS創世 SD NAND,不再贅述)
1.struct mmc_host
功能:表示一個MMC/SD卡主機控制器,它是驅動程序和內核MMC子系統之間的主要接口;
重要成員:
const struct mmc_host_ops *ops:包含操作該主機的各種函數指針,包括發送命令,設置時鐘和電源,請求操作等,用于和硬件交互
struct device class_dev:代表該主機控制器的設備對象,可用于設備模型的注冊和管理
unsigned int f_min:主機控制器支持的最小時鐘頻率
unsigned int f_max:主機控制器支持的最大時鐘頻率,對于SD卡的操作頻率非常重要
struct mmc_card *card:指向插入該主機的SD卡設備
struct mmc_ios ios:包含了當前IO的狀態信息,例如時鐘頻率,電壓范圍,電源模式等
const struct mmc_bus_ops *bus_ops:指向struct mmc_bus_ops結構體,定義了和MMC卡通信的操作集,例如讀寫,卡檢測等;
u32 ocr_avail:存儲MMC主機可用的操作條件寄存器OCR的值,
u32 caps:表示MMC主機的能力和特性,通過不同的位來標記主機的各種模式;
- struct mmc_card
功能:表示一個插入到MMC主機控制器的SD卡設備
重要成員:
struct mmc_host *host:指向SD卡所連接的主機控制器
unsigned int rca:相對卡地址,是SD卡的重要標識符,用于在總線上唯一標識該卡
unsigned int type:卡類型,例如MMC,SD,SDIO等,用于區分不同的設備類型
u32 ocr:操作條件寄存器,包含了SD卡的操作條件信息,例如支持的電壓范圍,電源模式等;
struct mmc_cid cid:包含卡的CID信息,例如制造商id,產品名稱等;
- struct mmc_ios
功能:包含SD主機控制器的IO狀態信息
重要成員:
unsigned int clock:當前的時鐘頻率,驅動可以根據需要調整此時鐘頻率,來滿足不同操作的需求;
unsigned char power_mode:電源模式,例如MMC_POWER_OFF,MMC_POWER_UP,用于控制SD卡的電源狀態
unsigned char bus_width:總線寬度,可以選擇1線,4線,8線,根據SD卡的能力和操作需求進行調整
- struct mmc_host_ops
功能:包含了操作MMC主機控制器的一系列函數指針,是驅動程序與硬件交互的接口;
重要成員舉例:
void (*request)(struct mmc_host *host, struct mmc_request *req):函數指針,用于將一個操作請求添加到主機控制器的請求隊列中
void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios):用于設置主機控制器的IO狀態,例如調整時鐘頻率,電源模式和總線寬度等等;
int (*start_signal_voltage_switch)(struct mmc_host *host, struct mmc_ios *ios):在需要切換SD卡的操作電壓時調用此函數;
int (*get_ro)(struct mmc_host *host):檢查MMC/SD卡是否被寫保護了;
int (*get_cd)(struct mmc_host *host):檢查SD卡的插入和拔出;
- struct mmc_request
功能:表示一個對SD卡的操作請求,通常包括命令,數據傳輸等信息;
重要成員:
struct mmc_command *cmd:指向要執行的命令;
struct mmc_data *data:指向要傳輸的數據對象,用于數據塊的讀寫操作;
3. host層函數調用關系解析
這里主要做了兩件事,其一是mmc_alloc_host分配一個mmc_host,其二是mmc_add_host添加一個mmc_host;
4. 卡的檢測
我們用的SD卡只是一張卡,要操作卡還得通過主機控制器才行,因此會有struct mmc_card,struct mmc_host之分,截至這里再回憶一下 dw_mci_init_slot做的事情,大概就是準備一個 mmc_host 結構,然后添加一個主控制器設備到內核,最后又調用了一下 mmc_rescan 來檢測是不是有卡插入了,有人會問如果此時卡沒有插入呢,那么不就是白白調用一次mmc_rescan,那下次卡插入又是怎么檢測到的呢,很明顯,這種不能確定觸發時間的完全未知的動作,肯定是需要通過中斷機制來處理,檢測到卡插入,觸發中斷,掃描卡,開始初始化等流程,檢測到卡拔出觸發中斷,清理各類資源,釋放空間;
5. 掃描流程
struct mmc_card 結構里面包含了一個 struct device 結構, mmc_alloc_card 不但申請了內存,而且還填充了 struct device 中的幾個成員,尤其 card->dev.bus = &mmc_bus_type; 這一句要重點對待,mmc_bus_type的定義如下圖
申請一個 mmc_card 結構,并簡單初始化后, mmc_init_card 的使命就完成了,然后再調用 mmc_add_card 將這個 card 設備添加到內核。 mmc_add_card 其實很簡單,就是調用 device_add 將 card->dev 添加到內核當中去;
device_add 里面,設備對應的總線會拿著你這個設備和掛在這個總線上的所有驅動程序去匹配( match ),此時會調用 match 函數(如下圖),如果匹配到了就會調用總線的 probe 函數或驅動的 probe 函數;
所以match永遠不會失敗,匹配成功就會執行mmc_bus_probe(定義見下圖)
追蹤到這里,probe由調用了 drv->probe() ,這就需要知道drv的定義了,struct mmc_driver*drv=to_mmc_driver(dev->driver);match 函數總是返回 1 ,說明掛在這條總線上的 driver 都有可能跑到這里來了,事實的確也是這樣的,不過好在掛在這條總線上的 driver 只有一個,定義見下圖:
因此跳轉到mmc_bllk_probe函數執行,函數定義如下:
mmc_blk_probe 是 MMC 塊設備驅動的核心探測函數,負責將 MMC/SD 卡注冊為塊設備,使其能夠被系統訪問,看到這里已經把core,host目錄下的文件都牽扯進來了,慢慢再捋一下就能看出從host到core的聯系了;
6. 數據的讀寫
在驅動中,向SD卡發送cmd都是通過請求隊列來完成的,所有的cmd都會被封裝成請求,然后由內核的I/O調度器統一排序,合并或拆分,再下發給硬件驅動,這樣避免了驅動直接操作硬件,而是通過標準接口解耦,增強了安全性和可維護性,所以分析cmd的發送首先要定位到request請求隊列,關鍵函數調用流程如下圖:
順便附上上圖中提到的兩個ops操作集合的賦值:
分析到這里,整個SD驅動框架做的事情說簡單一些其實就干了兩件事,一是卡的掃描檢測,而是數據的讀寫,不過這個過程中涉及到的數據結構和函數調用確實相對復雜,捋清楚驅動框架還是需要靜下心來花費時間的;
五:CS創世 SD NAND啟動
相同的板卡廠商一般CS創世 SD NAND啟動的流程固定,大致講一下流程,首先是要制作SD啟動卡,即將啟動鏡像燒錄進CS創世 SD NAND,一般板卡廠商都會有專門的制作工具,只需按照使用方法來制作啟動卡即可,如果沒有制作工具,那么一般使用dd命令將系統鏡像寫入卡內(寫入時可能有地址參數要求,需要咨詢板卡廠商的技術支持),然后是選擇啟動方式,一般是有幾個boot引腳,啟動時系統會根據boot引腳的電平組合來選擇啟動方式,有些開發板可能在選擇CS創世 SD NAND啟動時還需要配置其他內核參數,只需咨詢對應的技術即可,最后就是驗證系統是否能正常從SD啟動,數據讀寫是否正常;
君正平臺
開發板是x2600e,CS創世 SD NAND是采用CS256G-AOW;
1. 制作SD啟動卡
君正的燒錄工具支持將啟動鏡像燒錄到CS創世 SD NAND,先編譯準備好啟動鏡像,然后按照下圖順序進行制作啟動卡;
2. 選擇啟動方式
查詢芯片手冊得知啟動方式的選擇依據如下圖
再查看原理圖如下:
可知目前的電平組合是001,即選擇的是SFC@PD06_3.3V(默認從SPI NAND FLASH啟動),現在需要改為從SD啟動,那么就要將BOOT_SET0即PD14接低電平,使得電平組合為000,然后就是查看PCB,找到PD14的gpio,再修改硬件將其接地即可;
3. 驗證SD啟動
通過上圖可知,系統成功從CS創世 SD NAND啟動,然后使用一些簡單的讀寫命令驗證是否正常即可,一般而言只要能正常啟動系統讀寫就沒問題,因為啟動過程中本身就已經包含了對SD進行讀寫。
瑞芯微平臺
開發板是RK3568,CS創世 SD NAND采用CS256G-AOW,也采取相同步驟;
1. 制作SD啟動卡
首先編譯準備好鏡像文件,并將其拷貝到windows端(可以將鏡像放置共享目錄下),然后打開瑞芯微的制作工具SDDiskTool,按照下圖所示進行配置:
正常來說制作過程是2~3分鐘,但是也遇到過十分鐘左右的,這個可能因CS創世 SD NAND而異,但是只要沒報錯,就耐心等待制作完成;
2. 選擇啟動方式
由于咨詢技術支持得到的答復是RK對于啟動引導不開源,原理也是靠硬件選boot腳,然后在芯片手冊上也沒找到有關boot引腳配置的部分,所以說明在RK上我們不需要修改硬件,額外配置boot引腳來選擇啟動方式,后面在rockchip-common.h文件中找到了關于啟動方式的優先順序,如下圖:
因此只要啟動時在卡槽檢測到CS創世 SD NAND,那么就會優先從SD啟動;
3. 驗證SD啟動
從上面兩張圖中可以相互印證,系統成功從SD啟動;
啟動卡的分區情況如下圖:
從mmcblk1p1至mmcblk1p6共6個分區,依次是uboot,misc,boot,recovery,backup和rootfs,前面5個分區一般存儲特定數據,不建議用戶將數據寫入,而mmcblk1p6是根文件系統分區,存儲所有系統文件、應用程序、用戶數據等,進行用戶操作時就是基于這個分區,因此進行讀寫測試或者存儲用戶數據建議在此分區進行。
六、結語
最后分享一些使用的軟件:
串口工具:Windows下:MobaXterm;Ubuntu下:Minicom
分析內核源碼:source insight 4
邏輯分析儀:ATK-Logic 或Acute TravelLogic Analyzer
除了軟件,硬件上的邏輯分析儀,示波器,萬用表也可輔助調試驗證。