是現在市場上兩種主要的非易失閃存技術。Intel於1988年首先開發出NOR Flash 技術,徹底改變了原先由EPROM(Electrically Programmable Read-Only-Memory電可編程序只讀存儲器)和EEPROM(電可擦只讀存儲器Electrically Erasable Programmable Read - Only Memory)一統天下的局面。緊接着,1989年,東芝公司發表了NAND Flash 結構,強調降低每比特的成本,有更高的性能,並且像磁盤一樣可以通過接口輕松升級。NOR Flash 的特點是芯片內執行(XIP ,eXecute In Place),這樣應用程序可以直接在Flash閃存內運行,不必再把代碼讀到系統RAM。
這樣我們知道程序能直接在norlash執行的原因在XIP
那:什么是XIP?工作原理又是怎么樣的?
XIP eXecute In Place
eXecute In Place,即芯片內執行,指應用程序可以直接在flash閃存內運行,不必再把代碼讀到系統RAM中。flash內執行是指nor flash 不需要初始化,可以直接在flash內執行代碼。但往往只執行部分代碼,比如初始化RAM.
(注:片內執行不是說程序在存儲器內執行哦,CPU的基本功能就是取指、譯碼和執行。norflash能在芯片內執行,就是指CPU的取指模塊能夠直接從norflash中把指令取出來,供后面的譯碼和執行模塊使用)
--------------------- 本文來自 yjzh_td 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/yjzh_td/article/details/72870044?utm_source=copy
轉:https://blog.csdn.net/thisway_diy/article/details/79397638
Nor Flash的連接線有地址線,數據線,片選信號讀寫信號等,Nor Flash的接口屬於內存類接口,Nor Flash可以向內存一樣讀,但是不能像內存一樣寫,需要做一些特殊的操作才能進行寫操作,讀只需像內存一樣讀很簡單。
Nor Flash原理圖如圖:
Flash介紹
常用的Flash類型有Nor Flash和NAND Flash兩種。
Nor Flash由Intel公司在1988年發明,以替代當時在市場上占據主要地位的EPROM和E2PROM。NAND Flash由Toshiba公司在1989年發明。兩者的主要差別如下表:
- | Nor | NAND |
---|---|---|
XIP(代碼可以直接運行) | Yes | no |
性能(擦除) | 非常慢(5s) | 快(3ms) |
性能(寫) | 慢 | 快 |
性能(讀) | 快 | 快 |
可靠性 | 較高,位反轉的比例小於NAND Flash的10% | 比較低,位反轉比較常見,必須有校驗措施,比如TNR必須有壞塊管理措施 |
可擦除次數 | 10000 ~ 100000 | 100000 ~ 1000000 |
生命周期 | 低於NAND Flash的10% | 是Nor Flash的10倍以上 |
接口 | 與RAM接口相同 | I/O接口 |
易用性 | 容易 | 復雜 |
主要用途 | 常用於保存代碼和關鍵數 | 用於保存數據 |
價格 | 高 | 低 |
Nor Flash支持XIP,即代碼可以直接在Nor Flash上執行,無需復制到內存中。這是由於NorF lash的接口與RAM完全相同,可以隨機訪問任意地址的數據。Nor Flash進行讀操作的效率非常高,但是擦除和寫操作的效率很低,另外,Nor Flash的容量一般比較小。NAND Flash進行擦除和寫操作的效率更高,並且容量更大。一般而言,Nor Flash用於存儲程序,NAND Flash用於存儲數據。基於NAND Flash的設備通常也要搭配Nor Flash以存儲程字。
Flash存儲器件由擦除單元(也稱為塊)組成,當要寫某個塊時,需要確保這個塊己經
被擦除。Nor Flash的塊大小范圍為64kB、128kB:NAND Flash的塊大小范圍為8kB,64kB,擦/寫一個Nor Flash塊需4s,而擦/寫一個NAND Flash塊僅需2ms。Nor Flash的塊太大,不僅增加了擦寫時間,對於給定的寫操作,Nor Flash也需要更多的擦除操作——特別是小文件,比如一個文件只有IkB,但是為了保存它卻需要擦除人小為64kB—128kB的Nor Flash塊。
Nor Flash的接口與RAM完全相同,可以隨意訪問任意地址的數據。而NAND Flash的
接口僅僅包含幾個I/O引腳,需要串行地訪問。NAND Flash一般以512字節為單位進行讀寫。這使得Nor Flash適合於運行程序,而NAND Flash更適合於存儲數據。
容量相同的情況下,NAND Flash的體積更小,對於空間有嚴格要求的系統,NAND Flash可以節省更多空間。市場上Nor Flash的容量通常為IMB~4MB(也有32MB的Nor Flash),NAND Flash的容量為8MB~512MB。容量的差別也使得Nor Flash多用於存儲程序,NAND Flash多用於存儲數據。
對於Flash存儲器件的可靠性需要考慮3點:位反轉、壞塊和可擦除次數。所有Flash器件都遭遇位反轉的問題:由於Flash固有的電器特性,在讀寫數據過程中,偶然會產生一位或幾位數據錯誤(這種概率很低),而NAND Flash出現的概率遠大於Nor Flash,當位反轉發生在關鍵的代碼、數據上時,有可能導致系統崩潰。當僅僅是報告位反轉,重新讀取即可:如果確實發生了位反轉,則必須有相應的錯誤檢測/恢復措施。在NAND Flash上發生位反轉的概率史高,推薦使用EDC/ECC進行錯誤檢測和恢復。NAND Flash上面會有壞塊隨機分布在使用前需要將壞塊掃描出來,確保不再使用它們,否則會使產品含有嚴重的故障。NAND Flash每塊的可擦除次數通常在100000次左右,是Nor Flash的10倍。另外,因為NAND Flash的塊大小通常是NorF lash的1/8,所以NAND Flash的壽命遠遠超過Nor Flash。
嵌入式Linux對Nor、NAND Flash的軟件支持都很成熟。在Nor Flash上常用jffs2文
件系統,而在NAND Flash常用yaffs文件系統。在更底層,有MTD驅動程序實現對它們的讀、寫、擦除操仵,它也實現了EDC/ECC校驗。
Nor Flash的操作
下面我們使用u-boot來體驗Nor Flash的操作(開發板設置Nor啟動,進入u-boot)。
1).使用OpenJTAG燒寫UBOOT到Nor Flash
那么我們怎么用u-boot來操作呢?
Nor Flash手冊里會有一個命令的表格,如圖:
下面簡單的舉一些例子:
復位(reset):往任何一個地址寫入F0。
讀ID(ReadSiliconID):很多的Nor Flash可以配置成位寬16bit(Word),位寬8bit(Byte)。對於我們使用的jz2440開發板使用是位寬16bit,怎樣讀ID呢?
根據前面得圖可知,往Nor Flash的555地址寫AA,再往2AA的地址寫入55,再往555的地址寫入90,然后就可以讀ADI地址,就可以讀到DDI數據了。
實例1
讀數據:
在u-boot上執行:md.b0
結果(和我們燒進去的數據完全一樣):
00000000:170000ea14f09fe514f09fe514f09fe5................ 00000010:14f09fe514f09fe514f09fe514f09fe5................ 00000020:6001f833c001f8332002f8337002f833`..3...3..3...3 00000030:e002f8330004f8332004f833efbeadde...3...3..3....
- 1
- 2
- 3
- 4
可以得出結論:u-boot可以像讀內存一樣來讀nor flash
實例2
讀ID(參考Nor手冊)
- 往地址555H寫入AAH(解鎖)
- 往地址2AAH寫入55H(解鎖)
- 往地址555H寫入90H(命令)
- 讀0地址得到廠家ID(C2H)
- 讀1地址得到設備ID(22DAH或225BH)
- 退出讀ID狀態:給任意地址寫F0H就可以了。
下圖為2440和Nor Flash的簡易連接圖:
2440的A1接到Nor的A0所以2440發出的地址是,Nor Flash收到的地址左移一位。比如:2440發出(555H<<1)地址,Nor Flash才能收到555H這個地址。
下面對在Nor Flash的操作,2440的操作,U-BOOT上的操作進行比較,如下表:
Nor Flash的操作 | 2440的操作 | U-BOOT上的操作 |
---|---|---|
往地址555H寫入AAH(解鎖) | 往地址AAAH寫入AAH(解鎖) | mw.waaaaa |
往地址2AAH寫入55H(解鎖) | 往地址554H寫入55H(解鎖) | mw.w 554 55 |
往地址555H寫入90H(命令) | 往地址AAAH寫入90H(命令) | mw.w aaa 90 |
讀0地址得到廠家ID(C2H) | 讀0地址得到廠家ID(C2H) | md.w 0 1 (1:表示都一次) |
讀1地址得到設備ID(22DAH或225BH) | 讀2地址得到設備ID(22DAH或225BH) | md.w 2 1 (1:表示都一次) |
退出讀ID狀態:給任意地址寫F0H就可以了 | 退出讀ID狀態:給任意地址寫F0H就可以了 | mw.w 0 f0 |
1).當執行過
md.w 0 1
結果(輸出廠家ID):
00000000:00c2..(00c2就是廠家ID)
2).當執行過
md.w 2 1
結果(輸出設備ID):
00000002:2249I”(2249就是設備ID)
3).當執行
mw.w 0 f0
就退出讀ID的狀態,
執行:
md.b0
結果:
00000000:17.(讀到的就是Nor Flash地址·0的數據)
Nor Flash的兩種規范
通常內核里面要識別一個 Nor Flash 有兩種方法:
一種是 jedec 探測,就是在內核里面事先定義一個數組,該數組里面放有不同廠家各個芯片的一些參數,探測的時候將 flash 的 ID 和數組里面的 ID 一一比較,如果發現相同的,就使用該數組的參數。
jedec 探測的優點就是簡單,缺點是如果內核要支持的 flash 種類很多,這個數組就會很龐大。內核里面用 jedec 探測一個芯片時,是先通過發命令來獲取 flash 的 ID,然后和數組比較,但是 flash.c 中連 ID 都是自己通過宏配置的。
一種是 CFI(common flash interface)探測,就是直接發各種命令來讀取芯片的信息,比如 ID、容量等,芯片本身就包含了電壓有多大,容量有有多少等信息。
下面對在Nor Flash上操作,2440上操作,U-BOOT上操作cfi 探測(讀取芯片信息)進行比較參考芯片手冊。
Nor Flash上操作cfi | 2440上操作cfi | U-BOOT上操作cfi |
---|---|---|
往55H地址寫入98H | 往AAH地址寫入98H | mw.w aa 98 |
讀地址10H得到0051 | 讀地址20H得到0051 | md.w 20 1 |
讀地址11H得到0052 | 讀地址22H得到0052 | md.w 22 1 |
讀地址12H得到0059 | 讀地址24H得到0059 | md.w 24 1 |
讀地址27H得到容量 | 讀地址4EH得到容量 | md.w 4e 1 |
Nor Flash寫數據
我們在Nor Flash的10000的地址讀數據,
md.w 100000 1
結果:
00100000:ffff..
在Nor flash的10000的地址寫數據下0x1234,
mw.w 100000 1234
然后在這個地址讀數據,
md.w 100000 1
結果:
00100000:ffff(這個地址上的數據沒有被修改,寫操作無效)。
怎樣把數據寫進Nor Flash進去呢?
寫數據之前必須保證,要寫的地址是擦除的。
下面是Nor Flash的寫操作,如下表:
Nor Flash上操作寫操作 | 2440上操作寫操作 | U-BOOT上操作寫操作 |
---|---|---|
往地址555H寫AAH(解鎖) | 往地址AAAH寫AAH(解鎖) | mw.w aaa aa |
往地址2AAH寫55H(解鎖) | 往地址554H寫55H(解鎖) | mw.w 554 55 |
往地址555H寫A0H | 往地址AAAH寫A0H | mw.w aaa a0 |
往地址PA寫PD | 往地址0x100000寫1234h | mw.w 100000 1234 |
1).U-BOOT執行完上述指令后,0x1234,就被寫到0x100000地址處,
執行:
md.w1000001
結果(1234被寫進去):
00100000:1234 4
從這里可以看出來U-BOOT的操作不是很復雜。
2).我們再次往0x100000地址處,寫入0x5678,執行如下命令:
mw.w aaa aa
mw.w 554 55
mw.w aaa a0
mw.w 100000 5678
查看0x100000地址處的數據
md.w 100000 1
結果:
00100000:12300.
0x100000地址處的數據不是0x5678,寫操作失敗,失敗的原因是,原來的數據已經是0x1234不是全0xffff,再次寫操作失敗,(Nor Flash只有先擦出,才能燒寫)。
先擦除(參考Nor Flash芯片手冊)
Nor Flash操作 u-boot操作
555H AAH mw.w aaa aa
2AAH 55H mw.w 554 55
555H 80H mw.w aaa 80
555H AAH mw.w aaa aa
2AAH 55H mw.w 554 55
SA 30H //往扇區地址寫入30 mw.w 100000 30
執行完上述指令后測試
執行:
md.w 100000 1
結果:
00100000:ffff..
已被擦除,這個時候再次燒寫就不會有問題了。
再燒寫
mw.w aaa aa
mw.w 554 55
mw.w aaa a0
mw.w 100000 5678
測試燒寫結果
執行:
md.w 100000 1
結果:
00100000:5678 xV
數據被燒寫進去,燒寫成功。
總結:我們燒寫時,如果上面的數據,不是0ffff,沒有被擦除過,我們就要先擦出,擦除完后,才可以燒寫,擦除燒寫的命令可以從芯片手冊里面獲得。
= 第002節Nor Flash編程識別 =
本節實例的目的目的:識別nor flash
發送命令函數
nor_cmd函數代碼如下,往NOR Flash某個地址發送指令,
16 17 /* offset是基於NOR的角度看到 */ 18 void nor_cmd(unsigned int offset, unsigned int cmd) 19 { 20 nor_write_word(NOR_FLASH_BASE, offset, cmd); 21 }
- 1
- 2
- 3
- 4
- 5
- 6
讀取函數
nor_read_word函數是從NOR Flash 讀取兩個字節(本開發板位寬16bit),讀取數據的地址,是基於2440,所以讀取NOR Flash某個地址上的數據時,需要把NOR Flash對應的地址左移一位(地址乘以2)。
23 unsigned int nor_read_word(unsigned int base, unsigned int offset) 24 { 25 volatile unsigned short *p = (volatile unsigned short *)(base + (offset << 1)); 26 return *p; 27 }
- 1
- 2
- 3
- 4
- 5
讀取地址中的數據
向nor_dat函數中寫入NOR Flash某個地址,返回該NOR Flash地址上的數據。
29 unsigned int nor_dat(unsigned int offset) 30 { 31 return nor_read_word(NOR_FLASH_BASE, offset); 32 }
- 1
- 2
- 3
- 4
進入NOR FLASH的CFI模式,讀取各類信息
do_scan_nor_flash函數代碼如下,該函數的功能:進入CFI模式讀取NOR Flash中的廠家ID,設備ID,容量等信息。
50/* 進入NOR FLASH的CFI模式 51 * 讀取各類信息 52 */ 53 void do_scan_nor_flash(void) 54 { 55 char str[4]; 56 unsigned int size; 57 int regions, i; 58 int region_info_base; 59 int block_addr, blocks, block_size, j; 60 int cnt; 61 62 int vendor, device; 63 64 /* 打印廠家ID、設備ID */ 65 nor_cmd(0x555, 0xaa); /* 解鎖 */ 66 nor_cmd(0x2aa, 0x55); 67 nor_cmd(0x555, 0x90); /* read id */ 68 vendor = nor_dat(0); 69 device = nor_dat(1); 70 nor_cmd(0, 0xf0); /* reset */ 71 72 nor_cmd(0x55, 0x98); /* 進入cfi模式 */ 073 74 str[0] = nor_dat(0x10); 75 str[1] = nor_dat(0x11); 76 str[2] = nor_dat(0x12); 77 str[3] = '\0'; 78 printf("str = %s", str); 79 80 /* 打印容量 */ 81 size = 1<<(nor_dat(0x27)); 82 printf("v=0x%x,d=0x%x,s=0x%x,%dM",vendor,device,size,size/(1024*1024)); 83 84 /* 打印各個扇區的起始地址 */ 85 /* 名詞解釋: 86 * erase block region : 里面含有1個或多個block, 它們的大小一樣 87 * 一個nor flash含有1個或多個region 88 * 一個region含有1個或多個block(扇區) 89 90 * Erase block region information: 91 * 前2字節+1 : 表示該region有多少個block 92 * 后2字節*256 : 表示block的大小 93 */ 94 95 regions = nor_dat(0x2c); 96 region_info_base = 0x2d; 97 block_addr = 0; 98 printf("Block/Sector start Address:"); 99 cnt = 0; 100 for (i = 0; i < regions; i++) 101 { 102 blocks = 1 + nor_dat(region_info_base) + (nor_dat(region_info_base+1)<<8); 103 block_size=256*(nor_dat(region_info_base+2)+(nor_dat(region_info_base+3)<<8)); 104 region_info_base += 4; 105 106 //printf("…………"); 107 108 for (j = 0; j < blocks; j++) 109 { 110 /* 打印每個block的起始地址 */ 111 //printf("0x%08x ", block_addr); 112 printHex(block_addr); 113 putchar(' '); 114 cnt++; 115 block_addr += block_size; 116 if (cnt % 5 == 0) 117 printf("\n\r"); 118 } 119 } 120 printf("\n\r"); 121 /* 退出CFI模式 */ 122 nor_cmd(0, 0xf0); 123 }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
第65,66行 這兩步是解鎖,解鎖之后就進入讀ID狀態,就可以讀取廠家和設備ID了。
第68行 是把讀取到的廠家ID的值,復制給vendor變量。
第69行 是把讀取到的設備ID的值,復制給device變量。
第70行 退出讀ID狀態: 給任意地址寫F0H。
第72行,往地址0x55地址寫入數據0x98,是進入cfi模式。
第74,75,76行是讀取NOR Flash地址0x10,0x11,x012中的字符,賦值給字符串str。
第81行,根據芯片手冊可知道,讀取NOR Flash地址0x27處的數據,得到的是NOR Flash容量大小2的冪數,所以把1左移讀取到的數據,就可得到NOR Flash的容量。
第95行讀取NOR Flash地址0x2c地址中的數據,可以得到NOR Flash中有多少region。
第102行根據Erase block region information:的信息可以知道讀取[2E,2D]這兩個字節的地址+1,可以得到一個region有多少block(參考芯片手冊)。代碼中的region_info_base變量的值是0x2d,0x2d是前兩個字節中的低字節,0x2e是前兩個字節中的高字節,所以需要左移8位,然后加上1就得到了一個region有多少block.。
第103行參考芯片手冊,讀取[30,2F]這兩個字節地址,然后乘上256就可以得到一個塊的大小。
第104行,地址加4,讀取下一個region有多少block和每個block的大小。
第112,115行,由於NOR Flash的基地址是0,所以第一個block的首地址是0,下一個block的首地址,就是上一個block的首地址加上block的大小。
第112行往0地址寫入0xf0,退出CFI模式。
Nor Flash的測試
nor_flash_test函數通過switch語句,分別處理識別NOR Flash,擦除NOR Flash某個扇區,編寫某個地址,讀某個地址。代碼如下:
232 void nor_flash_test(void) 233 { 234 char c; 235 236 while (1) 237 { 238 /* 打印菜單, 供我們選擇測試內容 */ 239 printf("[s] Scan nor flash\n\r"); 240 printf("[e] Erase nor flash\n\r"); 241 printf("[w] Write nor flash\n\r"); 242 printf("[r] Read nor flash\n\r"); 243 printf("[q] quit\n\r"); 244 printf("Enter selection: "); 245 246 c = getchar(); 247 printf("%c", c); 248 249 /* 測試內容: 250 * 1. 識別nor flash 251 * 2. 擦除nor flash某個扇區 252 * 3. 編寫某個地址 253 * 4. 讀某個地址 254 */ 255 switch (c) 256 { 257 case 'q': 258 case 'Q': 259 return; 260 break; 261 262 case 's': 263 case 'S': 264 do_scan_nor_flash(); 265 break; 266 267 case 'e': 268 case 'E': 269 do_erase_nor_flash(); 270 break; 271 272 case 'w': 273 case 'W': 274 do_write_nor_flash(); 275 break; 276 277 case 'r': 278 case 'R': 279 do_read_nor_flash(); 280 break; 281 default: 282 break; 283 } 284 } 285 }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
主函數
main函數代碼如下所示。把timer中斷去掉,否則: 測試NOR Flash時進入CFI等模式時, 如果發生了中斷,cpu必定讀NOR Flash,那么讀不到正確的指令,導致程序崩潰。
12 int main(void) 13 { 14 led_init(); 15 //interrupt_init(); /* 初始化中斷控制器 */ 16 key_eint_init(); /* 初始化按鍵, 設為中斷源 */ 17 //timer_init(); 18 19 puts("\n\rg_A = "); 20 printHex(g_A); 21 puts("\n\r"); 22 23 nor_flash_test(); 24 25 return 0; 26 }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
第003節Nor Flash編程擦寫讀
本實例的目的目的:擦除nor flash某個扇區,編寫某個地址,讀某個地址。
等待燒寫
等待燒寫完成 : 讀數據, Q6無變化時表示結束 (參考芯片手冊),
35 void wait_ready(unsigned int addr) 36 { 37 unsigned int val; 38 unsigned int pre; 39 40 pre = nor_dat(addr>>1); 41 val = nor_dat(addr>>1); 42 while ((val & (1<<6)) != (pre & (1<<6))) 43 { 44 pre = val; 45 val = nor_dat(addr>>1); 46 } 47}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
擦除NOR Flash 某個扇區
do_erase_nor_flash函數的代碼如下。參考芯片手冊,就可以知道擦除某個扇區,還是相對比較簡單的。
125 void do_erase_nor_flash(void) 126 { 127 unsigned int addr; 128 129 /* 獲得地址 */ 130 printf("Enter the address of sector to erase: "); 131 addr = get_uint(); 132 133 printf("erasing ..."); 134 nor_cmd(0x555, 0xaa); /* 解鎖 */ 135 nor_cmd(0x2aa, 0x55); 136 nor_cmd(0x555, 0x80); /* erase sector */ 137 138 nor_cmd(0x555, 0xaa); /* 解鎖 */ 139 nor_cmd(0x2aa, 0x55); 140 nor_cmd(addr>>1, 0x30); /* 發出扇區地址 */ 141 wait_ready(addr); 142 }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
第131行,get_uint函數用於獲取輸入的地址。
第134,135這兩行是解鎖。
第136行是erase sector。
第138,139行是再次解鎖。
第140行是對發出的扇區地址。
第 141行等待擦除完成。
寫NOR Flash
do_write_nor_flash的代碼如下所示,開發板上的NOR Flash的位寬是16bit,所以可以把要寫的數據構造出16bit然后在寫進NOR Flash中。
144 void do_write_nor_flash(void) 145 { 146 unsigned int addr; 147 unsigned char str[100]; 148 int i, j; 149 unsigned int val; 150 151 /* 獲得地址 */ 152 printf("Enter the address of sector to write: "); 153 addr = get_uint(); 154 155 printf("Enter the string to write: "); 156 gets(str); 157 158 printf("writing ...\n\r"); 159 160 /* str[0],str[1]==>16bit 161 * str[2],str[3]==>16bit 162 */ 163 i = 0; 164 j = 1; 165 while (str[i] && str[j]) 166 { 167 val = str[i] + (str[j]<<8); 168 169 /* 燒寫 */ 170 nor_cmd(0x555, 0xaa); /* 解鎖 */ 171 nor_cmd(0x2aa, 0x55); 172 nor_cmd(0x555, 0xa0); /* program */ 173 nor_cmd(addr>>1, val); 174 /* 等待燒寫完成 : 讀數據, Q6無變化時表示結束 */ 175 wait_ready(addr); 176 177 i += 2; 178 j += 2; 179 addr += 2; 180 } 181 182 val = str[i]; 183 /* 燒寫 */ 184 nor_cmd(0x555, 0xaa); /* 解鎖 */ 185 nor_cmd(0x2aa, 0x55); 186 nor_cmd(0x555, 0xa0); /* program */ 187 nor_cmd(addr>>1, val); 188 /* 等待燒寫完成 : 讀數據, Q6無變化時表示結束 */ 189 wait_ready(addr); 190 }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
第153行把通過get_uint獲得的地址賦值給addr變量,
第156行通過gets函數獲得輸入的字符串。
第168行兩個8位的數據,組合成一個16位的數據賦值給變量val。
讀NOR Flash
do_read_nor_flash函數代碼如下,由於NOR Flash是內存類接口,可以像內存一樣讀取。
191 void do_read_nor_flash(void) 192 { 193 unsigned int addr; 194 volatile unsigned char *p; 195 int i, j; 196 unsigned char c; 197 unsigned char str[16]; 198 199 /* 獲得地址 */ 200 printf("Enter the address to read: "); 201 addr = get_uint(); 202 203 p = (volatile unsigned char *)addr; 204 205 printf("Data : \n\r"); 206 /* 長度固定為64 */ 207 for (i = 0; i < 4; i++) 208 { 209 /* 每行打印16個數據 */ 210 for (j = 0; j < 16; j++) 211 { 212 /* 先打印數值 */ 213 c = *p++; 214 str[j] = c; 215 printf("%02x ", c); 216 } 217 218 printf(" ; "); 219 220 for (j = 0; j < 16; j++) 221 { 222 /* 后打印字符 */ 223 if (str[j] < 0x20 || str[j] > 0x7e) /* 不可視字符 */ 224 putchar('.'); 225 else 226 putchar(str[j]); 227 } 228 printf("\n\r"); 229 }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
第201行中的get_uint函數,從串口中獲得輸入的地址。
第203行,強制類型轉化。
第207行~216行是對NOR Flash內容的讀取,輸出的內容為16進制的數據,由於NOR Flash是內存類接口,可以像內存一樣讀取。
第220行~227輸出NOR Flash的內容為字符型數據,其中的第223行用來判斷,輸出的字符是否為不可視字符,要是為不可視字符輸出點’.’,要是可視字符輸出字符。
--------------------- 本文來自 韋東山 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/thisway_diy/article/details/79397638?utm_source=copy