You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

677 lines
17 KiB

  1. /**
  2. *
  3. * \file
  4. *
  5. * \brief SPI Flash.
  6. *
  7. * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries.
  8. *
  9. * \asf_license_start
  10. *
  11. * \page License
  12. *
  13. * Subject to your compliance with these terms, you may use Microchip
  14. * software and any derivatives exclusively with Microchip products.
  15. * It is your responsibility to comply with third party license terms applicable
  16. * to your use of third party software (including open source software) that
  17. * may accompany Microchip software.
  18. *
  19. * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
  20. * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
  21. * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
  22. * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
  23. * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
  24. * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
  25. * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
  26. * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
  27. * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
  28. * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
  29. * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
  30. *
  31. * \asf_license_stop
  32. *
  33. */
  34. #ifdef PROFILING
  35. #include "windows.h"
  36. #endif
  37. #include "spi_flash/include/spi_flash.h"
  38. #define DUMMY_REGISTER (0x1084)
  39. #define TIMEOUT (-1) /*MS*/
  40. //#define DISABLE_UNSED_FLASH_FUNCTIONS
  41. #define HOST_SHARE_MEM_BASE (0xd0000UL)
  42. #define CORTUS_SHARE_MEM_BASE (0x60000000UL)
  43. #define NMI_SPI_FLASH_ADDR (0x111c)
  44. /***********************************************************
  45. SPI Flash DMA
  46. ***********************************************************/
  47. #define GET_UINT32(X,Y) (X[0+Y] + ((uint32)X[1+Y]<<8) + ((uint32)X[2+Y]<<16) +((uint32)X[3+Y]<<24))
  48. #define SPI_FLASH_BASE (0x10200)
  49. #define SPI_FLASH_MODE (SPI_FLASH_BASE + 0x00)
  50. #define SPI_FLASH_CMD_CNT (SPI_FLASH_BASE + 0x04)
  51. #define SPI_FLASH_DATA_CNT (SPI_FLASH_BASE + 0x08)
  52. #define SPI_FLASH_BUF1 (SPI_FLASH_BASE + 0x0c)
  53. #define SPI_FLASH_BUF2 (SPI_FLASH_BASE + 0x10)
  54. #define SPI_FLASH_BUF_DIR (SPI_FLASH_BASE + 0x14)
  55. #define SPI_FLASH_TR_DONE (SPI_FLASH_BASE + 0x18)
  56. #define SPI_FLASH_DMA_ADDR (SPI_FLASH_BASE + 0x1c)
  57. #define SPI_FLASH_MSB_CTL (SPI_FLASH_BASE + 0x20)
  58. #define SPI_FLASH_TX_CTL (SPI_FLASH_BASE + 0x24)
  59. /*********************************************/
  60. /* STATIC FUNCTIONS */
  61. /*********************************************/
  62. /**
  63. * @fn spi_flash_read_status_reg
  64. * @brief Read status register
  65. * @param[OUT] val
  66. value of status reg
  67. * @return Status of execution
  68. * @note Compatible with MX25L6465E
  69. * @author M. Abdelmawla
  70. * @version 1.0
  71. */
  72. static sint8 spi_flash_read_status_reg(uint8 * val)
  73. {
  74. sint8 ret = M2M_SUCCESS;
  75. uint8 cmd[1];
  76. uint32 reg;
  77. cmd[0] = 0x05;
  78. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 4);
  79. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  80. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
  81. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, DUMMY_REGISTER);
  82. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7));
  83. do
  84. {
  85. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&reg);
  86. if(M2M_SUCCESS != ret) break;
  87. }
  88. while(reg != 1);
  89. reg = (M2M_SUCCESS == ret)?(nm_read_reg(DUMMY_REGISTER)):(0);
  90. *val = reg & 0xff;
  91. return ret;
  92. }
  93. #ifdef DISABLE_UNSED_FLASH_FUNCTIONS
  94. /**
  95. * @fn spi_flash_read_security_reg
  96. * @brief Read security register
  97. * @return Security register value
  98. * @note Compatible with MX25L6465E
  99. * @author M. Abdelmawla
  100. * @version 1.0
  101. */
  102. static uint8 spi_flash_read_security_reg(void)
  103. {
  104. uint8 cmd[1];
  105. uint32 reg;
  106. sint8 ret = M2M_SUCCESS;
  107. cmd[0] = 0x2b;
  108. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 1);
  109. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  110. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
  111. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, DUMMY_REGISTER);
  112. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7));
  113. do
  114. {
  115. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&reg);
  116. if(M2M_SUCCESS != ret) break;
  117. }
  118. while(reg != 1);
  119. reg = (M2M_SUCCESS == ret)?(nm_read_reg(DUMMY_REGISTER)):(0);
  120. return (sint8)reg & 0xff;
  121. }
  122. /**
  123. * @fn spi_flash_gang_unblock
  124. * @brief Unblock all flash area
  125. * @note Compatible with MX25L6465E
  126. * @author M. Abdelmawla
  127. * @version 1.0
  128. */
  129. static sint8 spi_flash_gang_unblock(void)
  130. {
  131. uint8 cmd[1];
  132. uint32 val = 0;
  133. sint8 ret = M2M_SUCCESS;
  134. cmd[0] = 0x98;
  135. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
  136. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  137. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
  138. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
  139. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7));
  140. do
  141. {
  142. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
  143. if(M2M_SUCCESS != ret) break;
  144. }
  145. while(val != 1);
  146. return ret;
  147. }
  148. /**
  149. * @fn spi_flash_clear_security_flags
  150. * @brief Clear all security flags
  151. * @note Compatible with MX25L6465E
  152. * @author M. Abdelmawla
  153. * @version 1.0
  154. */
  155. static sint8 spi_flash_clear_security_flags(void)
  156. {
  157. uint8 cmd[1];
  158. uint32 val = 0;
  159. sint8 ret = M2M_SUCCESS;
  160. cmd[0] = 0x30;
  161. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
  162. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  163. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
  164. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
  165. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7));
  166. do
  167. {
  168. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
  169. if(M2M_SUCCESS != ret) break;
  170. }
  171. while(val != 1);
  172. return ret;
  173. }
  174. #endif
  175. /**
  176. * @fn spi_flash_load_to_cortus_mem
  177. * @brief Load data from SPI flash into cortus memory
  178. * @param[IN] u32MemAdr
  179. * Cortus load address. It must be set to its AHB access address
  180. * @param[IN] u32FlashAdr
  181. * Address to read from at the SPI flash
  182. * @param[IN] u32Sz
  183. * Data size
  184. * @return Status of execution
  185. * @note Compatible with MX25L6465E and should be working with other types
  186. * @author M. Abdelmawla
  187. * @version 1.0
  188. */
  189. static sint8 spi_flash_load_to_cortus_mem(uint32 u32MemAdr, uint32 u32FlashAdr, uint32 u32Sz)
  190. {
  191. uint8 cmd[5];
  192. uint32 val = 0;
  193. sint8 ret = M2M_SUCCESS;
  194. cmd[0] = 0x0b;
  195. cmd[1] = (uint8)(u32FlashAdr >> 16);
  196. cmd[2] = (uint8)(u32FlashAdr >> 8);
  197. cmd[3] = (uint8)(u32FlashAdr);
  198. cmd[4] = 0xA5;
  199. ret += nm_write_reg(SPI_FLASH_DATA_CNT, u32Sz);
  200. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]|(cmd[1]<<8)|(cmd[2]<<16)|(cmd[3]<<24));
  201. ret += nm_write_reg(SPI_FLASH_BUF2, cmd[4]);
  202. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x1f);
  203. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, u32MemAdr);
  204. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 5 | (1<<7));
  205. do
  206. {
  207. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
  208. if(M2M_SUCCESS != ret) break;
  209. }
  210. while(val != 1);
  211. return ret;
  212. }
  213. /**
  214. * @fn spi_flash_sector_erase
  215. * @brief Erase sector (4KB)
  216. * @param[IN] u32FlashAdr
  217. * Any memory address within the sector
  218. * @return Status of execution
  219. * @note Compatible with MX25L6465E and should be working with other types
  220. * @author M. Abdelmawla
  221. * @version 1.0
  222. */
  223. static sint8 spi_flash_sector_erase(uint32 u32FlashAdr)
  224. {
  225. uint8 cmd[4];
  226. uint32 val = 0;
  227. sint8 ret = M2M_SUCCESS;
  228. cmd[0] = 0x20;
  229. cmd[1] = (uint8)(u32FlashAdr >> 16);
  230. cmd[2] = (uint8)(u32FlashAdr >> 8);
  231. cmd[3] = (uint8)(u32FlashAdr);
  232. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
  233. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]|(cmd[1]<<8)|(cmd[2]<<16)|(cmd[3]<<24));
  234. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x0f);
  235. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
  236. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 4 | (1<<7));
  237. do
  238. {
  239. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
  240. if(M2M_SUCCESS != ret) break;
  241. }
  242. while(val != 1);
  243. return ret;
  244. }
  245. /**
  246. * @fn spi_flash_write_enable
  247. * @brief Send write enable command to SPI flash
  248. * @return Status of execution
  249. * @note Compatible with MX25L6465E and should be working with other types
  250. * @author M. Abdelmawla
  251. * @version 1.0
  252. */
  253. static sint8 spi_flash_write_enable(void)
  254. {
  255. uint8 cmd[1];
  256. uint32 val = 0;
  257. sint8 ret = M2M_SUCCESS;
  258. cmd[0] = 0x06;
  259. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
  260. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  261. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
  262. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
  263. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7));
  264. do
  265. {
  266. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
  267. if(M2M_SUCCESS != ret) break;
  268. }
  269. while(val != 1);
  270. return ret;
  271. }
  272. /**
  273. * @fn spi_flash_write_disable
  274. * @brief Send write disable command to SPI flash
  275. * @note Compatible with MX25L6465E and should be working with other types
  276. * @author M. Abdelmawla
  277. * @version 1.0
  278. */
  279. static sint8 spi_flash_write_disable(void)
  280. {
  281. uint8 cmd[1];
  282. uint32 val = 0;
  283. sint8 ret = M2M_SUCCESS;
  284. cmd[0] = 0x04;
  285. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
  286. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  287. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
  288. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
  289. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7));
  290. do
  291. {
  292. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
  293. if(M2M_SUCCESS != ret) break;
  294. }
  295. while(val != 1);
  296. return ret;
  297. }
  298. /**
  299. * @fn spi_flash_page_program
  300. * @brief Write data (less than page size) from cortus memory to SPI flash
  301. * @param[IN] u32MemAdr
  302. * Cortus data address. It must be set to its AHB access address
  303. * @param[IN] u32FlashAdr
  304. * Address to write to at the SPI flash
  305. * @param[IN] u32Sz
  306. * Data size
  307. * @note Compatible with MX25L6465E and should be working with other types
  308. * @author M. Abdelmawla
  309. * @version 1.0
  310. */
  311. static sint8 spi_flash_page_program(uint32 u32MemAdr, uint32 u32FlashAdr, uint32 u32Sz)
  312. {
  313. uint8 cmd[4];
  314. uint32 val = 0;
  315. sint8 ret = M2M_SUCCESS;
  316. cmd[0] = 0x02;
  317. cmd[1] = (uint8)(u32FlashAdr >> 16);
  318. cmd[2] = (uint8)(u32FlashAdr >> 8);
  319. cmd[3] = (uint8)(u32FlashAdr);
  320. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
  321. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]|(cmd[1]<<8)|(cmd[2]<<16)|(cmd[3]<<24));
  322. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x0f);
  323. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, u32MemAdr);
  324. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 4 | (1<<7) | ((u32Sz & 0xfffff) << 8));
  325. do
  326. {
  327. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
  328. if(M2M_SUCCESS != ret) break;
  329. }
  330. while(val != 1);
  331. return ret;
  332. }
  333. /**
  334. * @fn spi_flash_read_internal
  335. * @brief Read from data from SPI flash
  336. * @param[OUT] pu8Buf
  337. * Pointer to data buffer
  338. * @param[IN] u32Addr
  339. * Address to read from at the SPI flash
  340. * @param[IN] u32Sz
  341. * Data size
  342. * @note Data size must be < 64KB (limitation imposed by the bus wrapper)
  343. * @author M. Abdelmawla
  344. * @version 1.0
  345. */
  346. static sint8 spi_flash_read_internal(uint8 *pu8Buf, uint32 u32Addr, uint32 u32Sz)
  347. {
  348. sint8 ret = M2M_SUCCESS;
  349. /* read size must be < 64KB */
  350. ret = spi_flash_load_to_cortus_mem(HOST_SHARE_MEM_BASE, u32Addr, u32Sz);
  351. if(M2M_SUCCESS != ret) goto ERR;
  352. ret = nm_read_block(HOST_SHARE_MEM_BASE, pu8Buf, u32Sz);
  353. ERR:
  354. return ret;
  355. }
  356. /**
  357. * @fn spi_flash_pp
  358. * @brief Program data of size less than a page (256 bytes) at the SPI flash
  359. * @param[IN] u32Offset
  360. * Address to write to at the SPI flash
  361. * @param[IN] pu8Buf
  362. * Pointer to data buffer
  363. * @param[IN] u32Sz
  364. * Data size
  365. * @return Status of execution
  366. * @author M. Abdelmawla
  367. * @version 1.0
  368. */
  369. static sint8 spi_flash_pp(uint32 u32Offset, uint8 *pu8Buf, uint16 u16Sz)
  370. {
  371. sint8 ret = M2M_SUCCESS;
  372. uint8 tmp;
  373. spi_flash_write_enable();
  374. /* use shared packet memory as temp mem */
  375. ret += nm_write_block(HOST_SHARE_MEM_BASE, pu8Buf, u16Sz);
  376. ret += spi_flash_page_program(HOST_SHARE_MEM_BASE, u32Offset, u16Sz);
  377. do
  378. {
  379. if(ret != M2M_SUCCESS) goto ERR;
  380. ret += spi_flash_read_status_reg(&tmp);
  381. }
  382. while(tmp & 0x01);
  383. ret += spi_flash_write_disable();
  384. ERR:
  385. return ret;
  386. }
  387. /**
  388. * @fn spi_flash_rdid
  389. * @brief Read SPI Flash ID
  390. * @return SPI FLash ID
  391. * @author M.S.M
  392. * @version 1.0
  393. */
  394. static uint32 spi_flash_rdid(void)
  395. {
  396. unsigned char cmd[1];
  397. uint32 reg = 0;
  398. uint32 cnt = 0;
  399. sint8 ret = M2M_SUCCESS;
  400. cmd[0] = 0x9f;
  401. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 4);
  402. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  403. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x1);
  404. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, DUMMY_REGISTER);
  405. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7));
  406. do
  407. {
  408. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&reg);
  409. if(M2M_SUCCESS != ret) break;
  410. if(++cnt > 500)
  411. {
  412. ret = M2M_ERR_INIT;
  413. break;
  414. }
  415. }
  416. while(reg != 1);
  417. reg = (M2M_SUCCESS == ret)?(nm_read_reg(DUMMY_REGISTER)):(0);
  418. M2M_PRINT("Flash ID %x \n",(unsigned int)reg);
  419. return reg;
  420. }
  421. /**
  422. * @fn spi_flash_unlock
  423. * @brief Unlock SPI Flash
  424. * @author M.S.M
  425. * @version 1.0
  426. */
  427. #if 0
  428. static void spi_flash_unlock(void)
  429. {
  430. uint8 tmp;
  431. tmp = spi_flash_read_security_reg();
  432. spi_flash_clear_security_flags();
  433. if(tmp & 0x80)
  434. {
  435. spi_flash_write_enable();
  436. spi_flash_gang_unblock();
  437. }
  438. }
  439. #endif
  440. /*********************************************/
  441. /* GLOBAL FUNCTIONS */
  442. /*********************************************/
  443. /**
  444. * @fn spi_flash_read
  445. * @brief Read from data from SPI flash
  446. * @param[OUT] pu8Buf
  447. * Pointer to data buffer
  448. * @param[IN] u32offset
  449. * Address to read from at the SPI flash
  450. * @param[IN] u32Sz
  451. * Data size
  452. * @return Status of execution
  453. * @note Data size is limited by the SPI flash size only
  454. * @author M. Abdelmawla
  455. * @version 1.0
  456. */
  457. sint8 spi_flash_read(uint8 *pu8Buf, uint32 u32offset, uint32 u32Sz)
  458. {
  459. sint8 ret = M2M_SUCCESS;
  460. if(u32Sz > FLASH_BLOCK_SIZE)
  461. {
  462. do
  463. {
  464. ret = spi_flash_read_internal(pu8Buf, u32offset, FLASH_BLOCK_SIZE);
  465. if(M2M_SUCCESS != ret) goto ERR;
  466. u32Sz -= FLASH_BLOCK_SIZE;
  467. u32offset += FLASH_BLOCK_SIZE;
  468. pu8Buf += FLASH_BLOCK_SIZE;
  469. } while(u32Sz > FLASH_BLOCK_SIZE);
  470. }
  471. ret = spi_flash_read_internal(pu8Buf, u32offset, u32Sz);
  472. ERR:
  473. return ret;
  474. }
  475. /**
  476. * @fn spi_flash_write
  477. * @brief Proram SPI flash
  478. * @param[IN] pu8Buf
  479. * Pointer to data buffer
  480. * @param[IN] u32Offset
  481. * Address to write to at the SPI flash
  482. * @param[IN] u32Sz
  483. * Data size
  484. * @return Status of execution
  485. * @author M. Abdelmawla
  486. * @version 1.0
  487. */
  488. sint8 spi_flash_write(uint8* pu8Buf, uint32 u32Offset, uint32 u32Sz)
  489. {
  490. #ifdef PROFILING
  491. unsigned long long t1 = 0;
  492. uint32 percent =0;
  493. uint32 tpercent =0;
  494. #endif
  495. sint8 ret = M2M_SUCCESS;
  496. uint32 u32wsz;
  497. uint32 u32off;
  498. uint32 u32Blksz;
  499. u32Blksz = FLASH_PAGE_SZ;
  500. u32off = u32Offset % u32Blksz;
  501. #ifdef PROFILING
  502. tpercent = (u32Sz/u32Blksz)+((u32Sz%u32Blksz)>0);
  503. t1 = GetTickCount64();
  504. M2M_PRINT(">Start programming...\r\n");
  505. #endif
  506. if(u32Sz<=0)
  507. {
  508. M2M_ERR("Data size = %d",(int)u32Sz);
  509. ret = M2M_ERR_FAIL;
  510. goto ERR;
  511. }
  512. if (u32off)/*first part of data in the address page*/
  513. {
  514. u32wsz = u32Blksz - u32off;
  515. if(spi_flash_pp(u32Offset, pu8Buf, (uint16)BSP_MIN(u32Sz, u32wsz))!=M2M_SUCCESS)
  516. {
  517. ret = M2M_ERR_FAIL;
  518. goto ERR;
  519. }
  520. if (u32Sz < u32wsz) goto EXIT;
  521. pu8Buf += u32wsz;
  522. u32Offset += u32wsz;
  523. u32Sz -= u32wsz;
  524. }
  525. while (u32Sz > 0)
  526. {
  527. u32wsz = BSP_MIN(u32Sz, u32Blksz);
  528. /*write complete page or the remaining data*/
  529. if(spi_flash_pp(u32Offset, pu8Buf, (uint16)u32wsz)!=M2M_SUCCESS)
  530. {
  531. ret = M2M_ERR_FAIL;
  532. goto ERR;
  533. }
  534. pu8Buf += u32wsz;
  535. u32Offset += u32wsz;
  536. u32Sz -= u32wsz;
  537. #ifdef PROFILING
  538. percent++;
  539. printf("\r>Complete Percentage = %d%%.\r",((percent*100)/tpercent));
  540. #endif
  541. }
  542. EXIT:
  543. #ifdef PROFILING
  544. M2M_PRINT("\rDone\t\t\t\t\t\t");
  545. M2M_PRINT("\n#Programming time = %f sec\n\r",(GetTickCount64() - t1)/1000.0);
  546. #endif
  547. ERR:
  548. return ret;
  549. }
  550. /**
  551. * @fn spi_flash_erase
  552. * @brief Erase from data from SPI flash
  553. * @param[IN] u32Offset
  554. * Address to write to at the SPI flash
  555. * @param[IN] u32Sz
  556. * Data size
  557. * @return Status of execution
  558. * @note Data size is limited by the SPI flash size only
  559. * @author M. Abdelmawla
  560. * @version 1.0
  561. */
  562. sint8 spi_flash_erase(uint32 u32Offset, uint32 u32Sz)
  563. {
  564. uint32 i = 0;
  565. sint8 ret = M2M_SUCCESS;
  566. uint8 tmp = 0;
  567. #ifdef PROFILING
  568. unsigned long long t;
  569. t = GetTickCount64();
  570. #endif
  571. M2M_DBG("\r\n>Start erasing...\r\n");
  572. for(i = u32Offset; i < (u32Sz +u32Offset); i += (16*FLASH_PAGE_SZ))
  573. {
  574. ret += spi_flash_write_enable();
  575. ret += spi_flash_read_status_reg(&tmp);
  576. ret += spi_flash_sector_erase(i);
  577. ret += spi_flash_read_status_reg(&tmp);
  578. do
  579. {
  580. if(ret != M2M_SUCCESS) goto ERR;
  581. ret += spi_flash_read_status_reg(&tmp);
  582. }while(tmp & 0x01);
  583. }
  584. M2M_DBG("Done\r\n");
  585. #ifdef PROFILING
  586. M2M_PRINT("#Erase time = %f sec\n", (GetTickCount64()-t)/1000.0);
  587. #endif
  588. ERR:
  589. return ret;
  590. }
  591. /**
  592. * @fn spi_flash_get_size
  593. * @brief Get size of SPI Flash
  594. * @return Size of Flash
  595. * @author M.S.M
  596. * @version 1.0
  597. */
  598. uint32 spi_flash_get_size(void)
  599. {
  600. uint32 u32FlashId = 0, u32FlashPwr = 0;
  601. static uint32 gu32InernalFlashSize= 0;
  602. if(!gu32InernalFlashSize)
  603. {
  604. u32FlashId = spi_flash_rdid();//spi_flash_probe();
  605. if(u32FlashId != 0xffffffff)
  606. {
  607. /*flash size is the third byte from the FLASH RDID*/
  608. u32FlashPwr = ((u32FlashId>>16)&0xff) - 0x11; /*2MBIT is the min*/
  609. /*That number power 2 to get the flash size*/
  610. gu32InernalFlashSize = 1<<u32FlashPwr;
  611. M2M_INFO("Flash Size %lu Mb\n",gu32InernalFlashSize);
  612. }
  613. else
  614. {
  615. M2M_ERR("Cann't Detect Flash size\n");
  616. }
  617. }
  618. return gu32InernalFlashSize;
  619. }