Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 

599 wiersze
18 KiB

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