作者:gooogleman@foxmail.com 2008-12-04
在前段時間,songtitan牛人在論壇說了一下使用SD卡更新NK的方法。如下:
http://topic.csdn.net/u/20081009/17/4E0F5E66-C7A0-43D2-B33F-14E132280F70.html
在CE下和在bootloader下都可以實現更新NK.
1 在CE下
可以直接用檔案系統API讀出NK.bin,放到記憶體buffer中,在通過DEVICEIOCTL的方式來調用nand驅動的接一些介面來直接對nand flash進行寫操作。
好處:跳過boot section,FAT/FAT32檔案系統的解析;對記憶體大小無要求
缺點:NAND驅動需要暴露讀寫的IOCTL,必須進入OS才能更新OS,如果OS掛了的話,無法更新。
2 bootloader下
直接對SD CONTROLLER操作來對SD卡進行讀寫,解析FAT/FAT32格式,找到NK.BIN,並能將其讀取到記憶體中,再假設NK.BIN如下載一般到記憶體中,將其燒寫到nand flash中。
好處:只要bootloader不掛,就可以對OS進行更新;
缺點:需要自己解析BOOT SECION,FAT/FAT32檔案系統;需要至少和NK.BIN大小相同的剩餘RAM
如果BSP本身沒有支援bootloader下的SD更新nk,自己研究還是需要不少工作量的,最好的捷徑就是能“弄到”別的平台的SD更新代碼,改動就只是SD HOST controller部分。
=======================現在我的工作就是詳細弄出怎麼實現這個東西==========================
公司要求在bootloader階段實現SD更新NK,並且說要實現用觸控螢幕操作,我覺得這個在裸奔階段實現觸控螢幕菜單太難了,簡直是不可能的事情。如果非要實現的話就一定要加上GUI,那bootloader搞的這麼大,就沒有什麼意義了。我現在覺得有一種方法可行:就是放棄使用SD卡更新NK的辦法,而是在flash裡面備份一個NK,更新的時候就把備份NK放到啟動的NK上。這樣實現起來bootloader修改簡單,在wince起來之後實現也不困難。現在的flash都已經1G以上了,那點容量犧牲不成問題,並且SD卡也騰出了空間——哈哈,好,就模仿ghost做一個嵌入式還原精靈吧。
====================================================================================
——經過幾天的思索,我覺得在flash上做備份有點不妥當,因為flash有時候不穩定,很容易出問題。現在還是決定採用系統起來後更新NK的方法。很榮幸在這裡找了個很好的老文章——--------------------------------------wince下將flash中的內容全部讀出來
http://topic.csdn.net/u/20080530/10/8A86B2C8-1623-4AB9-ACA7-D5DE24994CF6.html內容經典,摘抄下來。
--------------------------------------------------------------------------
硬體:2410 ,64M nandflash,64M RAM
我現在在想在wince下將難道中的內容從地址0,到nandflash結束,全部讀出來,
該怎麼做!
就好像是給台式電腦做GHOST備份一樣,不同的是NANDFLASH為空白的地方我們也要讀取!
緊急,謝謝
--------------------------------------
要看你的檔案系統是否支援.因為檔案系統只能識別被分區的地方,那沒有分區的空白地區是無法通過WINCE API訪問到的.一般flash都有專用的讀寫器直接複製晶片內容的,也就是生產時用來做母片的工具。
--------------------------------------
恐怕只能自己寫一個簡單的flash driver,從頭到尾讀一遍了。wince的fat檔案系統肯定是不能保證按flash的物理地址順序讀的。
--------------------------------------
NAND上一層是DISK介面了,不會有相應的API供你讀取所有內容的。
如果能修改驅動,那麼就讓驅動開放一個特殊的IOContrl Code給你,輸入位址範圍,輸出是將位址範圍內的資料全部放到指定的buf指標地址去。Nand flash的驅動,修改FMD_OEMIoControl函數
-----------------------------------------------------------------
是標準的流介面,其實還是用DSK驅動就行,只是你自己設計一個原來沒有的IOCONTROL_CODE,通過Device的IOControl()函數傳下去時,在NAND FLASH的驅動中的IOControl直接判斷,如果滿足,就將指定範圍的資料都讀到指定的地址空間。
9樓的有個小錯誤,NAND驅動的讀函數裡已經做了ECC校正了,通過FMD_NAND_READ這樣的函數讀出來的資料是不需要再ECC校正的。
------------------------------------------------------------------------
引用 13 樓 so927 的回複:
引用 12 樓 jlctt 的回複:
修改FMD中FMD_OEMIoControl代碼,開放FMD_ReadSector/FMD_WriteSector介面訪問,然後用DeviceIoControl去訪問整個NAND Flash.
明白您的意思了,我覺得也可以這樣實現,謝謝提醒,
不過還有一個問題,我會不會把壞塊也一起讀出來了,每讀一個塊我是不是都需要檢測一下是不是壞塊呢
是的,需要的
=========================================抄貼結束======================================
——這幾天,我首先在學習EVC讀寫SD卡程式,剛開始以為可以像PC一樣malloc幾十M的記憶體,結果實驗發現當讀400K寫字板的時候已經那個非常慢,看來一次性讀寫30M的想法是行不通的。今天終於分段讀寫30M核心檔案成功,下面是關鍵代碼。
-
C/C++ code
-
- //我把30M的檔案讀出來,再存放到一個檔案,已經完全可行。該結貼了,是修改flash驅動的時候了。晚上回去結貼。
- //==================從檔案中分段讀出資料,每次30K ,讀1024次,共30M====================
- for (unsigned int count=0;count<READCOUNT;count++)
- {
- SetFilePointer(hFile, m_FilePointer, NULL, FILE_BEGIN); /* 移動檔案指標到檔案開頭 */
- if (ret == 0xFFFFFFFF)
- {
- MessageBox(_T("將檔案指標移至檔案指定處失敗!"));
- return;
- }
- pcharbuff=(char *)malloc(READSIZE); //每次申請30K的記憶體
- ret = ReadFile(hFile, pcharbuff, READSIZE, &actlen, NULL); /* 從檔案中分段讀出資料,每次30K */
- if (ret == FALSE)
- MessageBox(_T("讀檔案失敗!"));
-
-
- //--------------------write read file to wogo.nb0-----------------------
- //--讀出30K,就寫30K
- SetFilePointer(hTestFile, m_FilePointer, NULL, FILE_BEGIN); /* 移動檔案指標到檔案開頭 */
- if (ret == 0xFFFFFFFF)
- {
- MessageBox(_T("將檔案指標移至檔案指定處失敗!"));
- return;
- }
- ret = WriteFile(hTestFile, pcharbuff, READSIZE, &writelen, NULL); /* 將資料寫入檔案中 */
- if (ret == FALSE)
- MessageBox(_T("寫檔案失敗!"));
-
- free((void *)pcharbuff);//釋放記憶體
-
-
- m_FilePointer=m_FilePointer+READSIZE;//每次檔案指標下移30K
- //if (count==1023)
- //{
- // MessageBox(_T("讀檔案成功!"));
- //}
- }
——做這個除了瞭解了一下wince 虛擬記憶體申請以外,還得出:不管是二進位檔案還是文字檔,
-
使用的讀寫函數都一樣,要想把二進位的資料讀出來顯示,不能使用顯示文字檔的方法。
-
=============================flash驅動修改部分==============================
http://blog.csdn.net/nanjianhui/archive/2008/03/19/2196466.aspx微軟MVP的文章
——應用程式直接控制flash
===========================採用wince運行下更新NK的方法成功===========================
——現在公布要點。
一、在FMD中增加下面代碼
- //------------------------------------------------------------------------------
- //---------------------------應用程式和flash直接通訊-------希望大家看了有啟發---
- //------------------------------------------------------------------------------
- static DWORD g_dwStartSector=2*64;
- BOOL FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
- {
-
- switch(dwIoControlCode)
- {
- case 0x77777777:
- for(unsigned int i=2;i<=242;i++)//30M NK 佔用240 block
- FMD_EraseBlock(i); //察除NK所佔地區30M
- RETAILMSG(1, (TEXT("FMD_OEMIoControl: recognized IOCTL.FMD_EraseBlock (0x%x)./r/n"), dwIoControlCode));
-
- break;
- case 0x12345678:
- //寫入NK所佔地區——這個要看eboot中的函數才知道具體起始block
- //RETAILMSG(1, (TEXT("FMD_OEMIoControl: recognized IOCTL.FMD_WriteSector(0x%x)./r/n"), dwIoControlCode));
-
- RETAILMSG(1, (TEXT("FMD_OEMIoControl: recognized IOCTL.FMD_WriteSector(0x%x)./r/n"), nInBufSize));
- RETAILMSG(1, (TEXT("FMD_OEMIoControl: nInBufSize=%d./r/n"), nInBufSize));
- //for(unsigned int k=0;k<nInBufSize;k++)
- // {
- // FMD_WriteSector(g_dwStartSector,pInBuf,NULL,1);
- // g_dwStartSector=g_dwStartSector+1;
- // }
- //FMD_WriteSector函數的參數很關鍵,pInBuf是應用程式傳入,並且大小隻能是一個page
- //FMD_WriteSector的代碼推測出,pInBuf只能是一個page
- FMD_WriteSector(g_dwStartSector,pInBuf,NULL,1);
- if(g_dwStartSector<=242*64)
- g_dwStartSector=g_dwStartSector+1;
- break;
-
-
- default:
- RETAILMSG(1, (TEXT("FMD_OEMIoControl: unrecognized IOCTL (0x%x)./r/n"), dwIoControlCode));
- return(FALSE);
- }
- return TRUE;
- }
轉載請標明:作者wogoyixikexie@gliet.桂林電子科技大學一系科協。如有錯誤,希望能夠留言指出;如果你有更加好的方法,也請在部落格後面留言,我會感激你的批評和分享。