日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

nor flash的一般操作与分析

發(fā)布時間:2024/8/24 编程问答 40 如意码农
生活随笔 收集整理的這篇文章主要介紹了 nor flash的一般操作与分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

是現(xiàn)在市場上兩種主要的非易失閃存技術(shù)。Intel于1988年首先開發(fā)出NOR Flash 技術(shù),徹底改變了原先由EPROM(Electrically Programmable Read-Only-Memory電可編程序只讀存儲器)和EEPROM(電可擦只讀存儲器Electrically Erasable Programmable Read - Only Memory)一統(tǒng)天下的局面。緊接著,1989年,東芝公司發(fā)表了NAND Flash 結(jié)構(gòu),強調(diào)降低每比特的成本,有更高的性能,并且像磁盤一樣可以通過接口輕松升級。NOR Flash 的特點是芯片內(nèi)執(zhí)行(XIP ,eXecute In Place),這樣應用程序可以直接在Flash閃存內(nèi)運行,不必再把代碼讀到系統(tǒng)RAM。

這樣我們知道程序能直接在norlash執(zhí)行的原因在XIP

那:什么是XIP?工作原理又是怎么樣的?

XIP eXecute In Place

  eXecute In Place,即芯片內(nèi)執(zhí)行,指應用程序可以直接在flash閃存內(nèi)運行,不必再把代碼讀到系統(tǒng)RAM中。flash內(nèi)執(zhí)行是指nor flash 不需要初始化,可以直接在flash內(nèi)執(zhí)行代碼。但往往只執(zhí)行部分代碼,比如初始化RAM.

(注:片內(nèi)執(zhí)行不是說程序在存儲器內(nèi)執(zhí)行哦,CPU的基本功能就是取指、譯碼和執(zhí)行。norflash能在芯片內(nèi)執(zhí)行,就是指CPU的取指模塊能夠直接從norflash中把指令取出來,供后面的譯碼和執(zhí)行模塊使用

--------------------- 本文來自 yjzh_td 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/yjzh_td/article/details/72870044?utm_source=copy

轉(zhuǎn):https://blog.csdn.net/thisway_diy/article/details/79397638

Nor Flash的連接線有地址線,數(shù)據(jù)線,片選信號讀寫信號等,Nor Flash的接口屬于內(nèi)存類接口,Nor Flash可以向內(nèi)存一樣讀,但是不能像內(nèi)存一樣寫,需要做一些特殊的操作才能進行寫操作,讀只需像內(nèi)存一樣讀很簡單。

Nor Flash原理圖如圖:

Flash介紹

常用的Flash類型有Nor Flash和NAND Flash兩種。

Nor Flash由Intel公司在1988年發(fā)明,以替代當時在市場上占據(jù)主要地位的EPROM和E2PROM。NAND Flash由Toshiba公司在1989年發(fā)明。兩者的主要差別如下表:

- Nor NAND
XIP(代碼可以直接運行) Yes no
性能(擦除) 非常慢(5s) 快(3ms)
性能(寫)
性能(讀)
可靠性 較高,位反轉(zhuǎn)的比例小于NAND Flash的10% 比較低,位反轉(zhuǎn)比較常見,必須有校驗措施,比如TNR必須有壞塊管理措施
可擦除次數(shù) 10000 ~ 100000 100000 ~ 1000000
生命周期 低于NAND Flash的10% 是Nor Flash的10倍以上
接口 與RAM接口相同 I/O接口
易用性 容易 復雜
主要用途 常用于保存代碼和關(guān)鍵數(shù) 用于保存數(shù)據(jù)
價格

Nor Flash支持XIP,即代碼可以直接在Nor Flash上執(zhí)行,無需復制到內(nèi)存中。這是由于NorF lash的接口與RAM完全相同,可以隨機訪問任意地址的數(shù)據(jù)。Nor Flash進行讀操作的效率非常高,但是擦除和寫操作的效率很低,另外,Nor Flash的容量一般比較小。NAND Flash進行擦除和寫操作的效率更高,并且容量更大。一般而言,Nor Flash用于存儲程序,NAND Flash用于存儲數(shù)據(jù)。基于NAND Flash的設(shè)備通常也要搭配Nor Flash以存儲程字。

Flash存儲器件由擦除單元(也稱為塊)組成,當要寫某個塊時,需要確保這個塊己經(jīng)
被擦除。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完全相同,可以隨意訪問任意地址的數(shù)據(jù)。而NAND Flash的
接口僅僅包含幾個I/O引腳,需要串行地訪問。NAND Flash一般以512字節(jié)為單位進行讀寫。這使得Nor Flash適合于運行程序,而NAND Flash更適合于存儲數(shù)據(jù)。

容量相同的情況下,NAND Flash的體積更小,對于空間有嚴格要求的系統(tǒng),NAND Flash可以節(jié)省更多空間。市場上Nor Flash的容量通常為IMB~4MB(也有32MB的Nor Flash),NAND Flash的容量為8MB~512MB。容量的差別也使得Nor Flash多用于存儲程序,NAND Flash多用于存儲數(shù)據(jù)。

對于Flash存儲器件的可靠性需要考慮3點:位反轉(zhuǎn)、壞塊和可擦除次數(shù)。所有Flash器件都遭遇位反轉(zhuǎn)的問題:由于Flash固有的電器特性,在讀寫數(shù)據(jù)過程中,偶然會產(chǎn)生一位或幾位數(shù)據(jù)錯誤(這種概率很低),而NAND Flash出現(xiàn)的概率遠大于Nor Flash,當位反轉(zhuǎn)發(fā)生在關(guān)鍵的代碼、數(shù)據(jù)上時,有可能導致系統(tǒng)崩潰。當僅僅是報告位反轉(zhuǎn),重新讀取即可:如果確實發(fā)生了位反轉(zhuǎn),則必須有相應的錯誤檢測/恢復措施。在NAND Flash上發(fā)生位反轉(zhuǎn)的概率史高,推薦使用EDC/ECC進行錯誤檢測和恢復。NAND Flash上面會有壞塊隨機分布在使用前需要將壞塊掃描出來,確保不再使用它們,否則會使產(chǎn)品含有嚴重的故障。NAND Flash每塊的可擦除次數(shù)通常在100000次左右,是Nor Flash的10倍。另外,因為NAND Flash的塊大小通常是NorF lash的1/8,所以NAND Flash的壽命遠遠超過Nor Flash。

嵌入式Linux對Nor、NAND Flash的軟件支持都很成熟。在Nor Flash上常用jffs2文
件系統(tǒng),而在NAND Flash常用yaffs文件系統(tǒng)。在更底層,有MTD驅(qū)動程序?qū)崿F(xiàn)對它們的讀、寫、擦除操仵,它也實現(xiàn)了EDC/ECC校驗。

Nor Flash的操作

下面我們使用u-boot來體驗Nor Flash的操作(開發(fā)板設(shè)置Nor啟動,進入u-boot)。

1).使用OpenJTAG燒寫UBOOT到Nor Flash

那么我們怎么用u-boot來操作呢?

Nor Flash手冊里會有一個命令的表格,如圖:

下面簡單的舉一些例子:

復位(reset):往任何一個地址寫入F0。

讀ID(ReadSiliconID):很多的Nor Flash可以配置成位寬16bit(Word),位寬8bit(Byte)。對于我們使用的jz2440開發(fā)板使用是位寬16bit,怎樣讀ID呢?

根據(jù)前面得圖可知,往Nor Flash的555地址寫AA,再往2AA的地址寫入55,再往555的地址寫入90,然后就可以讀ADI地址,就可以讀到DDI數(shù)據(jù)了。

實例1

讀數(shù)據(jù):

在u-boot上執(zhí)行:md.b0

結(jié)果(和我們燒進去的數(shù)據(jù)完全一樣):

00000000:170000ea14f09fe514f09fe514f09fe5................
00000010:14f09fe514f09fe514f09fe514f09fe5................
00000020:6001f833c001f8332002f8337002f833`..3...3..3...3
00000030:e002f8330004f8332004f833efbeadde...3...3..3....
  • 1
  • 2
  • 3
  • 4

可以得出結(jié)論:u-boot可以像讀內(nèi)存一樣來讀nor flash

實例2

讀ID(參考Nor手冊)

  • 往地址555H寫入AAH(解鎖)
  • 往地址2AAH寫入55H(解鎖)
  • 往地址555H寫入90H(命令)
  • 讀0地址得到廠家ID(C2H)
  • 讀1地址得到設(shè)備ID(22DAH或225BH)
  • 退出讀ID狀態(tài):給任意地址寫F0H就可以了。

下圖為2440和Nor Flash的簡易連接圖:

2440的A1接到Nor的A0所以2440發(fā)出的地址是,Nor Flash收到的地址左移一位。比如:2440發(fā)出(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地址得到設(shè)備ID(22DAH或225BH) 讀2地址得到設(shè)備ID(22DAH或225BH) md.w 2 1 (1:表示都一次)
退出讀ID狀態(tài):給任意地址寫F0H就可以了 退出讀ID狀態(tài):給任意地址寫F0H就可以了 mw.w 0 f0

1).當執(zhí)行過
md.w 0 1
結(jié)果(輸出廠家ID):
00000000:00c2..(00c2就是廠家ID)

2).當執(zhí)行過
md.w 2 1

結(jié)果(輸出設(shè)備ID):
00000002:2249I”(2249就是設(shè)備ID)

3).當執(zhí)行
mw.w 0 f0
就退出讀ID的狀態(tài),

執(zhí)行:
md.b0
結(jié)果:
00000000:17.(讀到的就是Nor Flash地址·0的數(shù)據(jù))

Nor Flash的兩種規(guī)范

通常內(nèi)核里面要識別一個 Nor Flash 有兩種方法:

一種是 jedec 探測,就是在內(nèi)核里面事先定義一個數(shù)組,該數(shù)組里面放有不同廠家各個芯片的一些參數(shù),探測的時候?qū)?flash 的 ID 和數(shù)組里面的 ID 一一比較,如果發(fā)現(xiàn)相同的,就使用該數(shù)組的參數(shù)。
jedec 探測的優(yōu)點就是簡單,缺點是如果內(nèi)核要支持的 flash 種類很多,這個數(shù)組就會很龐大。內(nèi)核里面用 jedec 探測一個芯片時,是先通過發(fā)命令來獲取 flash 的 ID,然后和數(shù)組比較,但是 flash.c 中連 ID 都是自己通過宏配置的。

一種是 CFI(common flash interface)探測,就是直接發(fā)各種命令來讀取芯片的信息,比如 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寫數(shù)據(jù)

我們在Nor Flash的10000的地址讀數(shù)據(jù),
md.w 100000 1
結(jié)果:
00100000:ffff..
在Nor flash的10000的地址寫數(shù)據(jù)下0x1234,
mw.w 100000 1234
然后在這個地址讀數(shù)據(jù),
md.w 100000 1
結(jié)果:
00100000:ffff(這個地址上的數(shù)據(jù)沒有被修改,寫操作無效)。

怎樣把數(shù)據(jù)寫進Nor Flash進去呢?

寫數(shù)據(jù)之前必須保證,要寫的地址是擦除的。

下面是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執(zhí)行完上述指令后,0x1234,就被寫到0x100000地址處,

執(zhí)行:
md.w1000001
結(jié)果(1234被寫進去):
00100000:1234 4
從這里可以看出來U-BOOT的操作不是很復雜。

2).我們再次往0x100000地址處,寫入0x5678,執(zhí)行如下命令:
mw.w aaa aa
mw.w 554 55
mw.w aaa a0
mw.w 100000 5678
查看0x100000地址處的數(shù)據(jù)
md.w 100000 1
結(jié)果:
00100000:12300.
0x100000地址處的數(shù)據(jù)不是0x5678,寫操作失敗,失敗的原因是,原來的數(shù)據(jù)已經(jīng)是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 //往扇區(qū)地址寫入30 mw.w 100000 30

執(zhí)行完上述指令后測試

執(zhí)行:
md.w 100000 1
結(jié)果:
00100000:ffff..
已被擦除,這個時候再次燒寫就不會有問題了。

再燒寫
mw.w aaa aa
mw.w 554 55
mw.w aaa a0
mw.w 100000 5678

測試燒寫結(jié)果
執(zhí)行:
md.w 100000 1
結(jié)果:
00100000:5678 xV
數(shù)據(jù)被燒寫進去,燒寫成功。

總結(jié):我們燒寫時,如果上面的數(shù)據(jù),不是0ffff,沒有被擦除過,我們就要先擦出,擦除完后,才可以燒寫,擦除燒寫的命令可以從芯片手冊里面獲得。

= 第002節(jié)Nor Flash編程識別 =
本節(jié)實例的目的目的:識別nor flash
發(fā)送命令函數(shù)
nor_cmd函數(shù)代碼如下,往NOR Flash某個地址發(fā)送指令,

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

讀取函數(shù)

nor_read_word函數(shù)是從NOR Flash 讀取兩個字節(jié)(本開發(fā)板位寬16bit),讀取數(shù)據(jù)的地址,是基于2440,所以讀取NOR Flash某個地址上的數(shù)據(jù)時,需要把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

讀取地址中的數(shù)據(jù)

向nor_dat函數(shù)中寫入NOR Flash某個地址,返回該NOR Flash地址上的數(shù)據(jù)。

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函數(shù)代碼如下,該函數(shù)的功能:進入CFI模式讀取NOR Flash中的廠家ID,設(shè)備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、設(shè)備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 /* 打印各個扇區(qū)的起始地址 */
85 /* 名詞解釋:
86 * erase block region : 里面含有1個或多個block, 它們的大小一樣
87 * 一個nor flash含有1個或多個region
88 * 一個region含有1個或多個block(扇區(qū))
89
90 * Erase block region information:
91 * 前2字節(jié)+1 : 表示該region有多少個block
92 * 后2字節(jié)*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狀態(tài),就可以讀取廠家和設(shè)備ID了。

第68行 是把讀取到的廠家ID的值,復制給vendor變量。

第69行 是把讀取到的設(shè)備ID的值,復制給device變量。

第70行 退出讀ID狀態(tài): 給任意地址寫F0H。

第72行,往地址0x55地址寫入數(shù)據(jù)0x98,是進入cfi模式。

第74,75,76行是讀取NOR Flash地址0x10,0x11,x012中的字符,賦值給字符串str。

第81行,根據(jù)芯片手冊可知道,讀取NOR Flash地址0x27處的數(shù)據(jù),得到的是NOR Flash容量大小2的冪數(shù),所以把1左移讀取到的數(shù)據(jù),就可得到NOR Flash的容量。

第95行讀取NOR Flash地址0x2c地址中的數(shù)據(jù),可以得到NOR Flash中有多少region。

第102行根據(jù)Erase block region information:的信息可以知道讀取[2E,2D]這兩個字節(jié)的地址+1,可以得到一個region有多少block(參考芯片手冊)。代碼中的region_info_base變量的值是0x2d,0x2d是前兩個字節(jié)中的低字節(jié),0x2e是前兩個字節(jié)中的高字節(jié),所以需要左移8位,然后加上1就得到了一個region有多少block.。

第103行參考芯片手冊,讀取[30,2F]這兩個字節(jié)地址,然后乘上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函數(shù)通過switch語句,分別處理識別NOR Flash,擦除NOR Flash某個扇區(qū),編寫某個地址,讀某個地址。代碼如下:

232 void nor_flash_test(void)
233 {
234 char c;
235
236 while (1)
237 {
238 /* 打印菜單, 供我們選擇測試內(nèi)容 */
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 /* 測試內(nèi)容:
250 * 1. 識別nor flash
251 * 2. 擦除nor flash某個扇區(qū)
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

主函數(shù)

main函數(shù)代碼如下所示。把timer中斷去掉,否則: 測試NOR Flash時進入CFI等模式時, 如果發(fā)生了中斷,cpu必定讀NOR Flash,那么讀不到正確的指令,導致程序崩潰。

12  int main(void)
13 {
14 led_init();
15 //interrupt_init(); /* 初始化中斷控制器 */
16 key_eint_init(); /* 初始化按鍵, 設(shè)為中斷源 */
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節(jié)Nor Flash編程擦寫讀

本實例的目的目的:擦除nor flash某個扇區(qū),編寫某個地址,讀某個地址。

等待燒寫

等待燒寫完成 : 讀數(shù)據(jù), Q6無變化時表示結(jié)束 (參考芯片手冊),

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 某個扇區(qū)

do_erase_nor_flash函數(shù)的代碼如下。參考芯片手冊,就可以知道擦除某個扇區(qū),還是相對比較簡單的。

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); /* 發(fā)出扇區(qū)地址 */
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函數(shù)用于獲取輸入的地址。

第134,135這兩行是解鎖。

第136行是erase sector。

第138,139行是再次解鎖。

第140行是對發(fā)出的扇區(qū)地址。

第 141行等待擦除完成。

寫NOR Flash

do_write_nor_flash的代碼如下所示,開發(fā)板上的NOR Flash的位寬是16bit,所以可以把要寫的數(shù)據(jù)構(gòu)造出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 /* 等待燒寫完成 : 讀數(shù)據(jù), Q6無變化時表示結(jié)束 */
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 /* 等待燒寫完成 : 讀數(shù)據(jù), Q6無變化時表示結(jié)束 */
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函數(shù)獲得輸入的字符串。

第168行兩個8位的數(shù)據(jù),組合成一個16位的數(shù)據(jù)賦值給變量val。

讀NOR Flash

do_read_nor_flash函數(shù)代碼如下,由于NOR Flash是內(nèi)存類接口,可以像內(nèi)存一樣讀取。

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個數(shù)據(jù) */
210 for (j = 0; j < 16; j++)
211 {
212 /* 先打印數(shù)值 */
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函數(shù),從串口中獲得輸入的地址。
第203行,強制類型轉(zhuǎn)化。
第207行~216行是對NOR Flash內(nèi)容的讀取,輸出的內(nèi)容為16進制的數(shù)據(jù),由于NOR Flash是內(nèi)存類接口,可以像內(nèi)存一樣讀取。
第220行~227輸出NOR Flash的內(nèi)容為字符型數(shù)據(jù),其中的第223行用來判斷,輸出的字符是否為不可視字符,要是為不可視字符輸出點’.’,要是可視字符輸出字符。

---------------------

本文來自 韋東山 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/thisway_diy/article/details/79397638?utm_source=copy

總結(jié)

以上是生活随笔為你收集整理的nor flash的一般操作与分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。