sfud.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. /*
  2. * This file is part of the Serial Flash Universal Driver Library.
  3. *
  4. * Copyright (c) 2016-2018, Armink, <armink.ztl@gmail.com>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the
  8. * 'Software'), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sublicense, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  21. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  22. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  23. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24. *
  25. * Function: serial flash operate functions by SFUD lib.
  26. * Created on: 2016-04-23
  27. */
  28. #include "sfud.h"
  29. #include <string.h>
  30. /* send dummy data for read data */
  31. #define DUMMY_DATA 0xFF
  32. #ifndef SFUD_FLASH_DEVICE_TABLE
  33. #error "Please configure the flash device information table in (in sfud_cfg.h)."
  34. #endif
  35. /* user configured flash device information table */
  36. sfud_flash sfud_flash_tables[] = SFUD_FLASH_DEVICE_TABLE;
  37. /* supported manufacturer information table */
  38. static const sfud_mf mf_table[] = SFUD_MF_TABLE;
  39. #ifdef SFUD_USING_FLASH_INFO_TABLE
  40. /* supported flash chip information table */
  41. static const sfud_flash_chip flash_chip_table[] = SFUD_FLASH_CHIP_TABLE;
  42. #endif
  43. #ifdef SFUD_USING_QSPI
  44. /**
  45. * flash read data mode
  46. */
  47. enum sfud_qspi_read_mode {
  48. NORMAL_SPI_READ = 1 << 0, /**< mormal spi read mode */
  49. DUAL_OUTPUT = 1 << 1, /**< qspi fast read dual output */
  50. DUAL_IO = 1 << 2, /**< qspi fast read dual input/output */
  51. QUAD_OUTPUT = 1 << 3, /**< qspi fast read quad output */
  52. QUAD_IO = 1 << 4, /**< qspi fast read quad input/output */
  53. };
  54. /* QSPI flash chip's extended information table */
  55. static const sfud_qspi_flash_ext_info qspi_flash_ext_info_table[] = SFUD_FLASH_EXT_INFO_TABLE;
  56. #endif /* SFUD_USING_QSPI */
  57. static sfud_err software_init(const sfud_flash *flash);
  58. static sfud_err hardware_init(sfud_flash *flash);
  59. static sfud_err page256_or_1_byte_write(const sfud_flash *flash, uint32_t addr, size_t size, uint16_t write_gran,
  60. const uint8_t *data);
  61. static sfud_err aai_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data);
  62. static sfud_err wait_busy(const sfud_flash *flash, uint32_t long_delay_times);
  63. static sfud_err reset(const sfud_flash *flash);
  64. static sfud_err read_jedec_id(sfud_flash *flash);
  65. static sfud_err set_write_enabled(const sfud_flash *flash, bool enabled);
  66. static sfud_err set_4_byte_address_mode(sfud_flash *flash, bool enabled);
  67. static void make_address_byte_array(const sfud_flash *flash, uint32_t addr, uint8_t *array);
  68. /* ../port/sfup_port.c */
  69. extern void sfud_log_debug(const char *file, const long line, const char *format, ...);
  70. extern void sfud_log_info(const char *format, ...);
  71. /**
  72. * SFUD initialize by flash device
  73. *
  74. * @param flash flash device
  75. *
  76. * @return result
  77. */
  78. sfud_err sfud_device_init(sfud_flash *flash) {
  79. sfud_err result = SFUD_SUCCESS;
  80. /* hardware initialize */
  81. result = hardware_init(flash);
  82. if (result == SFUD_SUCCESS) {
  83. result = software_init(flash);
  84. }
  85. if (result == SFUD_SUCCESS) {
  86. flash->init_ok = true;
  87. SFUD_INFO("%s flash device initialized successfully.", flash->name);
  88. } else {
  89. flash->init_ok = false;
  90. SFUD_INFO("Error: %s flash device initialization failed.", flash->name);
  91. }
  92. return result;
  93. }
  94. /**
  95. * SFUD library initialize.
  96. *
  97. * @return result
  98. */
  99. sfud_err sfud_init(void) {
  100. sfud_err cur_flash_result = SFUD_SUCCESS, all_flash_result = SFUD_SUCCESS;
  101. size_t i;
  102. SFUD_DEBUG("Start initialize Serial Flash Universal Driver(SFUD) V%s.", SFUD_SW_VERSION);
  103. SFUD_DEBUG("You can get the latest version on https://github.com/armink/SFUD .");
  104. /* initialize all flash device in flash device table */
  105. for (i = 0; i < sizeof(sfud_flash_tables) / sizeof(sfud_flash); i++) {
  106. /* initialize flash device index of flash device information table */
  107. sfud_flash_tables[i].index = i;
  108. cur_flash_result = sfud_device_init(&sfud_flash_tables[i]);
  109. if (cur_flash_result != SFUD_SUCCESS) {
  110. all_flash_result = cur_flash_result;
  111. }
  112. }
  113. return all_flash_result;
  114. }
  115. /**
  116. * get flash device by its index which in the flash information table
  117. *
  118. * @param index the index which in the flash information table @see flash_table
  119. *
  120. * @return flash device
  121. */
  122. sfud_flash *sfud_get_device(size_t index) {
  123. if (index < sfud_get_device_num()) {
  124. return &sfud_flash_tables[index];
  125. } else {
  126. return NULL;
  127. }
  128. }
  129. /**
  130. * get flash device total number on flash device information table @see flash_table
  131. *
  132. * @return flash device total number
  133. */
  134. size_t sfud_get_device_num(void) {
  135. return sizeof(sfud_flash_tables) / sizeof(sfud_flash);
  136. }
  137. /**
  138. * get flash device information table @see flash_table
  139. *
  140. * @return flash device table pointer
  141. */
  142. const sfud_flash *sfud_get_device_table(void) {
  143. return sfud_flash_tables;
  144. }
  145. #ifdef SFUD_USING_QSPI
  146. static void qspi_set_read_cmd_format(sfud_flash *flash, uint8_t ins, uint8_t ins_lines, uint8_t addr_lines,
  147. uint8_t dummy_cycles, uint8_t data_lines) {
  148. /* if medium size greater than 16Mb, use 4-Byte address, instruction should be added one */
  149. if (flash->chip.capacity <= 0x1000000) {
  150. flash->read_cmd_format.instruction = ins;
  151. flash->read_cmd_format.address_size = 24;
  152. } else {
  153. if(ins == SFUD_CMD_READ_DATA){
  154. flash->read_cmd_format.instruction = ins + 0x10;
  155. }
  156. else{
  157. flash->read_cmd_format.instruction = ins + 1;
  158. }
  159. flash->read_cmd_format.address_size = 32;
  160. }
  161. flash->read_cmd_format.instruction_lines = ins_lines;
  162. flash->read_cmd_format.address_lines = addr_lines;
  163. flash->read_cmd_format.alternate_bytes_lines = 0;
  164. flash->read_cmd_format.dummy_cycles = dummy_cycles;
  165. flash->read_cmd_format.data_lines = data_lines;
  166. }
  167. /**
  168. * Enbale the fast read mode in QSPI flash mode. Default read mode is normal SPI mode.
  169. *
  170. * it will find the appropriate fast-read instruction to replace the read instruction(0x03)
  171. * fast-read instruction @see SFUD_FLASH_EXT_INFO_TABLE
  172. *
  173. * @note When Flash is in QSPI mode, the method must be called after sfud_device_init().
  174. *
  175. * @param flash flash device
  176. * @param data_line_width the data lines max width which QSPI bus supported, such as 1, 2, 4
  177. *
  178. * @return result
  179. */
  180. sfud_err sfud_qspi_fast_read_enable(sfud_flash *flash, uint8_t data_line_width) {
  181. size_t i = 0;
  182. uint8_t read_mode = NORMAL_SPI_READ;
  183. sfud_err result = SFUD_SUCCESS;
  184. SFUD_ASSERT(flash);
  185. SFUD_ASSERT(data_line_width == 1 || data_line_width == 2 || data_line_width == 4);
  186. /* get read_mode, If don't found, the default is SFUD_QSPI_NORMAL_SPI_READ */
  187. for (i = 0; i < sizeof(qspi_flash_ext_info_table) / sizeof(sfud_qspi_flash_ext_info); i++) {
  188. if ((qspi_flash_ext_info_table[i].mf_id == flash->chip.mf_id)
  189. && (qspi_flash_ext_info_table[i].type_id == flash->chip.type_id)
  190. && (qspi_flash_ext_info_table[i].capacity_id == flash->chip.capacity_id)) {
  191. read_mode = qspi_flash_ext_info_table[i].read_mode;
  192. }
  193. }
  194. /* determine qspi supports which read mode and set read_cmd_format struct */
  195. switch (data_line_width) {
  196. case 1:
  197. qspi_set_read_cmd_format(flash, SFUD_CMD_READ_DATA, 1, 1, 0, 1);
  198. break;
  199. case 2:
  200. if (read_mode & DUAL_IO) {
  201. qspi_set_read_cmd_format(flash, SFUD_CMD_DUAL_IO_READ_DATA, 1, 2, 4, 2);
  202. } else if (read_mode & DUAL_OUTPUT) {
  203. qspi_set_read_cmd_format(flash, SFUD_CMD_DUAL_OUTPUT_READ_DATA, 1, 1, 8, 2);
  204. } else {
  205. qspi_set_read_cmd_format(flash, SFUD_CMD_READ_DATA, 1, 1, 0, 1);
  206. }
  207. break;
  208. case 4:
  209. if (read_mode & QUAD_IO) {
  210. qspi_set_read_cmd_format(flash, SFUD_CMD_QUAD_IO_READ_DATA, 1, 4, 6, 4);
  211. } else if (read_mode & QUAD_OUTPUT) {
  212. qspi_set_read_cmd_format(flash, SFUD_CMD_QUAD_OUTPUT_READ_DATA, 1, 1, 8, 4);
  213. } else {
  214. qspi_set_read_cmd_format(flash, SFUD_CMD_READ_DATA, 1, 1, 0, 1);
  215. }
  216. break;
  217. }
  218. return result;
  219. }
  220. #endif /* SFUD_USING_QSPI */
  221. /**
  222. * hardware initialize
  223. */
  224. static sfud_err hardware_init(sfud_flash *flash) {
  225. extern sfud_err sfud_spi_port_init(sfud_flash * flash);
  226. sfud_err result = SFUD_SUCCESS;
  227. size_t i;
  228. SFUD_ASSERT(flash);
  229. result = sfud_spi_port_init(flash);
  230. if (result != SFUD_SUCCESS) {
  231. return result;
  232. }
  233. #ifdef SFUD_USING_QSPI
  234. /* set default read instruction */
  235. flash->read_cmd_format.instruction = SFUD_CMD_READ_DATA;
  236. #endif /* SFUD_USING_QSPI */
  237. /* SPI write read function must be initialize */
  238. SFUD_ASSERT(flash->spi.wr);
  239. /* if the user don't configure flash chip information then using SFDP parameter or static flash parameter table */
  240. if (flash->chip.capacity == 0 || flash->chip.write_mode == 0 || flash->chip.erase_gran == 0
  241. || flash->chip.erase_gran_cmd == 0) {
  242. /* read JEDEC ID include manufacturer ID, memory type ID and flash capacity ID */
  243. result = read_jedec_id(flash);
  244. if (result != SFUD_SUCCESS) {
  245. return result;
  246. }
  247. #ifdef SFUD_USING_SFDP
  248. extern bool sfud_read_sfdp(sfud_flash *flash);
  249. /* read SFDP parameters */
  250. if (sfud_read_sfdp(flash)) {
  251. flash->chip.name = NULL;
  252. flash->chip.capacity = flash->sfdp.capacity;
  253. /* only 1 byte or 256 bytes write mode for SFDP */
  254. if (flash->sfdp.write_gran == 1) {
  255. flash->chip.write_mode = SFUD_WM_BYTE;
  256. } else {
  257. flash->chip.write_mode = SFUD_WM_PAGE_256B;
  258. }
  259. /* find the the smallest erase sector size for eraser. then will use this size for erase granularity */
  260. flash->chip.erase_gran = flash->sfdp.eraser[0].size;
  261. flash->chip.erase_gran_cmd = flash->sfdp.eraser[0].cmd;
  262. for (i = 1; i < SFUD_SFDP_ERASE_TYPE_MAX_NUM; i++) {
  263. if (flash->sfdp.eraser[i].size != 0 && flash->chip.erase_gran > flash->sfdp.eraser[i].size) {
  264. flash->chip.erase_gran = flash->sfdp.eraser[i].size;
  265. flash->chip.erase_gran_cmd = flash->sfdp.eraser[i].cmd;
  266. }
  267. }
  268. } else {
  269. #endif
  270. #ifdef SFUD_USING_FLASH_INFO_TABLE
  271. /* read SFDP parameters failed then using SFUD library provided static parameter */
  272. for (i = 0; i < sizeof(flash_chip_table) / sizeof(sfud_flash_chip); i++) {
  273. if ((flash_chip_table[i].mf_id == flash->chip.mf_id)
  274. && (flash_chip_table[i].type_id == flash->chip.type_id)
  275. && (flash_chip_table[i].capacity_id == flash->chip.capacity_id)) {
  276. flash->chip.name = flash_chip_table[i].name;
  277. flash->chip.capacity = flash_chip_table[i].capacity;
  278. flash->chip.write_mode = flash_chip_table[i].write_mode;
  279. flash->chip.erase_gran = flash_chip_table[i].erase_gran;
  280. flash->chip.erase_gran_cmd = flash_chip_table[i].erase_gran_cmd;
  281. break;
  282. }
  283. }
  284. #endif
  285. #ifdef SFUD_USING_SFDP
  286. }
  287. #endif
  288. }
  289. if (flash->chip.capacity == 0 || flash->chip.write_mode == 0 || flash->chip.erase_gran == 0
  290. || flash->chip.erase_gran_cmd == 0) {
  291. SFUD_INFO("Warning: This flash device is not found or not supported.");
  292. return SFUD_ERR_NOT_FOUND;
  293. } else {
  294. const char *flash_mf_name = NULL;
  295. /* find the manufacturer information */
  296. for (i = 0; i < sizeof(mf_table) / sizeof(sfud_mf); i++) {
  297. if (mf_table[i].id == flash->chip.mf_id) {
  298. flash_mf_name = mf_table[i].name;
  299. break;
  300. }
  301. }
  302. /* print manufacturer and flash chip name */
  303. if (flash_mf_name && flash->chip.name) {
  304. SFUD_INFO("Found a %s %s flash chip. Size is %ld bytes.", flash_mf_name, flash->chip.name,
  305. flash->chip.capacity);
  306. } else if (flash_mf_name) {
  307. SFUD_INFO("Found a %s flash chip. Size is %ld bytes.", flash_mf_name, flash->chip.capacity);
  308. } else {
  309. SFUD_INFO("Found a flash chip. Size is %ld bytes.", flash->chip.capacity);
  310. }
  311. }
  312. /* reset flash device */
  313. result = reset(flash);
  314. if (result != SFUD_SUCCESS) {
  315. return result;
  316. }
  317. /* The flash all blocks is protected,so need change the flash status to unprotected before write and erase operate. */
  318. if (flash->chip.write_mode & SFUD_WM_AAI) {
  319. result = sfud_write_status(flash, true, 0x00);
  320. } else {
  321. /* MX25L3206E */
  322. if ((0xC2 == flash->chip.mf_id) && (0x20 == flash->chip.type_id) && (0x16 == flash->chip.capacity_id)) {
  323. result = sfud_write_status(flash, false, 0x00);
  324. }
  325. }
  326. if (result != SFUD_SUCCESS) {
  327. return result;
  328. }
  329. /* if the flash is large than 16MB (256Mb) then enter in 4-Byte addressing mode */
  330. if (flash->chip.capacity > (1L << 24)) {
  331. result = set_4_byte_address_mode(flash, true);
  332. } else {
  333. flash->addr_in_4_byte = false;
  334. }
  335. return result;
  336. }
  337. /**
  338. * software initialize
  339. *
  340. * @param flash flash device
  341. *
  342. * @return result
  343. */
  344. static sfud_err software_init(const sfud_flash *flash) {
  345. sfud_err result = SFUD_SUCCESS;
  346. SFUD_ASSERT(flash);
  347. return result;
  348. }
  349. /**
  350. * read flash data
  351. *
  352. * @param flash flash device
  353. * @param addr start address
  354. * @param size read size
  355. * @param data read data pointer
  356. *
  357. * @return result
  358. */
  359. sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t *data) {
  360. sfud_err result = SFUD_SUCCESS;
  361. const sfud_spi *spi = &flash->spi;
  362. uint8_t cmd_data[5 + SFUD_READ_DUMMY_BYTE_CNT];
  363. uint8_t cmd_size;
  364. SFUD_ASSERT(flash);
  365. SFUD_ASSERT(data);
  366. /* must be call this function after initialize OK */
  367. SFUD_ASSERT(flash->init_ok);
  368. /* check the flash address bound */
  369. if (addr + size > flash->chip.capacity) {
  370. SFUD_INFO("Error: Flash address is out of bound.");
  371. return SFUD_ERR_ADDR_OUT_OF_BOUND;
  372. }
  373. /* lock SPI */
  374. if (spi->lock) {
  375. spi->lock(spi);
  376. }
  377. result = wait_busy(flash, 0);
  378. if (result == SFUD_SUCCESS) {
  379. #ifdef SFUD_USING_QSPI
  380. if (flash->read_cmd_format.instruction != SFUD_CMD_READ_DATA) {
  381. result = spi->qspi_read(spi, addr, (sfud_qspi_read_cmd_format *)&flash->read_cmd_format, data, size);
  382. } else
  383. #endif
  384. {
  385. #ifdef SFUD_USING_FAST_READ
  386. cmd_data[0] = SFUD_CMD_FAST_READ_DATA;
  387. #else
  388. cmd_data[0] = SFUD_CMD_READ_DATA;
  389. #endif
  390. make_address_byte_array(flash, addr, &cmd_data[1]);
  391. cmd_size = flash->addr_in_4_byte ? 5 : 4;
  392. #if SFUD_READ_DUMMY_BYTE_CNT > 0
  393. for (uint8_t i = 0; i < SFUD_READ_DUMMY_BYTE_CNT; i++) {
  394. cmd_data[cmd_size] = SFUD_DUMMY_DATA;
  395. cmd_size++;
  396. }
  397. #endif
  398. result = spi->wr(spi, cmd_data, cmd_size, data, size);
  399. }
  400. }
  401. /* unlock SPI */
  402. if (spi->unlock) {
  403. spi->unlock(spi);
  404. }
  405. return result;
  406. }
  407. /**
  408. * erase all flash data
  409. *
  410. * @param flash flash device
  411. *
  412. * @return result
  413. */
  414. sfud_err sfud_chip_erase(const sfud_flash *flash) {
  415. sfud_err result = SFUD_SUCCESS;
  416. const sfud_spi *spi = &flash->spi;
  417. uint8_t cmd_data[4];
  418. SFUD_ASSERT(flash);
  419. /* must be call this function after initialize OK */
  420. SFUD_ASSERT(flash->init_ok);
  421. /* lock SPI */
  422. if (spi->lock) {
  423. spi->lock(spi);
  424. }
  425. /* set the flash write enable */
  426. result = set_write_enabled(flash, true);
  427. if (result != SFUD_SUCCESS) {
  428. goto __exit;
  429. }
  430. cmd_data[0] = SFUD_CMD_ERASE_CHIP;
  431. /* dual-buffer write, like AT45DB series flash chip erase operate is different for other flash */
  432. if (flash->chip.write_mode & SFUD_WM_DUAL_BUFFER) {
  433. cmd_data[1] = 0x94;
  434. cmd_data[2] = 0x80;
  435. cmd_data[3] = 0x9A;
  436. result = spi->wr(spi, cmd_data, 4, NULL, 0);
  437. } else {
  438. result = spi->wr(spi, cmd_data, 1, NULL, 0);
  439. }
  440. if (result != SFUD_SUCCESS) {
  441. SFUD_INFO("Error: Flash chip erase SPI communicate error.");
  442. goto __exit;
  443. }
  444. result = wait_busy(flash, 2000); //全片擦除最多给20秒
  445. __exit:
  446. /* set the flash write disable */
  447. set_write_enabled(flash, false);
  448. /* unlock SPI */
  449. if (spi->unlock) {
  450. spi->unlock(spi);
  451. }
  452. return result;
  453. }
  454. /**
  455. * erase flash data
  456. *
  457. * @note It will erase align by erase granularity.
  458. *
  459. * @param flash flash device
  460. * @param addr start address
  461. * @param size erase size
  462. *
  463. * @return result
  464. */
  465. sfud_err sfud_erase(const sfud_flash *flash, uint32_t addr, size_t size) {
  466. extern size_t sfud_sfdp_get_suitable_eraser(const sfud_flash *flash, uint32_t addr, size_t erase_size);
  467. sfud_err result = SFUD_SUCCESS;
  468. const sfud_spi *spi = &flash->spi;
  469. uint8_t cmd_data[5], cmd_size, cur_erase_cmd;
  470. size_t cur_erase_size;
  471. SFUD_ASSERT(flash);
  472. /* must be call this function after initialize OK */
  473. SFUD_ASSERT(flash->init_ok);
  474. /* check the flash address bound */
  475. if (addr + size > flash->chip.capacity) {
  476. SFUD_INFO("Error: Flash address is out of bound.");
  477. return SFUD_ERR_ADDR_OUT_OF_BOUND;
  478. }
  479. if (addr == 0 && size == flash->chip.capacity) {
  480. return sfud_chip_erase(flash);
  481. }
  482. /* lock SPI */
  483. if (spi->lock) {
  484. spi->lock(spi);
  485. }
  486. /* loop erase operate. erase unit is erase granularity */
  487. while (size) {
  488. /* if this flash is support SFDP parameter, then used SFDP parameter supplies eraser */
  489. #ifdef SFUD_USING_SFDP
  490. size_t eraser_index;
  491. if (flash->sfdp.available) {
  492. /* get the suitable eraser for erase process from SFDP parameter */
  493. eraser_index = sfud_sfdp_get_suitable_eraser(flash, addr, size);
  494. cur_erase_cmd = flash->sfdp.eraser[eraser_index].cmd;
  495. cur_erase_size = flash->sfdp.eraser[eraser_index].size;
  496. } else {
  497. #else
  498. {
  499. #endif
  500. cur_erase_cmd = flash->chip.erase_gran_cmd;
  501. cur_erase_size = flash->chip.erase_gran;
  502. }
  503. /* set the flash write enable */
  504. result = set_write_enabled(flash, true);
  505. if (result != SFUD_SUCCESS) {
  506. goto __exit;
  507. }
  508. cmd_data[0] = cur_erase_cmd;
  509. make_address_byte_array(flash, addr, &cmd_data[1]);
  510. cmd_size = flash->addr_in_4_byte ? 5 : 4;
  511. result = spi->wr(spi, cmd_data, cmd_size, NULL, 0);
  512. if (result != SFUD_SUCCESS) {
  513. SFUD_INFO("Error: Flash erase SPI communicate error.");
  514. goto __exit;
  515. }
  516. result = wait_busy(flash, 100); //擦除最多给1秒
  517. if (result != SFUD_SUCCESS) {
  518. goto __exit;
  519. }
  520. /* make erase align and calculate next erase address */
  521. if (addr % cur_erase_size != 0) {
  522. if (size > cur_erase_size - (addr % cur_erase_size)) {
  523. size -= cur_erase_size - (addr % cur_erase_size);
  524. addr += cur_erase_size - (addr % cur_erase_size);
  525. } else {
  526. goto __exit;
  527. }
  528. } else {
  529. if (size > cur_erase_size) {
  530. size -= cur_erase_size;
  531. addr += cur_erase_size;
  532. } else {
  533. goto __exit;
  534. }
  535. }
  536. }
  537. __exit:
  538. /* set the flash write disable */
  539. set_write_enabled(flash, false);
  540. /* unlock SPI */
  541. if (spi->unlock) {
  542. spi->unlock(spi);
  543. }
  544. return result;
  545. }
  546. /**
  547. * write flash data (no erase operate) for write 1 to 256 bytes per page mode or byte write mode
  548. *
  549. * @param flash flash device
  550. * @param addr start address
  551. * @param size write size
  552. * @param write_gran write granularity bytes, only support 1 or 256
  553. * @param data write data
  554. *
  555. * @return result
  556. */
  557. static sfud_err page256_or_1_byte_write(const sfud_flash *flash, uint32_t addr, size_t size, uint16_t write_gran,
  558. const uint8_t *data) {
  559. sfud_err result = SFUD_SUCCESS;
  560. const sfud_spi *spi = &flash->spi;
  561. static uint8_t cmd_data[5 + SFUD_WRITE_MAX_PAGE_SIZE];
  562. uint8_t cmd_size;
  563. size_t data_size;
  564. SFUD_ASSERT(flash);
  565. /* only support 1 or 256 */
  566. SFUD_ASSERT(write_gran == 1 || write_gran == 256);
  567. /* must be call this function after initialize OK */
  568. SFUD_ASSERT(flash->init_ok);
  569. /* check the flash address bound */
  570. if (addr + size > flash->chip.capacity) {
  571. SFUD_INFO("Error: Flash address is out of bound.");
  572. return SFUD_ERR_ADDR_OUT_OF_BOUND;
  573. }
  574. /* lock SPI */
  575. if (spi->lock) {
  576. spi->lock(spi);
  577. }
  578. /* loop write operate. write unit is write granularity */
  579. while (size) {
  580. /* set the flash write enable */
  581. result = set_write_enabled(flash, true);
  582. if (result != SFUD_SUCCESS) {
  583. goto __exit;
  584. }
  585. cmd_data[0] = SFUD_CMD_PAGE_PROGRAM;
  586. make_address_byte_array(flash, addr, &cmd_data[1]);
  587. cmd_size = flash->addr_in_4_byte ? 5 : 4;
  588. /* make write align and calculate next write address */
  589. if (addr % write_gran != 0) {
  590. if (size > write_gran - (addr % write_gran)) {
  591. data_size = write_gran - (addr % write_gran);
  592. } else {
  593. data_size = size;
  594. }
  595. } else {
  596. if (size > write_gran) {
  597. data_size = write_gran;
  598. } else {
  599. data_size = size;
  600. }
  601. }
  602. size -= data_size;
  603. addr += data_size;
  604. memcpy(&cmd_data[cmd_size], data, data_size);
  605. result = spi->wr(spi, cmd_data, cmd_size + data_size, NULL, 0);
  606. if (result != SFUD_SUCCESS) {
  607. SFUD_INFO("Error: Flash write SPI communicate error.");
  608. goto __exit;
  609. }
  610. result = wait_busy(flash, 0);
  611. if (result != SFUD_SUCCESS) {
  612. goto __exit;
  613. }
  614. data += data_size;
  615. }
  616. __exit:
  617. /* set the flash write disable */
  618. set_write_enabled(flash, false);
  619. /* unlock SPI */
  620. if (spi->unlock) {
  621. spi->unlock(spi);
  622. }
  623. return result;
  624. }
  625. /**
  626. * write flash data (no erase operate) for auto address increment mode
  627. *
  628. * If the address is odd number, it will place one 0xFF before the start of data for protect the old data.
  629. * If the latest remain size is 1, it will append one 0xFF at the end of data for protect the old data.
  630. *
  631. * @param flash flash device
  632. * @param addr start address
  633. * @param size write size
  634. * @param data write data
  635. *
  636. * @return result
  637. */
  638. static sfud_err aai_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data) {
  639. sfud_err result = SFUD_SUCCESS;
  640. const sfud_spi *spi = &flash->spi;
  641. uint8_t cmd_data[8], cmd_size;
  642. bool first_write = true;
  643. SFUD_ASSERT(flash);
  644. SFUD_ASSERT(flash->init_ok);
  645. /* check the flash address bound */
  646. if (addr + size > flash->chip.capacity) {
  647. SFUD_INFO("Error: Flash address is out of bound.");
  648. return SFUD_ERR_ADDR_OUT_OF_BOUND;
  649. }
  650. /* lock SPI */
  651. if (spi->lock) {
  652. spi->lock(spi);
  653. }
  654. /* The address must be even for AAI write mode. So it must write one byte first when address is odd. */
  655. if (addr % 2 != 0) {
  656. result = page256_or_1_byte_write(flash, addr++, 1, 1, data++);
  657. if (result != SFUD_SUCCESS) {
  658. goto __exit;
  659. }
  660. size--;
  661. }
  662. /* set the flash write enable */
  663. result = set_write_enabled(flash, true);
  664. if (result != SFUD_SUCCESS) {
  665. goto __exit;
  666. }
  667. /* loop write operate. */
  668. cmd_data[0] = SFUD_CMD_AAI_WORD_PROGRAM;
  669. while (size >= 2) {
  670. if (first_write) {
  671. make_address_byte_array(flash, addr, &cmd_data[1]);
  672. cmd_size = flash->addr_in_4_byte ? 5 : 4;
  673. cmd_data[cmd_size] = *data;
  674. cmd_data[cmd_size + 1] = *(data + 1);
  675. first_write = false;
  676. } else {
  677. cmd_size = 1;
  678. cmd_data[1] = *data;
  679. cmd_data[2] = *(data + 1);
  680. }
  681. result = spi->wr(spi, cmd_data, cmd_size + 2, NULL, 0);
  682. if (result != SFUD_SUCCESS) {
  683. SFUD_INFO("Error: Flash write SPI communicate error.");
  684. goto __exit;
  685. }
  686. result = wait_busy(flash, 100);
  687. if (result != SFUD_SUCCESS) {
  688. goto __exit;
  689. }
  690. size -= 2;
  691. addr += 2;
  692. data += 2;
  693. }
  694. /* set the flash write disable for exit AAI mode */
  695. result = set_write_enabled(flash, false);
  696. /* write last one byte data when origin write size is odd */
  697. if (result == SFUD_SUCCESS && size == 1) {
  698. result = page256_or_1_byte_write(flash, addr, 1, 1, data);
  699. }
  700. __exit:
  701. if (result != SFUD_SUCCESS) {
  702. set_write_enabled(flash, false);
  703. }
  704. /* unlock SPI */
  705. if (spi->unlock) {
  706. spi->unlock(spi);
  707. }
  708. return result;
  709. }
  710. /**
  711. * write flash data (no erase operate)
  712. *
  713. * @param flash flash device
  714. * @param addr start address
  715. * @param size write size
  716. * @param data write data
  717. *
  718. * @return result
  719. */
  720. sfud_err sfud_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data) {
  721. sfud_err result = SFUD_SUCCESS;
  722. if (flash->chip.write_mode & SFUD_WM_PAGE_256B) {
  723. result = page256_or_1_byte_write(flash, addr, size, 256, data);
  724. } else if (flash->chip.write_mode & SFUD_WM_AAI) {
  725. result = aai_write(flash, addr, size, data);
  726. } else if (flash->chip.write_mode & SFUD_WM_DUAL_BUFFER) {
  727. //TODO dual-buffer write mode
  728. }
  729. return result;
  730. }
  731. /**
  732. * erase and write flash data
  733. *
  734. * @param flash flash device
  735. * @param addr start address
  736. * @param size write size
  737. * @param data write data
  738. *
  739. * @return result
  740. */
  741. sfud_err sfud_erase_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data) {
  742. sfud_err result = SFUD_SUCCESS;
  743. result = sfud_erase(flash, addr, size);
  744. if (result == SFUD_SUCCESS) {
  745. result = sfud_write(flash, addr, size, data);
  746. }
  747. return result;
  748. }
  749. static sfud_err reset(const sfud_flash *flash) {
  750. sfud_err result = SFUD_SUCCESS;
  751. const sfud_spi *spi = &flash->spi;
  752. uint8_t cmd_data[2];
  753. SFUD_ASSERT(flash);
  754. cmd_data[0] = SFUD_CMD_ENABLE_RESET;
  755. result = spi->wr(spi, cmd_data, 1, NULL, 0);
  756. if (result == SFUD_SUCCESS) {
  757. result = wait_busy(flash, 20); //初始化最多给200ms
  758. } else {
  759. SFUD_INFO("Error: Flash device reset failed.");
  760. return result;
  761. }
  762. cmd_data[1] = SFUD_CMD_RESET;
  763. result = spi->wr(spi, &cmd_data[1], 1, NULL, 0);
  764. if (result == SFUD_SUCCESS) {
  765. result = wait_busy(flash, 20); //初始化最多给200ms
  766. }
  767. if (result == SFUD_SUCCESS) {
  768. SFUD_DEBUG("Flash device reset success.");
  769. } else {
  770. SFUD_INFO("Error: Flash device reset failed.");
  771. }
  772. return result;
  773. }
  774. static sfud_err read_jedec_id(sfud_flash *flash) {
  775. sfud_err result = SFUD_SUCCESS;
  776. const sfud_spi *spi = &flash->spi;
  777. uint8_t cmd_data[1], recv_data[3];
  778. SFUD_ASSERT(flash);
  779. cmd_data[0] = SFUD_CMD_JEDEC_ID;
  780. result = spi->wr(spi, cmd_data, sizeof(cmd_data), recv_data, sizeof(recv_data));
  781. if (result == SFUD_SUCCESS) {
  782. flash->chip.mf_id = recv_data[0];
  783. flash->chip.type_id = recv_data[1];
  784. flash->chip.capacity_id = recv_data[2];
  785. SFUD_DEBUG("The flash device manufacturer ID is 0x%02X, memory type ID is 0x%02X, capacity ID is 0x%02X.",
  786. flash->chip.mf_id, flash->chip.type_id, flash->chip.capacity_id);
  787. } else {
  788. SFUD_INFO("Error: Read flash device JEDEC ID error.");
  789. }
  790. return result;
  791. }
  792. /**
  793. * set the flash write enable or write disable
  794. *
  795. * @param flash flash device
  796. * @param enabled true: enable false: disable
  797. *
  798. * @return result
  799. */
  800. static sfud_err set_write_enabled(const sfud_flash *flash, bool enabled) {
  801. sfud_err result = SFUD_SUCCESS;
  802. uint8_t cmd, register_status;
  803. SFUD_ASSERT(flash);
  804. if (enabled) {
  805. cmd = SFUD_CMD_WRITE_ENABLE;
  806. } else {
  807. cmd = SFUD_CMD_WRITE_DISABLE;
  808. }
  809. result = flash->spi.wr(&flash->spi, &cmd, 1, NULL, 0);
  810. if (result == SFUD_SUCCESS) {
  811. result = sfud_read_status(flash, &register_status);
  812. }
  813. if (result == SFUD_SUCCESS) {
  814. if (enabled && (register_status & SFUD_STATUS_REGISTER_WEL) == 0) {
  815. SFUD_INFO("Error: Can't enable write status.");
  816. return SFUD_ERR_WRITE;
  817. } else if (!enabled && (register_status & SFUD_STATUS_REGISTER_WEL) != 0) {
  818. SFUD_INFO("Error: Can't disable write status.");
  819. return SFUD_ERR_WRITE;
  820. }
  821. }
  822. return result;
  823. }
  824. /**
  825. * enable or disable 4-Byte addressing for flash
  826. *
  827. * @note The 4-Byte addressing just supported for the flash capacity which is large then 16MB (256Mb).
  828. *
  829. * @param flash flash device
  830. * @param enabled true: enable false: disable
  831. *
  832. * @return result
  833. */
  834. static sfud_err set_4_byte_address_mode(sfud_flash *flash, bool enabled) {
  835. sfud_err result = SFUD_SUCCESS;
  836. uint8_t cmd;
  837. SFUD_ASSERT(flash);
  838. /* set the flash write enable */
  839. result = set_write_enabled(flash, true);
  840. if (result != SFUD_SUCCESS) {
  841. return result;
  842. }
  843. if (enabled) {
  844. cmd = SFUD_CMD_ENTER_4B_ADDRESS_MODE;
  845. } else {
  846. cmd = SFUD_CMD_EXIT_4B_ADDRESS_MODE;
  847. }
  848. result = flash->spi.wr(&flash->spi, &cmd, 1, NULL, 0);
  849. if (result == SFUD_SUCCESS) {
  850. flash->addr_in_4_byte = enabled ? true : false;
  851. SFUD_DEBUG("%s 4-Byte addressing mode success.", enabled ? "Enter" : "Exit");
  852. } else {
  853. SFUD_INFO("Error: %s 4-Byte addressing mode failed.", enabled ? "Enter" : "Exit");
  854. }
  855. return result;
  856. }
  857. /**
  858. * read flash register status
  859. *
  860. * @param flash flash device
  861. * @param status register status
  862. *
  863. * @return result
  864. */
  865. sfud_err sfud_read_status(const sfud_flash *flash, uint8_t *status) {
  866. uint8_t cmd = SFUD_CMD_READ_STATUS_REGISTER;
  867. SFUD_ASSERT(flash);
  868. SFUD_ASSERT(status);
  869. return flash->spi.wr(&flash->spi, &cmd, 1, status, 1);
  870. }
  871. static sfud_err wait_busy(const sfud_flash *flash, uint32_t long_delay_times) {
  872. sfud_err result = SFUD_SUCCESS;
  873. uint8_t status;
  874. size_t retry_times;
  875. void (*__delay_temp)(void);
  876. if (long_delay_times)
  877. {
  878. retry_times = long_delay_times;
  879. __delay_temp = flash->retry.long_delay;
  880. }
  881. else
  882. {
  883. retry_times = flash->retry.times;
  884. __delay_temp = flash->retry.delay;
  885. }
  886. SFUD_ASSERT(flash);
  887. while (true) {
  888. __delay_temp();
  889. result = sfud_read_status(flash, &status);
  890. if (result == SFUD_SUCCESS && ((status & SFUD_STATUS_REGISTER_BUSY)) == 0) {
  891. break;
  892. }
  893. retry_times--;
  894. if (!retry_times) {result = SFUD_ERR_TIMEOUT;break;}
  895. /* retry counts */
  896. //SFUD_RETRY_PROCESS(flash->retry.delay, retry_times, result);
  897. }
  898. if (result != SFUD_SUCCESS || ((status & SFUD_STATUS_REGISTER_BUSY)) != 0) {
  899. SFUD_INFO("Error: Flash wait busy has an error.");
  900. }
  901. return result;
  902. }
  903. static void make_address_byte_array(const sfud_flash *flash, uint32_t addr, uint8_t *array) {
  904. uint8_t len, i;
  905. SFUD_ASSERT(flash);
  906. SFUD_ASSERT(array);
  907. len = flash->addr_in_4_byte ? 4 : 3;
  908. for (i = 0; i < len; i++) {
  909. array[i] = (addr >> ((len - (i + 1)) * 8)) & 0xFF;
  910. }
  911. }
  912. /**
  913. * write status register
  914. *
  915. * @param flash flash device
  916. * @param is_volatile true: volatile mode, false: non-volatile mode
  917. * @param status register status
  918. *
  919. * @return result
  920. */
  921. sfud_err sfud_write_status(const sfud_flash *flash, bool is_volatile, uint8_t status) {
  922. sfud_err result = SFUD_SUCCESS;
  923. const sfud_spi *spi = &flash->spi;
  924. uint8_t cmd_data[2];
  925. SFUD_ASSERT(flash);
  926. if (is_volatile) {
  927. cmd_data[0] = SFUD_VOLATILE_SR_WRITE_ENABLE;
  928. result = spi->wr(spi, cmd_data, 1, NULL, 0);
  929. } else {
  930. result = set_write_enabled(flash, true);
  931. }
  932. if (result == SFUD_SUCCESS) {
  933. cmd_data[0] = SFUD_CMD_WRITE_STATUS_REGISTER;
  934. cmd_data[1] = status;
  935. result = spi->wr(spi, cmd_data, 2, NULL, 0);
  936. }
  937. if (result != SFUD_SUCCESS) {
  938. SFUD_INFO("Error: Write_status register failed.");
  939. }
  940. return result;
  941. }