nor_flash.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. /*
  2. *********************************************************************************************************
  3. *
  4. * 模块名称 : NOR Flash驱动模块
  5. * 文件名称 : bsp_nor_flash.c
  6. * 版 本 : V1.0
  7. * 说 明 : 安富莱STM32-V5开发板标配的NOR Flash 为 S29GL128P10TFI01 容量16M字节,16Bit,100ns速度
  8. * 物理地址 : 0x6400 0000
  9. * 修改记录 :
  10. * 版本号 日期 作者 说明
  11. * V1.0 2013-02-01 armfly 正式发布
  12. *
  13. * Copyright (C), 2013-2014, 安富莱电子 www.armfly.com
  14. *
  15. *********************************************************************************************************
  16. */
  17. /*
  18. S29GL128P 内存组织结构: 每个扇区128K字节,一共128个扇区。总容量为 16M字节。按16Bit访问。
  19. 挂在STM32上,对应的物理地址范围为 : 0x6400 0000 - 0x64FF FFFF. 只能按16Bit模式访问。
  20. */
  21. #include "nor_flash.h"
  22. #include "interface.h"
  23. #include <inttypes.h>
  24. #define ADDR_SHIFT(A) (NOR_FLASH_ADDR + (2 * (A)))
  25. #define NOR_WRITE(Address, Data) (*(__IO uint16_t *)(Address) = (Data))
  26. /* 判忙时的执行语句循环次数 */
  27. #define BlockErase_Timeout ((uint32_t)0x00A00000)
  28. #define ChipErase_Timeout ((uint32_t)0x30000000)
  29. #define Program_Timeout ((uint32_t)0x00001400)
  30. /* PD6 是NOR Flash输出到STM32的忙信号, 通过GPIO查询方式判忙 */
  31. #define NOR_IS_BUSY() (GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_6) == RESET)
  32. static void NOR_QuitToReadStatus(void);
  33. static uint8_t NOR_GetStatus(uint32_t Timeout);
  34. /*
  35. *********************************************************************************************************
  36. * 函 数 名: bsp_InitNorFlash
  37. * 功能说明: 配置连接外部NOR Flash的GPIO和FSMC
  38. * 形 参: 无
  39. * 返 回 值: 无
  40. *********************************************************************************************************
  41. */
  42. void nor_flash_init(void)
  43. {
  44. FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
  45. FSMC_NORSRAMTimingInitTypeDef p;
  46. /* NOR Flash 的 GPIO :
  47. PD0/FSMC_D2
  48. PD1/FSMC_D3
  49. PD4/FSMC_NOE
  50. PD5/FSMC_NWE
  51. PD6/FSMC_NWAIT - 忙信号,配置为GPIO,输入模式,通过软件查询方式判忙
  52. PD8/FSMC_D13
  53. PD9/FSMC_D14
  54. PD10/FSMC_D15
  55. PD11/FSMC_CLE/FSMC_A16
  56. PD12/FSMC_ALE/FSMC_A17
  57. PD13/FSMC_A18
  58. PD14/FSMC_D0
  59. PD15/FSMC_D1
  60. PE3/FSMC_A19
  61. PE4/FSMC_A20
  62. PE5/FSMC_A21
  63. PE6/FSMC_A22
  64. PE7/FSMC_D4
  65. PE8/FSMC_D5
  66. PE9/FSMC_D6
  67. PE10/FSMC_D7
  68. PE11/FSMC_D8
  69. PE12/FSMC_D9
  70. PE13/FSMC_D10
  71. PE14/FSMC_D11
  72. PE15/FSMC_D12
  73. PF0/FSMC_A0
  74. PF1/FSMC_A1
  75. PF2/FSMC_A2
  76. PF3/FSMC_A3
  77. PF4/FSMC_A4
  78. PF5/FSMC_A5
  79. PF12/FSMC_A6
  80. PF13/FSMC_A7
  81. PF14/FSMC_A8
  82. PF15/FSMC_A9
  83. PG0/FSMC_A10
  84. PG1/FSMC_A11
  85. PG2/FSMC_A12
  86. PG3/FSMC_A13
  87. PG4/FSMC_A14
  88. PG5/FSMC_A15
  89. PG9/FSMC_NE2 - 片选信号
  90. */
  91. /*-- FSMC Configuration ------------------------------------------------------*/
  92. p.FSMC_AddressSetupTime = 0x06; /* 0x05正常, 0x04 出错 */
  93. p.FSMC_AddressHoldTime = 0x01;
  94. p.FSMC_DataSetupTime = 0x0C; /* 0x0B正常, 0x0A 出错 */
  95. p.FSMC_BusTurnAroundDuration = 0x00;
  96. p.FSMC_CLKDivision = 0x00;
  97. p.FSMC_DataLatency = 0x00;
  98. p.FSMC_AccessMode = FSMC_AccessMode_B;
  99. FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM2;
  100. FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
  101. FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR;
  102. FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
  103. FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
  104. FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
  105. FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
  106. FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
  107. FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
  108. FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
  109. FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
  110. FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
  111. FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
  112. FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
  113. FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
  114. FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
  115. /*!< Enable FSMC Bank1_SRAM2 Bank */
  116. FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM2, ENABLE);
  117. }
  118. /*
  119. *********************************************************************************************************
  120. * 函 数 名: NOR_ReadID
  121. * 功能说明: 读取NOR Flash的器件ID
  122. * 形 参: 无
  123. * 返 回 值: 器件ID,32Bit, 高8bit 是Manufacturer_Code, 低24bit是器件ID
  124. *********************************************************************************************************
  125. */
  126. uint32_t NOR_ReadID(void)
  127. {
  128. uint32_t uiID;
  129. uint8_t id1, id2, id3, id4;
  130. NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
  131. NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
  132. NOR_WRITE(ADDR_SHIFT(0x0555), 0x0090);
  133. id1 = *(__IO uint16_t *)ADDR_SHIFT(0x0000);
  134. id2 = *(__IO uint16_t *)ADDR_SHIFT(0x0001);
  135. id3 = *(__IO uint16_t *)ADDR_SHIFT(0x000E);
  136. id4 = *(__IO uint16_t *)ADDR_SHIFT(0x000F);
  137. uiID = ((uint32_t)id1 << 24) | ((uint32_t)id2 << 16) | ((uint32_t)id3 << 8) | id4;
  138. NOR_WRITE(NOR_FLASH_ADDR, 0x00F0); /* 退出ID模式 */
  139. return uiID;
  140. }
  141. /*
  142. *********************************************************************************************************
  143. * 函 数 名: NOR_QuitToReadStatus
  144. * 功能说明: 复位NOR,退到读状态
  145. * 形 参: 无
  146. * 返 回 值: 无
  147. *********************************************************************************************************
  148. */
  149. static void NOR_QuitToReadStatus(void)
  150. {
  151. NOR_WRITE(ADDR_SHIFT(0x00555), 0x00AA);
  152. NOR_WRITE(ADDR_SHIFT(0x002AA), 0x0055);
  153. NOR_WRITE(NOR_FLASH_ADDR, 0x00F0);
  154. }
  155. /*
  156. *********************************************************************************************************
  157. * 函 数 名: NOR_GetStatus
  158. * 功能说明: 读取NOR的操作状态
  159. * 形 参: 无
  160. * 返 回 值: 0表示成功. NOR_SUCCESS, NOR_ERROR, NOR_TIMEOUT
  161. *********************************************************************************************************
  162. */
  163. static uint8_t NOR_GetStatus(uint32_t Timeout)
  164. {
  165. uint16_t val1 = 0x00;
  166. uint16_t val2 = 0x00;
  167. uint8_t status = NOR_ONGOING;
  168. uint32_t timeout = Timeout;
  169. /* 等待NOR输出忙信号,高电平时等待。避免NOR的忙信号还未反映过来导致CPU提前认为不忙了 */
  170. while ((!NOR_IS_BUSY()) && (timeout > 0))
  171. {
  172. timeout--;
  173. }
  174. /* 等待NOR忙信号结束,低电平时等待 */
  175. timeout = Timeout;
  176. while (NOR_IS_BUSY() && (timeout > 0))
  177. {
  178. timeout--;
  179. }
  180. /*
  181. - DQ 6 编程时跳变
  182. - DQ 6 和 DQ 2 在擦除时跳变
  183. - DQ 2 在擦除挂起时跳变
  184. - DQ 1 在编程错误时置1
  185. - DQ 5 在超时时置1
  186. */
  187. /* 通过读取DQ6, DQ5 的数据位是否存在翻转现象判断NOR 内部操作是否完成。如果正忙,则第2次读和第1次读的数据不同 */
  188. while ((Timeout != 0x00) && (status != NOR_SUCCESS))
  189. {
  190. Timeout--;
  191. /* Read DQ6 */
  192. val1 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
  193. val2 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
  194. /* If DQ6 did not toggle between the two reads then return NOR_Success */
  195. if ((val1 & 0x0040) == (val2 & 0x0040))
  196. {
  197. return NOR_SUCCESS;
  198. }
  199. /* Read DQ2 */
  200. if ((val1 & 0x0020) != 0x0020)
  201. {
  202. status = NOR_ONGOING;
  203. }
  204. val1 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
  205. val2 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
  206. if ((val1 & 0x0040) == (val2 & 0x0040))
  207. {
  208. return NOR_SUCCESS;
  209. }
  210. else if ((val1 & 0x0020) == 0x0020)
  211. {
  212. status = NOR_ERROR;
  213. NOR_QuitToReadStatus();
  214. }
  215. }
  216. if (Timeout == 0x00)
  217. {
  218. status = NOR_TIMEOUT;
  219. NOR_QuitToReadStatus();
  220. }
  221. /* 返回操作状态 */
  222. return (status);
  223. }
  224. /*
  225. *********************************************************************************************************
  226. * 函 数 名: NOR_EraseChip
  227. * 功能说明: 擦除NOR Flash整个芯片
  228. * 形 参: 无
  229. * 返 回 值: 0表示成功
  230. *********************************************************************************************************
  231. */
  232. uint8_t NOR_EraseChip(void)
  233. {
  234. NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
  235. NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
  236. NOR_WRITE(ADDR_SHIFT(0x0555), 0x0080);
  237. NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
  238. NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
  239. NOR_WRITE(ADDR_SHIFT(0x0555), 0x0010);
  240. return (NOR_GetStatus(ChipErase_Timeout));
  241. }
  242. /*
  243. *********************************************************************************************************
  244. * 函 数 名: NOR_StartEraseChip
  245. * 功能说明: 开始擦除NOR Flash整个芯片, 不等待结束
  246. * 形 参: 无
  247. * 返 回 值: 0表示成功
  248. *********************************************************************************************************
  249. */
  250. void NOR_StartEraseChip(void)
  251. {
  252. NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
  253. NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
  254. NOR_WRITE(ADDR_SHIFT(0x0555), 0x0080);
  255. NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
  256. NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
  257. NOR_WRITE(ADDR_SHIFT(0x0555), 0x0010);
  258. NOR_GetStatus(1000);
  259. }
  260. /*
  261. *********************************************************************************************************
  262. * 函 数 名: NOR_CheckComplete
  263. * 功能说明: 检测擦除是否完成
  264. * 形 参: 无
  265. * 返 回 值: 0表示成功 NOR_SUCCESS, NOR_ERROR, NOR_TIMEOUT
  266. *********************************************************************************************************
  267. */
  268. uint8_t NOR_CheckStatus(void)
  269. {
  270. uint16_t val1 = 0x00;
  271. uint16_t val2 = 0x00;
  272. uint8_t status = NOR_ONGOING;
  273. uint32_t timeout = 10;
  274. /*
  275. - DQ 6 编程时跳变
  276. - DQ 6 和 DQ 2 在擦除时跳变
  277. - DQ 2 在擦除挂起时跳变
  278. - DQ 1 在编程错误时置1
  279. - DQ 5 在超时时置1
  280. */
  281. /* 通过读取DQ6, DQ5 的数据位是否存在翻转现象判断NOR 内部操作是否完成。如果正忙,则第2次读和第1次读的数据不同 */
  282. while ((timeout != 0x00) && (status != NOR_SUCCESS))
  283. {
  284. timeout--;
  285. /* Read DQ6 */
  286. val1 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
  287. val2 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
  288. /* If DQ6 did not toggle between the two reads then return NOR_Success */
  289. if ((val1 & 0x0040) == (val2 & 0x0040))
  290. {
  291. return NOR_SUCCESS;
  292. }
  293. /* Read DQ2 */
  294. if ((val1 & 0x0020) != 0x0020)
  295. {
  296. status = NOR_ONGOING;
  297. }
  298. val1 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
  299. val2 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
  300. if ((val1 & 0x0040) == (val2 & 0x0040))
  301. {
  302. return NOR_SUCCESS;
  303. }
  304. else if ((val1 & 0x0020) == 0x0020)
  305. {
  306. status = NOR_ERROR;
  307. NOR_QuitToReadStatus();
  308. }
  309. }
  310. if (timeout == 0x00)
  311. {
  312. status = NOR_TIMEOUT;
  313. // NOR_QuitToReadStatus();
  314. }
  315. /* 返回操作状态 */
  316. return (status);
  317. }
  318. /*
  319. *********************************************************************************************************
  320. * 函 数 名: NOR_EraseSector
  321. * 功能说明: 擦除NOR Flash指定的扇区
  322. * 形 参: 扇区地址
  323. * 返 回 值: NOR_SUCCESS, NOR_ERROR, NOR_TIMEOUT
  324. *********************************************************************************************************
  325. */
  326. uint8_t NOR_EraseSector(uint32_t _uiBlockAddr)
  327. {
  328. NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
  329. NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
  330. NOR_WRITE(ADDR_SHIFT(0x0555), 0x0080);
  331. NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
  332. NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
  333. NOR_WRITE((NOR_FLASH_ADDR + _uiBlockAddr), 0x30);
  334. return (NOR_GetStatus(BlockErase_Timeout));
  335. }
  336. /*
  337. *********************************************************************************************************
  338. * 函 数 名: NOR_ReadByte
  339. * 功能说明: 读取单字节数据
  340. * 形 参: _uiWriteAddr : 偏移地址[0, 16*1024*1024 - 2]; 编程地址可以为偶数,也可以为奇数。
  341. * 返 回 值: 读取到的数据
  342. *********************************************************************************************************
  343. */
  344. uint8_t NOR_ReadByte(uint32_t _uiWriteAddr)
  345. {
  346. uint16_t usHalfWord;
  347. if (_uiWriteAddr % 2) /* 奇数地址 */
  348. {
  349. usHalfWord = *(uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr - 1);
  350. return (usHalfWord >> 8); /* 取高8Bit */
  351. }
  352. else /* 偶数地址 */
  353. {
  354. usHalfWord = *(uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr);
  355. return usHalfWord; /* 取低8Bit */
  356. }
  357. }
  358. /*
  359. *********************************************************************************************************
  360. * 函 数 名: NOR_ReadBuffer
  361. * 功能说明: 连续读取NOR Flash
  362. * 形 参: _pBuf : 字节型数据缓冲区,用于存放读出的数据
  363. * _uiWriteAddr : 偏移地址[0, 16*1024*1024 - 2]; 编程地址可以为偶数,也可以为奇数。
  364. * _uiBytes : 字节大小
  365. * 返 回 值: 读取到的数据
  366. *********************************************************************************************************
  367. */
  368. void NOR_ReadBuffer(uint8_t *_pBuf, uint32_t _uiWriteAddr, uint32_t _uiBytes)
  369. {
  370. uint16_t usHalfWord;
  371. uint16_t *pNor16;
  372. uint32_t i;
  373. uint32_t uiNum;
  374. uiNum = _uiBytes;
  375. /* 处理首字节 */
  376. if (_uiWriteAddr % 2) /* 奇数地址 */
  377. {
  378. usHalfWord = *(uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr - 1);
  379. *_pBuf++ = (usHalfWord >> 8); /* 取高8Bit */
  380. uiNum--;
  381. _uiWriteAddr++; /* 变为偶数 */
  382. }
  383. /* 按照双字节模式连续读取NOR数据至缓冲区_pBuf */
  384. pNor16 = (uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr);
  385. for (i = 0; i < uiNum / 2; i++)
  386. {
  387. usHalfWord = *pNor16++;
  388. *_pBuf++ = usHalfWord;
  389. *_pBuf++ = usHalfWord >> 8;
  390. uiNum -= 2;
  391. }
  392. /* 处理最后1个字节 */
  393. if (uiNum == 1)
  394. {
  395. *_pBuf++ = *pNor16;
  396. }
  397. }
  398. /*
  399. *********************************************************************************************************
  400. * 函 数 名: NOR_WriteHalfWord
  401. * 功能说明: 半字编程. 编程前执行解锁命令序列。编程完毕后,自动退到读取模式。半字编程可以是随机地址。
  402. * 编程前需要保证存储单元是全0xFF状态。可以重复编程相同的数据。
  403. * 形 参: _uiWriteAddr : 偏移地址[0, 16*1024*1024 - 2]; 编程地址必须为偶数
  404. * _usData : 数据 16Bit
  405. *
  406. * 返 回 值: NOR_SUCCESS, NOR_ERROR, NOR_TIMEOUT
  407. *********************************************************************************************************
  408. */
  409. uint8_t NOR_WriteHalfWord(uint32_t _uiWriteAddr, uint16_t _usData)
  410. {
  411. NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
  412. NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
  413. NOR_WRITE(ADDR_SHIFT(0x0555), 0x00A0);
  414. NOR_WRITE(NOR_FLASH_ADDR + _uiWriteAddr, _usData);
  415. return (NOR_GetStatus(Program_Timeout));
  416. }
  417. /*
  418. *********************************************************************************************************
  419. * 函 数 名: NOR_WriteByte
  420. * 功能说明: 字节编程. 编程前需要保证存储单元是全0xFF状态。可以重复编程相同的数据。
  421. * 形 参: _uiWriteAddr : 偏移地址[0, 16*1024*1024 - 1]; 编程地址可以为奇数也可以为偶数
  422. * _usData : 数据 16Bit
  423. *
  424. * 返 回 值: NOR_SUCCESS, NOR_ERROR, NOR_TIMEOUT
  425. *********************************************************************************************************
  426. */
  427. uint8_t NOR_WriteByte(uint32_t _uiWriteAddr, uint8_t _ucByte)
  428. {
  429. uint16_t usHalfWord;
  430. if (_uiWriteAddr % 2) /* 奇数地址 */
  431. {
  432. /* 读出2字节数据,然后改写高字节,维持以前的低字节数据不变 */
  433. usHalfWord = *(uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr - 1);
  434. usHalfWord &= 0x00FF;
  435. usHalfWord |= (_ucByte << 8);
  436. }
  437. else
  438. {
  439. /* 读取NOR原始数据,保留高字节 */
  440. usHalfWord = *(uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr);
  441. usHalfWord &= 0xFF00;
  442. usHalfWord |= _ucByte;
  443. }
  444. return NOR_WriteHalfWord(_uiWriteAddr, usHalfWord);
  445. }
  446. /*
  447. *********************************************************************************************************
  448. * 函 数 名: NOR_WriteInPage.
  449. * 功能说明: 页面内编程(64字节一个页面). 编程前需要保证存储单元是全0xFF状态。可以重复编程相同的数据。
  450. * 形 参: pBuffer : 数据存放在此缓冲区
  451. * _uiWriteAddr : 偏移地址, 必须是偶数开始
  452. * _usNumHalfword : 数据格式,双字节为1个单位. 值域: 1-32
  453. *
  454. * 返 回 值: NOR_SUCCESS, NOR_ERROR, NOR_TIMEOUT
  455. *********************************************************************************************************
  456. */
  457. uint8_t NOR_WriteInPage(uint16_t *pBuffer, uint32_t _uiWriteAddr, uint16_t _usNumHalfword)
  458. {
  459. uint32_t lastloadedaddress;
  460. uint32_t currentaddress;
  461. uint32_t endaddress;
  462. /* pdf 表7.7 写入缓冲器编程
  463. 写入缓冲器编程允许系统在一个编程操作中写入最多32 个字。与标准的“ 字” 编程算法相比,这可以有效地
  464. 加快字编程速度。
  465. */
  466. if (_usNumHalfword > 32)
  467. {
  468. return NOR_ERROR;
  469. }
  470. if ((_uiWriteAddr % 2) != 0)
  471. {
  472. return NOR_ERROR;
  473. }
  474. _uiWriteAddr = _uiWriteAddr / 2;
  475. currentaddress = _uiWriteAddr;
  476. endaddress = _uiWriteAddr + _usNumHalfword - 1;
  477. lastloadedaddress = _uiWriteAddr;
  478. /* 解锁命令序列 */
  479. NOR_WRITE(ADDR_SHIFT(0x00555), 0x00AA);
  480. NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
  481. /* Write Write Buffer Load Command */
  482. NOR_WRITE(ADDR_SHIFT(_uiWriteAddr), 0x0025);
  483. NOR_WRITE(ADDR_SHIFT(_uiWriteAddr), (_usNumHalfword - 1));
  484. /* Load Data into NOR Buffer */
  485. while (currentaddress <= endaddress)
  486. {
  487. /* Store last loaded address & data value (for polling) */
  488. lastloadedaddress = currentaddress;
  489. NOR_WRITE(ADDR_SHIFT(currentaddress), *pBuffer++);
  490. currentaddress += 1;
  491. }
  492. NOR_WRITE(ADDR_SHIFT(lastloadedaddress), 0x29);
  493. return (NOR_GetStatus(Program_Timeout));
  494. }
  495. /*
  496. *********************************************************************************************************
  497. * 函 数 名: NOR_WriteBuffer
  498. * 功能说明: 连续编程操作。采取半字编程模式。
  499. * S29GL 支持64字节页面大小的连续编程。本函数暂时不支持页面编程。
  500. * 形 参: _pBuf : 8位数据缓冲区
  501. * _uiWriteAddr : 写入的存储单元首地址, 必须为偶数
  502. * _uiBytes : 字节个数
  503. * 返 回 值: NOR_SUCCESS, NOR_ERROR, NOR_TIMEOUT
  504. *********************************************************************************************************
  505. */
  506. uint8_t NOR_WriteBuffer(uint8_t *_pBuf, uint32_t _uiWriteAddr, uint32_t _uiBytes)
  507. {
  508. uint16_t usHalfWord;
  509. uint32_t i;
  510. uint32_t uiNum;
  511. uint8_t ucStatus;
  512. uiNum = _uiBytes;
  513. /* 处理首字节 */
  514. if (_uiWriteAddr % 2) /* 奇数地址 */
  515. {
  516. /* 读出2字节数据,然后改写高字节,维持以前的低字节数据不变 */
  517. usHalfWord = *(uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr - 1);
  518. usHalfWord &= 0x00FF;
  519. usHalfWord |= ((*_pBuf++) << 8);
  520. ucStatus = NOR_WriteHalfWord(_uiWriteAddr - 1, usHalfWord);
  521. if (ucStatus != NOR_SUCCESS)
  522. {
  523. goto err_quit;
  524. }
  525. uiNum--;
  526. _uiWriteAddr++; /* 变为偶数 */
  527. }
  528. /* 按照双字节模式连续编程NOR数据 */
  529. for (i = 0; i < uiNum / 2; i++)
  530. {
  531. usHalfWord = *_pBuf++;
  532. usHalfWord |= ((*_pBuf++) << 8);
  533. ucStatus = NOR_WriteHalfWord(_uiWriteAddr, usHalfWord);
  534. if (ucStatus != NOR_SUCCESS)
  535. {
  536. goto err_quit;
  537. }
  538. _uiWriteAddr += 2;
  539. }
  540. /* 处理最后1个字节 */
  541. if (uiNum % 2)
  542. {
  543. /* 读取NOR原始数据,保留高字节 */
  544. usHalfWord = *(uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr);
  545. usHalfWord &= 0xFF00;
  546. usHalfWord |= (*_pBuf++);
  547. ucStatus = NOR_WriteHalfWord(_uiWriteAddr, usHalfWord);
  548. if (ucStatus != NOR_SUCCESS)
  549. {
  550. goto err_quit;
  551. }
  552. }
  553. ucStatus = NOR_SUCCESS;
  554. err_quit:
  555. return ucStatus;
  556. }
  557. /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/