flash_at45db321.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  1. /******************************************************************************
  2. 版权所有:
  3. 文件名称: flash_at45db321.c
  4. 文件版本: 01.01
  5. 创建作者: sunxi
  6. 创建日期: 2008-08-19
  7. 功能说明: at45db321驱动程序。
  8. 其它说明: 目前通过页擦除整个FLASH需要64.8秒,读整个FLASH需要6.3秒,写整个FLASH
  9. 需要121秒(首版测试结果)。
  10. 修改记录:
  11. 2010-07-16 sunxi _at45db321_page_write函数以前是由OP_PROGRAM_VIA_BUF1命令
  12. 完成,现改为由OP_WRITE_BUFFER1和OP_MWRITE_BUFFER1命令组合
  13. 完成。这样做的原因OP_PROGRAM_VIA_BUF1实际由BUF写、页擦除、
  14. 页编程三个命令组合而成,由于有页擦除命令的存在,导致页写的
  15. 时间速度比较慢,要15ms左右,改进后只需3.5ms左右。使用本修改
  16. 后的程序必须确保写之前已经对相应的页进行了擦除。
  17. 新版本代码的测试结果如下:
  18. flash_test begin!
  19. block_size=512,blocks=8192.
  20. at45db321d_Identify ok!(us=9)!
  21. at45db321_sector_protection:ret=0!
  22. at45DB321Erase (us=77945334,ret=0)!
  23. at45DB321Erase verify ok(us=6230836)!
  24. at45DB321Write ok(us=28132804)!
  25. at45DB321Write verify ok(us=6217728)!
  26. at45DB321Erase (us=69492882,ret=0)!
  27. at45DB321Erase verify ok(us=6243943)!
  28. at45DB321Write ok(us=28350756)!
  29. at45DB321Write verify ok(us=6322586)!
  30. flash_test end!
  31. */
  32. /*------------------------------- 头文件 --------------------------------------
  33. */
  34. #include <string.h>
  35. #include "bspconfig.h"
  36. #include "ustimer.h"
  37. #include "dspi.h"
  38. #include "flash.h"
  39. #include "gpio.h"
  40. #include "rt.h"
  41. /*------------------------------- 宏定义 --------------------------------------
  42. */
  43. #define _DEBUG_FLASH
  44. #if CFG_BSP_DEBUG
  45. #define _DEBUG_FLASH
  46. #endif
  47. //操作命令宏定义
  48. #define OP_READ_CONTINUOUS 0xE8
  49. #define OP_READ_PAGE 0xD2
  50. #define OP_READ_STATUS 0xD7
  51. #define OP_READ_BUFFER1 0xD4
  52. #define OP_READ_BUFFER2 0xD6
  53. #define OP_WRITE_BUFFER1 0x84
  54. #define OP_WRITE_BUFFER2 0x87
  55. /* erasing flash */
  56. #define OP_ERASE_PAGE 0x81
  57. #define OP_ERASE_BLOCK 0x50
  58. /* move data between buffer and flash */
  59. #define OP_TRANSFER_BUF1 0x53
  60. #define OP_TRANSFER_BUF2 0x55
  61. #define OP_MREAD_BUFFER1 0xD4
  62. #define OP_MREAD_BUFFER2 0xD6
  63. #define OP_MWERASE_BUFFER1 0x83
  64. #define OP_MWERASE_BUFFER2 0x86
  65. #define OP_MWRITE_BUFFER1 0x88
  66. #define OP_MWRITE_BUFFER2 0x89
  67. /* write to buffer, then write-erase to flash */
  68. #define OP_PROGRAM_VIA_BUF1 0x82
  69. #define OP_PROGRAM_VIA_BUF2 0x85
  70. /* compare buffer to flash */
  71. #define OP_COMPARE_BUF1 0x60
  72. #define OP_COMPARE_BUF2 0x61
  73. /* read flash to buffer, then write-erase to flash */
  74. #define OP_REWRITE_VIA_BUF1 0x58
  75. #define OP_REWRITE_VIA_BUF2 0x59
  76. /* newer chips report JEDEC manufacturer and device IDs; chip
  77. * serial number and OTP bits; and per-sector writeprotect.
  78. */
  79. #define OP_READ_ID 0x9F
  80. #define OP_READ_SECURITY 0x77
  81. #define OP_WRITE_SECURITY 0x9A
  82. /*------------------------------ 全局变量 -------------------------------------
  83. */
  84. int g_flash_is_ok;
  85. /*------------------------------ 函数声明 -------------------------------------
  86. */
  87. int _at45db321_identify(void);
  88. int _at45db321_page_read(uint32_t offset,unsigned char * buffer,uint32_t length);
  89. int _at45db321_page_write(uint32_t offset,unsigned char * buffer,uint32_t length);
  90. int _at45db321_page_erase(uint32_t offset);
  91. int _at45db321_wait_ready(unsigned char *p_status_register);
  92. /*------------------------------ 外部函数 -------------------------------------
  93. */
  94. /******************************************************************************
  95. 函数名称: flash_init
  96. 函数版本: 01.01
  97. 创建作者: sunxi
  98. 创建日期: 2008-08-19
  99. 函数说明: flash初始化。
  100. 参数说明: 无
  101. 返回值: 成功返回0.
  102. 修改记录:
  103. */
  104. int flash_init(void)
  105. {
  106. // GPIO_WP_FLASH_INIT();
  107. if(_at45db321_identify() == 0)
  108. {
  109. g_flash_is_ok = 1;
  110. }
  111. else
  112. {
  113. g_flash_is_ok = 0;
  114. }
  115. return 0;
  116. }
  117. int flash_exit(void)
  118. {
  119. return 0;
  120. }
  121. /******************************************************************************
  122. 函数名称: flash_read
  123. 函数版本: 01.01
  124. 创建作者: sunxi
  125. 创建日期: 2008-08-21
  126. 函数说明: 从FLASH中读出数据。
  127. 参数说明:
  128. offset(in):需要读的数据在FLASH中的偏移量,和length之和不能大于
  129. CFG_FLASH_SIZE.
  130. buffer(out):读出数据的buffer。
  131. length(in): 需要读出数据的长度,和offset之和不能大于CFG_FLASH_SIZE。
  132. 返回值: 成功返回0.
  133. 修改记录:
  134. */
  135. int flash_read(uint32_t offset,unsigned char * buffer,uint32_t length)
  136. {
  137. int ret;
  138. uint32_t length_once,length_spare;
  139. //检查FLASH是否OK
  140. if(g_flash_is_ok == 0)
  141. {
  142. return -1;
  143. }
  144. //检查参数
  145. if(buffer == 0 || (offset + length) > CFG_FLASH_SIZE)
  146. {
  147. return -1;
  148. }
  149. if(length == 0)
  150. {
  151. return 0;
  152. }
  153. //初始化length_spare
  154. length_spare = length;
  155. //读起始不完整页
  156. length_once = CFG_FLASH_PAGE_SIZE - offset%CFG_FLASH_PAGE_SIZE;
  157. if(length_once > length_spare)
  158. {
  159. length_once = length_spare;
  160. }
  161. if(length_once)
  162. {
  163. ret = _at45db321_page_read(offset,buffer,length_once);
  164. if(ret != 0)
  165. {
  166. return ret;
  167. }
  168. offset += length_once;
  169. buffer += length_once;
  170. length_spare -= length_once;
  171. }
  172. //循环读完整页。
  173. length_once = CFG_FLASH_PAGE_SIZE;
  174. while(length_spare > CFG_FLASH_PAGE_SIZE)
  175. {
  176. ret = _at45db321_page_read(offset,buffer,length_once);
  177. if(ret != 0)
  178. {
  179. return ret;
  180. }
  181. offset += length_once;
  182. buffer += length_once;
  183. length_spare -= length_once;
  184. }
  185. //读末尾不完整页。
  186. length_once = length_spare;
  187. if(length_once)
  188. {
  189. ret = _at45db321_page_read(offset,buffer,length_once);
  190. if(ret != 0)
  191. {
  192. return ret;
  193. }
  194. }
  195. return 0;
  196. }
  197. /******************************************************************************
  198. 函数名称: flash_write
  199. 函数版本: 01.01
  200. 创建作者: sunxi
  201. 创建日期: 2008-08-21
  202. 函数说明: 将数据写入FLASH中。
  203. 参数说明:
  204. offset(in):需要写入的数据在FLASH中的偏移量,和length之和不能大于
  205. CFG_FLASH_SIZE.
  206. buffer(in):写入数据的buffer。
  207. length(in): 需要写入数据的长度,和offset之和不能大于CFG_FLASH_SIZE。
  208. 返回值: 成功返回0.
  209. 修改记录:
  210. */
  211. int flash_write(uint32_t offset,unsigned char * buffer,uint32_t length)
  212. {
  213. int ret;
  214. uint32_t length_once,length_spare;
  215. //检查FLASH是否OK
  216. if(g_flash_is_ok == 0)
  217. {
  218. return -1;
  219. }
  220. //检查参数
  221. if(buffer == 0 || (offset + length) > CFG_FLASH_SIZE)
  222. {
  223. return -1;
  224. }
  225. if(length == 0)
  226. {
  227. return 0;
  228. }
  229. //初始化length_spare
  230. length_spare = length;
  231. //写起始不完整页
  232. length_once = CFG_FLASH_PAGE_SIZE - offset%CFG_FLASH_PAGE_SIZE;
  233. if(length_once > length_spare)
  234. {
  235. length_once = length_spare;
  236. }
  237. if(length_once)
  238. {
  239. ret = _at45db321_page_write(offset,buffer,length_once);
  240. if(ret != 0)
  241. {
  242. return ret;
  243. }
  244. offset += length_once;
  245. buffer += length_once;
  246. length_spare -= length_once;
  247. }
  248. //循环写完整页。
  249. length_once = CFG_FLASH_PAGE_SIZE;
  250. while(length_spare > CFG_FLASH_PAGE_SIZE)
  251. {
  252. ret = _at45db321_page_write(offset,buffer,length_once);
  253. if(ret != 0)
  254. {
  255. return ret;
  256. }
  257. offset += length_once;
  258. buffer += length_once;
  259. length_spare -= length_once;
  260. }
  261. //写末尾不完整页。
  262. length_once = length_spare;
  263. if(length_once)
  264. {
  265. ret = _at45db321_page_write(offset,buffer,length_once);
  266. if(ret != 0)
  267. {
  268. return ret;
  269. }
  270. }
  271. return 0;
  272. }
  273. /******************************************************************************
  274. 函数名称: flash_erase
  275. 函数版本: 01.01
  276. 创建作者: sunxi
  277. 创建日期: 2008-08-21
  278. 函数说明: 擦除FLASH中的指定区域。注意擦除是以页(CFG_FLASH_PAGE_SIZE)为单位
  279. 擦除的,为了保证用户指定的区域一定被擦除,实际擦除的长度可能大于指定
  280. 的长度,用户应小心处理这个问题。
  281. 参数说明:
  282. offset(in):需要擦除的页在FLASH中的偏移量,和length之和不能大于
  283. CFG_FLASH_SIZE.
  284. length(in): 需要擦除的长度,和offset之和不能大于CFG_FLASH_SIZE。
  285. 返回值: 成功返回0.
  286. 修改记录:
  287. */
  288. int flash_erase(uint32_t offset,uint32_t length)
  289. {
  290. uint32_t offset_last;
  291. //检查FLASH是否OK
  292. if(g_flash_is_ok == 0)
  293. {
  294. return -1;
  295. }
  296. //检查参数
  297. if((offset + length) > CFG_FLASH_SIZE)
  298. {
  299. return -1;
  300. }
  301. if(length == 0)
  302. {
  303. return 0;
  304. }
  305. //循环擦除指定空间
  306. offset_last = offset + length;
  307. offset -= offset%CFG_FLASH_PAGE_SIZE;
  308. while(offset < offset_last)
  309. {
  310. if(_at45db321_page_erase(offset) != 0)
  311. {
  312. return -2;
  313. }
  314. offset += CFG_FLASH_PAGE_SIZE;
  315. }
  316. return 0;
  317. }
  318. /******************************************************************************
  319. 函数名称: at45db321_sector_protection
  320. 函数版本: 01.01
  321. 创建作者: sunxi
  322. 创建日期: 2008-10-10
  323. 函数说明: 启用FLASH的扇区保护功能。
  324. 参数说明: 无。
  325. 返回值: 成功返回0.
  326. 修改记录:
  327. */
  328. int at45db321_sector_protection(void)
  329. {
  330. int h_qspi,i,ret;
  331. unsigned char cmd[4];
  332. //获取总线
  333. h_qspi = dspi_open(DSPI_ID_FLASH);
  334. if(h_qspi < 0)
  335. {
  336. return -1;
  337. }
  338. //解除写保护
  339. // GPIO_WP_FLASH_HIGH();
  340. ustimer_delay(1*USTIMER_US);
  341. //写命令和地址
  342. //擦除扇区保护寄存器命令(0x3d,0x2a,0x7f,0xcf)
  343. cmd[0] = 0x3d;
  344. cmd[1] = 0x2a;
  345. cmd[2] = 0x7f;
  346. cmd[3] = 0xcf;
  347. dspi_write(h_qspi,cmd,4);
  348. //关闭总线
  349. dspi_close(h_qspi);
  350. //等待flash操作完成
  351. ret = _at45db321_wait_ready(0);
  352. //写保护
  353. // GPIO_WP_FLASH_LOW();
  354. //开始确认保护是否完整
  355. //获取总线
  356. h_qspi = dspi_open(DSPI_ID_FLASH);
  357. if(h_qspi < 0)
  358. {
  359. return -1;
  360. }
  361. //写命令和地址
  362. //读扇区保护寄存器命令(0x32,0xxx,0xxx,0xxx)
  363. cmd[0] = 0x32;
  364. cmd[1] = 0x0;
  365. cmd[2] = 0x0;
  366. cmd[3] = 0x0;
  367. dspi_write(h_qspi,cmd,4);
  368. //读出数据比较
  369. for(i=0; i<64; i++)
  370. {
  371. dspi_read(h_qspi,cmd,1);
  372. if(cmd[0] != 0xff)
  373. {
  374. ret = -2;
  375. }
  376. }
  377. //关闭总线
  378. dspi_close(h_qspi);
  379. if(ret != 0)
  380. {
  381. return -2;
  382. }
  383. return 0;
  384. }
  385. /*------------------------------ 内部函数 -------------------------------------
  386. */
  387. /******************************************************************************
  388. 函数名称: _at45db321_wait_ready
  389. 函数版本: 01.01
  390. 创建作者: sunxi
  391. 创建日期: 2008-08-21
  392. 函数说明: 等待FLASH完成操作,如果需要返回状态寄存器的值
  393. 参数说明:
  394. p_status_register(out):如果不为0,返回状态寄存器的值
  395. 返回值: 成功返回0.
  396. 修改记录:
  397. */
  398. int _at45db321_wait_ready(unsigned char *p_status_register)
  399. {
  400. int h_qspi,ret;
  401. uint32_t us0,us;
  402. unsigned char c;
  403. //获取总线
  404. h_qspi = dspi_open(DSPI_ID_FLASH);
  405. if(h_qspi < 0)
  406. {
  407. return -1;
  408. }
  409. //写命令
  410. c = OP_READ_STATUS;
  411. dspi_write(h_qspi,&c,1);
  412. //超时等待就绪
  413. us0= ustimer_get_origin();
  414. while(1)
  415. {
  416. // 得到超时值
  417. us = ustimer_get_duration(us0);
  418. //读状态寄存器
  419. dspi_read(h_qspi,&c,1);
  420. if(c & 0x80)
  421. {
  422. ret = 0;
  423. break;
  424. }
  425. //最大BLOCK擦除时间为100ms
  426. if(us > 100*USTIMER_MS)
  427. {
  428. ret = -1;
  429. break;
  430. }
  431. }
  432. //需要的话,返回状态寄存器的值
  433. if(ret == 0 && p_status_register != 0)
  434. {
  435. dspi_read(h_qspi,p_status_register,1);
  436. }
  437. //关闭总线
  438. dspi_close(h_qspi);
  439. return ret;
  440. }
  441. /******************************************************************************
  442. 函数名称: _at45db321_identify
  443. 函数版本: 01.01
  444. 创建作者: sunxi
  445. 创建日期: 2008-08-21
  446. 函数说明: 检查AT45DB321是否OK
  447. 参数说明: 无
  448. 返回值: 成功返回0.
  449. 修改记录:
  450. */
  451. int _at45db321_identify(void)
  452. {
  453. int h_qspi,ret;
  454. unsigned char buffer[2];
  455. // unsigned char dev_info[2] = {0x1F, 0x27};
  456. unsigned char dev_info[2] = {0x20, 0xba}; //n25q
  457. h_qspi = dspi_open(DSPI_ID_FLASH);
  458. if(h_qspi < 0)
  459. {
  460. return -1;
  461. }
  462. buffer[0] = OP_READ_ID;
  463. dspi_write(h_qspi,buffer,1);
  464. dspi_read(h_qspi,buffer,2);
  465. rt_printf("FLASH:ID0=%02x,ID1=%02x.\r\n",buffer[0],buffer[1]);
  466. if(memcmp(buffer,dev_info,2) != 0)
  467. {
  468. ret = -2;
  469. }
  470. else
  471. {
  472. ret = 0;
  473. }
  474. dspi_close(h_qspi);
  475. return ret;
  476. }
  477. /******************************************************************************
  478. 函数名称: _at45db321_page_read
  479. 函数版本: 01.01
  480. 创建作者: sunxi
  481. 创建日期: 2008-08-21
  482. 函数说明: 从FLASH的一页中读出数据。
  483. 参数说明:
  484. offset(in):需要读的数据在FLASH中的偏移量。
  485. buffer(out):读出数据的buffer。
  486. length(in): 需要读出数据的长度。
  487. 返回值: 成功返回0.
  488. 修改记录:
  489. */
  490. int _at45db321_page_read(uint32_t offset,unsigned char * buffer,uint32_t length)
  491. {
  492. int h_qspi;
  493. uint32_t pa,ba;
  494. unsigned char cmd[4];
  495. //获取总线
  496. h_qspi = dspi_open(DSPI_ID_FLASH);
  497. if(h_qspi < 0)
  498. {
  499. return -1;
  500. }
  501. //得到页地址和页内偏移
  502. pa = offset/CFG_FLASH_PAGE_SIZE;
  503. ba = offset%CFG_FLASH_PAGE_SIZE;
  504. //1 reserved bit + 13位的页面地址 + 10位的页内地址
  505. //R P12 P11 P10 P9 P8 P7 P6 | P5 P4 P3 P2 P1 P0 B9 B8 | B7 B6 B5 B4 B3 B2 B1 B0
  506. cmd[1] = (unsigned char)(pa>>6);
  507. cmd[2] = (unsigned char)(unsigned char)(pa<<2 | (ba>>8 & 0x3));
  508. cmd[3] = (unsigned char)ba;
  509. //写命令和地址
  510. cmd[0] = OP_READ_PAGE;
  511. dspi_write(h_qspi,cmd,4);
  512. //等待32个时钟周期
  513. dspi_dummy_byte(h_qspi,4);
  514. //读出数据
  515. dspi_read(h_qspi,buffer,length);
  516. //关闭总线
  517. dspi_close(h_qspi);
  518. return 0;
  519. }
  520. /******************************************************************************
  521. 函数名称: _at45db321_page_write
  522. 函数版本: 01.01
  523. 创建作者: sunxi
  524. 创建日期: 2008-08-21
  525. 函数说明: 将数据写入FLASH的一页中。
  526. 参数说明:
  527. offset(in):需要写入的数据在FLASH中的偏移量.
  528. buffer(in):写入数据的buffer。
  529. length(in): 需要写入数据的长度。
  530. 返回值: 成功返回0.
  531. 修改记录:
  532. 2010-07-16 sunxi _at45db321_page_write函数以前是由OP_PROGRAM_VIA_BUF1命令
  533. 完成,现改为由OP_WRITE_BUFFER1和OP_MWRITE_BUFFER1命令组合
  534. 完成。见文件头说明
  535. */
  536. int _at45db321_page_write(uint32_t offset,unsigned char * buffer,uint32_t length)
  537. {
  538. int h_qspi,ret;
  539. uint32_t pa,ba;
  540. unsigned char cmd[4],status;
  541. //得到页地址和页内偏移
  542. pa = offset/CFG_FLASH_PAGE_SIZE;
  543. ba = offset%CFG_FLASH_PAGE_SIZE;
  544. //1 reserved bit + 13位的页面地址 + 10位的页内地址
  545. //R P12 P11 P10 P9 P8 P7 P6 | P5 P4 P3 P2 P1 P0 B9 B8 | B7 B6 B5 B4 B3 B2 B1 B0
  546. cmd[1] = (unsigned char)(pa>>6);
  547. cmd[2] = (unsigned char)(unsigned char)(pa<<2 | (ba>>8 & 0x3));
  548. cmd[3] = (unsigned char)ba;
  549. //1.先将数据从FLASH中读出到BUFFER1
  550. //获取总线
  551. h_qspi = dspi_open(DSPI_ID_FLASH);
  552. if(h_qspi < 0)
  553. {
  554. return -1;
  555. }
  556. //解除写保护
  557. // GPIO_WP_FLASH_HIGH();
  558. ustimer_delay(USTIMER_US);
  559. //写命令和地址
  560. cmd[0] = OP_TRANSFER_BUF1;
  561. dspi_write(h_qspi,cmd,4);
  562. //关闭总线
  563. dspi_close(h_qspi);
  564. //等待flash操作完成
  565. if(_at45db321_wait_ready(0) != 0)
  566. {
  567. return -2;
  568. }
  569. //2. 将数据写入BUF
  570. //获取总线
  571. h_qspi = dspi_open(DSPI_ID_FLASH);
  572. if(h_qspi < 0)
  573. {
  574. return -3;
  575. }
  576. //写命令和地址
  577. cmd[0] = OP_WRITE_BUFFER1;
  578. dspi_write(h_qspi,cmd,4);
  579. //写入数据
  580. dspi_write(h_qspi,buffer,length);
  581. //关闭总线
  582. dspi_close(h_qspi);
  583. //3. 将数据从BUF写入FLASH
  584. //获取总线
  585. h_qspi = dspi_open(DSPI_ID_FLASH);
  586. if(h_qspi < 0)
  587. {
  588. return -33;
  589. }
  590. //写命令和地址
  591. cmd[0] = OP_MWRITE_BUFFER1;
  592. dspi_write(h_qspi,cmd,4);
  593. //关闭总线
  594. dspi_close(h_qspi);
  595. //等待flash操作完成
  596. ret = _at45db321_wait_ready(0);
  597. //写保护
  598. // GPIO_WP_FLASH_LOW();
  599. if(ret != 0)
  600. {
  601. return -4;
  602. }
  603. //4. 检查写入的数据是否正确
  604. //获取总线
  605. h_qspi = dspi_open(DSPI_ID_FLASH);
  606. if(h_qspi < 0)
  607. {
  608. return -5;
  609. }
  610. //写命令和地址
  611. cmd[0] = OP_COMPARE_BUF1;
  612. dspi_write(h_qspi,cmd,4);
  613. //关闭总线
  614. dspi_close(h_qspi);
  615. //等待flash操作完成
  616. if(_at45db321_wait_ready(&status) != 0)
  617. {
  618. return -6;
  619. }
  620. //比较不正确的话,返回出错。
  621. if(status & 0x40)
  622. {
  623. return -7;
  624. }
  625. return 0;
  626. }
  627. /******************************************************************************
  628. 函数名称: _at45db321_page_erase
  629. 函数版本: 01.01
  630. 创建作者: sunxi
  631. 创建日期: 2008-08-21
  632. 函数说明: 擦除FLASH中的一页。
  633. 参数说明:
  634. offset(in):需要擦除的页在FLASH中的偏移量.
  635. 返回值: 成功返回0.
  636. 修改记录:
  637. */
  638. int _at45db321_page_erase(uint32_t offset)
  639. {
  640. int h_qspi,ret;
  641. uint32_t pa,ba;
  642. unsigned char cmd[4];
  643. //获取总线
  644. h_qspi = dspi_open(DSPI_ID_FLASH);
  645. if(h_qspi < 0)
  646. {
  647. return -1;
  648. }
  649. //解除写保护
  650. // GPIO_WP_FLASH_HIGH();
  651. ustimer_delay(USTIMER_US);
  652. //得到页地址和页内偏移
  653. pa = offset/CFG_FLASH_PAGE_SIZE;
  654. ba = offset%CFG_FLASH_PAGE_SIZE;
  655. //1 reserved bit + 13位的页面地址 + 10位的页内地址
  656. //R P12 P11 P10 P9 P8 P7 P6 | P5 P4 P3 P2 P1 P0 B9 B8 | B7 B6 B5 B4 B3 B2 B1 B0
  657. cmd[1] = (unsigned char)(pa>>6);
  658. cmd[2] = (unsigned char)(unsigned char)(pa<<2 | (ba>>8 & 0x3));
  659. cmd[3] = (unsigned char)ba;
  660. //写命令和地址
  661. cmd[0] = OP_ERASE_PAGE;
  662. dspi_write(h_qspi,cmd,4);
  663. //关闭总线
  664. dspi_close(h_qspi);
  665. //等待flash操作完成
  666. ret = _at45db321_wait_ready(0);
  667. //写保护
  668. // GPIO_WP_FLASH_LOW();
  669. if(ret != 0)
  670. {
  671. return -2;
  672. }
  673. return 0;
  674. }
  675. /*------------------------------ 测试函数 -------------------------------------
  676. */
  677. #ifdef _DEBUG_FLASH
  678. #define FLASH_BLOCK_SIZE CFG_FLASH_PAGE_SIZE
  679. int flash_test(void)
  680. {
  681. int ret;
  682. u32 i, j;
  683. uint32_t block_size,blocks;
  684. uint32_t us0,us;
  685. unsigned int gTestBuf[FLASH_BLOCK_SIZE/sizeof(int)];
  686. block_size = FLASH_BLOCK_SIZE;
  687. blocks = CFG_FLASH_SIZE/FLASH_BLOCK_SIZE;
  688. // blocks = 1;
  689. rt_printf("flash_test begin!\r\n");
  690. rt_printf("block_size=%lu,blocks=%lu.\r\n",block_size,blocks);
  691. // dspi_init();
  692. us0 = ustimer_get_origin();
  693. //while(1)
  694. ret = _at45db321_identify();
  695. us = ustimer_get_duration(us0);
  696. if(ret != 0)
  697. {
  698. rt_printf("at45db321d_Identify error!(ret=%d)!\r\n",ret);
  699. return -1;
  700. }
  701. rt_printf("at45db321d_Identify ok!(us=%lu)!\r\n",us);
  702. //启用FLASH的扇区保护功能
  703. ret = at45db321_sector_protection();
  704. rt_printf("at45db321_sector_protection:ret=%d!\r\n",ret);
  705. //擦除整个flash。
  706. us0 = ustimer_get_origin();
  707. ret = flash_erase(0,blocks*block_size);
  708. us = ustimer_get_duration(us0);
  709. rt_printf("at45DB321Erase (us=%lu,ret=%d)!\r\n",us,ret);
  710. //确认擦除OK
  711. us0 = ustimer_get_origin();
  712. for(i=0;i<blocks;i++)
  713. {
  714. ret = flash_read(i*block_size,(unsigned char *)gTestBuf,block_size);
  715. if(ret != 0)
  716. {
  717. rt_printf("at45db321Read failure(i=%lu,ret=%d)!\r\n",i,ret);
  718. return -1;
  719. }
  720. for(j=0;j<block_size/sizeof(int);j++)
  721. {
  722. if(gTestBuf[j] != 0xffffffff)
  723. {
  724. rt_printf("at45DB321Erase verify failure(i=%lu,j=%lu,data=0x%08x)!\r\n",i,j,gTestBuf[j]);
  725. return -1;
  726. }
  727. }
  728. }
  729. us = ustimer_get_duration(us0);
  730. rt_printf("at45DB321Erase verify ok(us=%lu)!\r\n",us);
  731. //整个flash写0
  732. memset(gTestBuf,0,sizeof(gTestBuf));
  733. us0 = ustimer_get_origin();
  734. for(i=0;i<blocks;i++)
  735. {
  736. ret = flash_write(i*block_size,(unsigned char *)gTestBuf,block_size);
  737. if(ret != 0)
  738. {
  739. rt_printf("at45DB321Write failure(i=%lu,ret=%d)!\r\n",i,ret);
  740. return -1;
  741. }
  742. }
  743. us = ustimer_get_duration(us0);
  744. rt_printf("at45DB321Write ok(us=%lu)!\r\n",us);
  745. //检查整个flash是否全为0
  746. us0 = ustimer_get_origin();
  747. for(i=0;i<blocks;i++)
  748. {
  749. ret = flash_read(i*block_size,(unsigned char *)gTestBuf,block_size);
  750. if(ret != 0)
  751. {
  752. rt_printf("at45db321Read failure(i=%lu,ret=%d)!\r\n",i,ret);
  753. return -1;
  754. }
  755. for(j=0;j<block_size/sizeof(int);j++)
  756. {
  757. if(gTestBuf[j] != 0)
  758. {
  759. rt_printf("at45DB321Write verify failure(i=%lu,j=%lu,data=0x%08x)!\r\n",i,j,gTestBuf[j]);
  760. return -1;
  761. }
  762. }
  763. }
  764. us = ustimer_get_duration(us0);
  765. rt_printf("at45DB321Write verify ok(us=%lu)!\r\n",us);
  766. //擦除整个flash
  767. us0 = ustimer_get_origin();
  768. ret = flash_erase(0,blocks*block_size);
  769. us = ustimer_get_duration(us0);
  770. rt_printf("at45DB321Erase (us=%lu,ret=%d)!\r\n",us,ret);
  771. //确认擦除OK
  772. us0 = ustimer_get_origin();
  773. for(i=0;i<blocks;i++)
  774. {
  775. ret = flash_read(i*block_size,(unsigned char *)gTestBuf,block_size);
  776. if(ret != 0)
  777. {
  778. rt_printf("at45db321Read failure(i=%lu,ret=%d)!\r\n",i,ret);
  779. return -1;
  780. }
  781. for(j=0;j<block_size/sizeof(int);j++)
  782. {
  783. if(gTestBuf[j] != 0xffffffff)
  784. {
  785. rt_printf("at45DB321Erase verify failure(i=%lu,j=%lu,data=0x%08x)!\r\n",i,j,gTestBuf[j]);
  786. return -1;
  787. }
  788. }
  789. }
  790. us = ustimer_get_duration(us0);
  791. rt_printf("at45DB321Erase verify ok(us=%lu)!\r\n",us);
  792. //整个flash写测试数据
  793. us0 = ustimer_get_origin();
  794. for(i=0;i<blocks;i++)
  795. {
  796. //初始化写数据
  797. for(j=0;j<block_size/sizeof(int);j++)
  798. {
  799. gTestBuf[j] = i*block_size/sizeof(int) + j;
  800. }
  801. //写
  802. ret = flash_write(i*block_size,(unsigned char *)gTestBuf,block_size);
  803. if(ret != 0)
  804. {
  805. rt_printf("at45DB321Write failure(i=%lu,ret=%d)!\r\n",i,ret);
  806. return -1;
  807. }
  808. }
  809. us = ustimer_get_duration(us0);
  810. rt_printf("at45DB321Write ok(us=%lu)!\r\n",us);
  811. //读出并校验数据
  812. us0 = ustimer_get_origin();
  813. for(i=0;i<blocks;i++)
  814. {
  815. ret = flash_read(i*block_size,(unsigned char *)gTestBuf,block_size);
  816. if(ret != 0)
  817. {
  818. rt_printf("at45db321Read failure(i=%lu,ret=%d)!\r\n",i,ret);
  819. return -1;
  820. }
  821. for(j=0;j<block_size/sizeof(int);j++)
  822. if(gTestBuf[j] != i*block_size/sizeof(int) + j)
  823. {
  824. rt_printf("at45DB321Write verify failure(i=%lu,j=%lu,data=0x%08x)!\r\n",i,j,gTestBuf[j]);
  825. return -1;
  826. }
  827. }
  828. us = ustimer_get_duration(us0);
  829. rt_printf("at45DB321Write verify ok(us=%lu)!\r\n",us);
  830. rt_printf("flash_test end!\r\n\n");
  831. return 0;
  832. }
  833. #endif