nor flash的一般操作與分析


是現在市場上兩種主要的非易失閃存技術。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 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM