linux下SD卡烧录程序
1.文件mkv210_image.c詳解
?
分析啟動過程可知:
210 啟動后先執行內部iROM中的BL0,BL0執行完后會根據OMpin 的配置選擇一個外部設備來啟動(有很多,我們實際使用的有2個:usb 啟動和SD卡 啟動)。在 usb 啟動時內部 BL0 讀取到 BL1 后不做校驗,直接從 BL1 的實質內部 0xd0020010 開始執行,因此 usb 啟動的景象 led.bin 不需要頭信息,因此我們從 usb啟動時直接將鏡像下載到 0xd0020010 去執行即可,不管頭信息了;從 SD 啟動時,BL0 會首先讀取 SD卡 得到完整的鏡像(完整指的是 led.bin 和 16字節 的頭),然后BL0 會自己根據你的實際鏡像(指led.bin)來計算一個校驗和 checksum,然后和你完整鏡像的頭部中的 checksum 來比對。如果對應則執行 BL1,如果不對應則啟動失敗。
mkv210_image.c的作用:
為BL1添加校驗頭,我們編譯鏈接時只得到了led.bin,這個210.bin的得到和交叉編譯工具鏈是完全無關的。由led.bin得到210.bin的過程是三星的S5PV210所特有的,因此需要我們自己去完成,為此我們寫了mkv210_image.c來完成。
整個程序工作流分析:
整個程序中首先申請一個16KB大小的buffer,然后把所有內容按照各自的位置填充進去,最終把填充好的buffer寫入到一個文件(名叫210.bin)就形成了我們想要的鏡像。
/** mkv210_image.c的主要作用就是由usb啟動時使用的led.bin制作得到由sd卡啟動的鏡像210.bin** 本文件來自于友善之臂的裸機教程,據友善之臂的文檔中講述,本文件是一個熱心網友提供,在此表示感謝。*/ /* 在BL0階段,Irom內固化的代碼讀取nandflash或SD卡前16K的內容,* 并比對前16字節中的校驗和是否正確,正確則繼續,錯誤則停止。** */ #include <stdio.h> #include <string.h> #include <stdlib.h>#define BUFSIZE (16*1024) #define IMG_SIZE (16*1024) #define SPL_HEADER_SIZE 16 //#define SPL_HEADER "S5PC110 HEADER " #define SPL_HEADER "****************"int main (int argc, char *argv[]) {FILE *fp;char *Buf, *a;int BufLen;int nbytes, fileLen;unsigned int checksum, count;int i;// 1. 3個參數if (argc != 3){printf("Usage: %s <source file> <destination file>\n", argv[0]);return -1;}// 2. 分配16K的bufferBufLen = BUFSIZE;Buf = (char *)malloc(BufLen);if (!Buf){printf("Alloc buffer failed!\n");return -1;}memset(Buf, 0x00, BufLen);// 3. 讀源bin到buffer// 3.1 打開源binfp = fopen(argv[1], "rb");if( fp == NULL){printf("source file open error\n");free(Buf);return -1;}// 3.2 獲取源bin長度fseek(fp, 0L, SEEK_END); // 定位到文件尾fileLen = ftell(fp); // 得到文件長度fseek(fp, 0L, SEEK_SET); // 再次定位到文件頭// 3.3 源bin長度不得超過16K-16bytecount = (fileLen < (IMG_SIZE - SPL_HEADER_SIZE))? fileLen : (IMG_SIZE - SPL_HEADER_SIZE);// 3.4 buffer[0~15]存放"S5PC110 HEADER "memcpy(&Buf[0], SPL_HEADER, SPL_HEADER_SIZE);// 3.5 讀源bin到buffer[16]nbytes = fread(Buf + SPL_HEADER_SIZE, 1, count, fp);if ( nbytes != count ){printf("source file read error\n");free(Buf);fclose(fp);return -1;}fclose(fp);// 4. 計算校驗和// 4.1 從第16byte開始統計buffer中共有幾個1// 4.1 從第16byte開始計算,把buffer中所有的字節數據加和起來得到的結果a = Buf + SPL_HEADER_SIZE;for(i = 0, checksum = 0; i < IMG_SIZE - SPL_HEADER_SIZE; i++)checksum += (0x000000FF) & *a++;// 4.2 將校驗和保存在buffer[8~15]a = Buf + 8; // Buf是210.bin的起始地址,+8表示向后位移2個字,也就是說寫入到第3個字*( (unsigned int *)a ) = checksum;// 5. 拷貝buffer中的內容到目的bin// 5.1 打開目的binfp = fopen(argv[2], "wb");if (fp == NULL){printf("destination file open error\n");free(Buf);return -1;}// 5.2 將16k的buffer拷貝到目的bin中a = Buf;nbytes = fwrite( a, 1, BufLen, fp);if ( nbytes != BufLen ){printf("destination file write error\n");free(Buf);fclose(fp);return -1;}free(Buf);fclose(fp);return 0; }?
?
2.dd命令
?
dd命令作用:指定大小的塊拷貝一個文件,并在拷貝的同時進行指定的轉換,起到一個初始化磁盤的作用
dd?的主要選項:
if=file?
輸入文件名,缺省為標準輸入。
of=file?
輸出文件名,缺省為標準輸出。
ibs=bytes?
一次讀入 bytes 個字節(即一個塊大小為 bytes 個字節)。
obs=bytes?
一次寫出 bytes 個字節(即一個塊大小為 bytes 個字節)。
bs=bytes?
同時設置讀寫塊的大小為 bytes ,可代替 ibs 和 obs 。
cbs=bytes?
一次轉換 bytes 個字節,即轉換緩沖區大小。
skip=blocks?
從輸入文件開頭跳過 blocks 個塊后再開始復制。
seek=blocks?
從輸出文件開頭跳過 blocks 個塊后再開始復制。(通常只有當輸出文件是磁盤或磁帶時才有效)。
count=blocks?
僅拷貝 blocks 個塊,塊大小等于 ibs 指定的字節數。
conv=conversion[,conversion...]?
用指定的參數轉換文件。
轉換參數:?
ascii 轉換 EBCDIC 為 ASCII。
ebcdic?轉換 ASCII 為 EBCDIC。
ibm?轉換 ASCII 為?alternate EBCDIC.?
block 把每一行轉換為長度為 cbs 的記錄,不足部分用空格填充。
unblock?使每一行的長度都為 cbs ,不足部分用空格填充。
lcase?把大寫字符轉換為小寫字符。
ucase?把小寫字符轉換為大寫字符。
swab?交換輸入的每對字節。??
noerror 出錯時不停止。
notrunc?不截短輸出文件。 不取整指令
sync?把每個輸入塊填充到ibs個字節,不足部分用空(NUL)字符補齊。
?
?
3.使用方法
比如:使用SD卡燒錄led.bin到s5pv210中
1)編譯mkv210_image.c文件生成mkmini210? ? ? ? ? ? ? ? ? ? ? ? ? ? gcc mkv210_image.c -o mkmini210
2)使用mkmini210對led.bin進行加頭部處理生成210.bin? ? ? ? ? ?./mkmini210 led.bin 210.bin
3)使用dd命令將210.bin文件燒錄到SD中? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sudo dd iflag=dsync oflag=dsync if=210.bin of=/dev/sdb seek=1
4)將SD卡插入卡槽,s5pv210選擇為SD卡啟動方式
總結
以上是生活随笔為你收集整理的linux下SD卡烧录程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Simulink之三相桥式半控整流电路
- 下一篇: linux内核源码目录分析