sfud.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  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 "../inc/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. static sfud_flash flash_table[] = 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);
  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_adress_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 is initialize success.", flash->name);
  88. } else {
  89. flash->init_ok = false;
  90. SFUD_INFO("Error: %s flash device is initialize fail.", 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(flash_table) / sizeof(sfud_flash); i++) {
  106. /* initialize flash device index of flash device information table */
  107. flash_table[i].index = i;
  108. cur_flash_result = sfud_device_init(&flash_table[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 &flash_table[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(flash_table) / 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 flash_table;
  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. flash->read_cmd_format.instruction = ins + 1;
  154. flash->read_cmd_format.address_size = 32;
  155. }
  156. flash->read_cmd_format.instruction_lines = ins_lines;
  157. flash->read_cmd_format.address_lines = addr_lines;
  158. flash->read_cmd_format.alternate_bytes_lines = 0;
  159. flash->read_cmd_format.dummy_cycles = dummy_cycles;
  160. flash->read_cmd_format.data_lines = data_lines;
  161. }
  162. /**
  163. * Enbale the fast read mode in QSPI flash mode. Default read mode is normal SPI mode.
  164. *
  165. * it will find the appropriate fast-read instruction to replace the read instruction(0x03)
  166. * fast-read instruction @see SFUD_FLASH_EXT_INFO_TABLE
  167. *
  168. * @note When Flash is in QSPI mode, the method must be called after sfud_device_init().
  169. *
  170. * @param flash flash device
  171. * @param data_line_width the data lines max width which QSPI bus supported, such as 1, 2, 4
  172. *
  173. * @return result
  174. */
  175. sfud_err sfud_qspi_fast_read_enable(sfud_flash *flash, uint8_t data_line_width) {
  176. size_t i = 0;
  177. uint8_t read_mode = NORMAL_SPI_READ;
  178. sfud_err result = SFUD_SUCCESS;
  179. SFUD_ASSERT(flash);
  180. SFUD_ASSERT(data_line_width == 1 || data_line_width == 2 || data_line_width == 4);
  181. /* get read_mode, If don't found, the default is SFUD_QSPI_NORMAL_SPI_READ */
  182. for (i = 0; i < sizeof(qspi_flash_ext_info_table) / sizeof(sfud_qspi_flash_ext_info); i++) {
  183. if ((qspi_flash_ext_info_table[i].mf_id == flash->chip.mf_id)
  184. && (qspi_flash_ext_info_table[i].type_id == flash->chip.type_id)
  185. && (qspi_flash_ext_info_table[i].capacity_id == flash->chip.capacity_id)) {
  186. read_mode = qspi_flash_ext_info_table[i].read_mode;
  187. }
  188. }
  189. /* determine qspi supports which read mode and set read_cmd_format struct */
  190. switch (data_line_width) {
  191. case 1:
  192. qspi_set_read_cmd_format(flash, SFUD_CMD_READ_DATA, 1, 1, 0, 1);
  193. break;
  194. case 2:
  195. if (read_mode & DUAL_IO) {
  196. qspi_set_read_cmd_format(flash, SFUD_CMD_DUAL_IO_READ_DATA, 1, 2, 8, 2);
  197. } else if (read_mode & DUAL_OUTPUT) {
  198. qspi_set_read_cmd_format(flash, SFUD_CMD_DUAL_OUTPUT_READ_DATA, 1, 1, 8, 2);
  199. } else {
  200. qspi_set_read_cmd_format(flash, SFUD_CMD_READ_DATA, 1, 1, 0, 1);
  201. }
  202. break;
  203. case 4:
  204. if (read_mode & QUAD_IO) {
  205. qspi_set_read_cmd_format(flash, SFUD_CMD_QUAD_IO_READ_DATA, 1, 4, 6, 4);
  206. } else if (read_mode & QUAD_OUTPUT) {
  207. qspi_set_read_cmd_format(flash, SFUD_CMD_QUAD_OUTPUT_READ_DATA, 1, 1, 8, 4);
  208. } else {
  209. qspi_set_read_cmd_format(flash, SFUD_CMD_READ_DATA, 1, 1, 0, 1);
  210. }
  211. break;
  212. }
  213. return result;
  214. }
  215. #endif /* SFUD_USING_QSPI */
  216. /**
  217. * hardware initialize
  218. */
  219. static sfud_err hardware_init(sfud_flash *flash) {
  220. extern sfud_err sfud_spi_port_init(sfud_flash * flash);
  221. sfud_err result = SFUD_SUCCESS;
  222. size_t i;
  223. SFUD_ASSERT(flash);
  224. result = sfud_spi_port_init(flash);
  225. if (result != SFUD_SUCCESS) {
  226. return result;
  227. }
  228. #ifdef SFUD_USING_QSPI
  229. /* set default read instruction */
  230. flash->read_cmd_format.instruction = SFUD_CMD_READ_DATA;
  231. #endif /* SFUD_USING_QSPI */
  232. /* SPI write read function must be initialize */
  233. SFUD_ASSERT(flash->spi.wr);
  234. /* if the user don't configure flash chip information then using SFDP parameter or static flash parameter table */
  235. if (flash->chip.capacity == 0 || flash->chip.write_mode == 0 || flash->chip.erase_gran == 0
  236. || flash->chip.erase_gran_cmd == 0) {
  237. /* read JEDEC ID include manufacturer ID, memory type ID and flash capacity ID */
  238. result = read_jedec_id(flash);
  239. if (result != SFUD_SUCCESS) {
  240. return result;
  241. }
  242. #ifdef SFUD_USING_SFDP
  243. extern bool sfud_read_sfdp(sfud_flash *flash);
  244. /* read SFDP parameters */
  245. if (sfud_read_sfdp(flash)) {
  246. flash->chip.name = NULL;
  247. flash->chip.capacity = flash->sfdp.capacity;
  248. /* only 1 byte or 256 bytes write mode for SFDP */
  249. if (flash->sfdp.write_gran == 1) {
  250. flash->chip.write_mode = SFUD_WM_BYTE;
  251. } else {
  252. flash->chip.write_mode = SFUD_WM_PAGE_256B;
  253. }
  254. /* find the the smallest erase sector size for eraser. then will use this size for erase granularity */
  255. flash->chip.erase_gran = flash->sfdp.eraser[0].size;
  256. flash->chip.erase_gran_cmd = flash->sfdp.eraser[0].cmd;
  257. for (i = 1; i < SFUD_SFDP_ERASE_TYPE_MAX_NUM; i++) {
  258. if (flash->sfdp.eraser[i].size != 0 && flash->chip.erase_gran > flash->sfdp.eraser[i].size) {
  259. flash->chip.erase_gran = flash->sfdp.eraser[i].size;
  260. flash->chip.erase_gran_cmd = flash->sfdp.eraser[i].cmd;
  261. }
  262. }
  263. } else {
  264. #endif
  265. #ifdef SFUD_USING_FLASH_INFO_TABLE
  266. /* read SFDP parameters failed then using SFUD library provided static parameter */
  267. for (i = 0; i < sizeof(flash_chip_table) / sizeof(sfud_flash_chip); i++) {
  268. if ((flash_chip_table[i].mf_id == flash->chip.mf_id)
  269. && (flash_chip_table[i].type_id == flash->chip.type_id)
  270. && (flash_chip_table[i].capacity_id == flash->chip.capacity_id)) {
  271. flash->chip.name = flash_chip_table[i].name;
  272. flash->chip.capacity = flash_chip_table[i].capacity;
  273. flash->chip.write_mode = flash_chip_table[i].write_mode;
  274. flash->chip.erase_gran = flash_chip_table[i].erase_gran;
  275. flash->chip.erase_gran_cmd = flash_chip_table[i].erase_gran_cmd;
  276. break;
  277. }
  278. }
  279. #endif
  280. #ifdef SFUD_USING_SFDP
  281. }
  282. #endif
  283. }
  284. if (flash->chip.capacity == 0 || flash->chip.write_mode == 0 || flash->chip.erase_gran == 0
  285. || flash->chip.erase_gran_cmd == 0) {
  286. SFUD_INFO("Warning: This flash device is not found or not support.");
  287. return SFUD_ERR_NOT_FOUND;
  288. } else {
  289. const char *flash_mf_name = NULL;
  290. /* find the manufacturer information */
  291. for (i = 0; i < sizeof(mf_table) / sizeof(sfud_mf); i++) {
  292. if (mf_table[i].id == flash->chip.mf_id) {
  293. flash_mf_name = mf_table[i].name;
  294. break;
  295. }
  296. }
  297. /* print manufacturer and flash chip name */
  298. if (flash_mf_name && flash->chip.name) {
  299. SFUD_INFO("Find a %s %s flash chip. Size is %ld bytes.", flash_mf_name, flash->chip.name,
  300. flash->chip.capacity);
  301. } else if (flash_mf_name) {
  302. SFUD_INFO("Find a %s flash chip. Size is %ld bytes.", flash_mf_name, flash->chip.capacity);
  303. } else {
  304. SFUD_INFO("Find a flash chip. Size is %ld bytes.", flash->chip.capacity);
  305. }
  306. }
  307. /* reset flash device */
  308. result = reset(flash);
  309. if (result != SFUD_SUCCESS) {
  310. return result;
  311. }
  312. /* I found when the flash write mode is supported AAI mode. The flash all blocks is protected,
  313. * so need change the flash status to unprotected before write and erase operate. */
  314. if (flash->chip.write_mode & SFUD_WM_AAI) {
  315. result = sfud_write_status(flash, true, 0x00);
  316. if (result != SFUD_SUCCESS) {
  317. return result;
  318. }
  319. }
  320. /* if the flash is large than 16MB (256Mb) then enter in 4-Byte addressing mode */
  321. if (flash->chip.capacity > (1L << 24)) {
  322. result = set_4_byte_address_mode(flash, true);
  323. } else {
  324. flash->addr_in_4_byte = false;
  325. }
  326. return result;
  327. }
  328. /**
  329. * software initialize
  330. *
  331. * @param flash flash device
  332. *
  333. * @return result
  334. */
  335. static sfud_err software_init(const sfud_flash *flash) {
  336. sfud_err result = SFUD_SUCCESS;
  337. SFUD_ASSERT(flash);
  338. return result;
  339. }
  340. /**
  341. * read flash data
  342. *
  343. * @param flash flash device
  344. * @param addr start address
  345. * @param size read size
  346. * @param data read data pointer
  347. *
  348. * @return result
  349. */
  350. sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t *data) {
  351. sfud_err result = SFUD_SUCCESS;
  352. const sfud_spi *spi = &flash->spi;
  353. uint8_t cmd_data[5], cmd_size;
  354. SFUD_ASSERT(flash);
  355. SFUD_ASSERT(data);
  356. /* must be call this function after initialize OK */
  357. SFUD_ASSERT(flash->init_ok);
  358. /* check the flash address bound */
  359. if (addr + size > flash->chip.capacity) {
  360. SFUD_INFO("Error: Flash address is out of bound.");
  361. return SFUD_ERR_ADDR_OUT_OF_BOUND;
  362. }
  363. /* lock SPI */
  364. if (spi->lock) {
  365. spi->lock(spi);
  366. }
  367. result = wait_busy(flash);
  368. if (result == SFUD_SUCCESS) {
  369. #ifdef SFUD_USING_QSPI
  370. if (flash->read_cmd_format.instruction != SFUD_CMD_READ_DATA) {
  371. result = spi->qspi_read(spi, addr, (sfud_qspi_read_cmd_format *)&flash->read_cmd_format, data, size);
  372. } else
  373. #endif
  374. {
  375. cmd_data[0] = SFUD_CMD_READ_DATA;
  376. make_adress_byte_array(flash, addr, &cmd_data[1]);
  377. cmd_size = flash->addr_in_4_byte ? 5 : 4;
  378. result = spi->wr(spi, cmd_data, cmd_size, data, size);
  379. }
  380. }
  381. /* unlock SPI */
  382. if (spi->unlock) {
  383. spi->unlock(spi);
  384. }
  385. return result;
  386. }
  387. /**
  388. * erase all flash data
  389. *
  390. * @param flash flash device
  391. *
  392. * @return result
  393. */
  394. sfud_err sfud_chip_erase(const sfud_flash *flash) {
  395. sfud_err result = SFUD_SUCCESS;
  396. const sfud_spi *spi = &flash->spi;
  397. uint8_t cmd_data[4];
  398. SFUD_ASSERT(flash);
  399. /* must be call this function after initialize OK */
  400. SFUD_ASSERT(flash->init_ok);
  401. /* lock SPI */
  402. if (spi->lock) {
  403. spi->lock(spi);
  404. }
  405. /* set the flash write enable */
  406. result = set_write_enabled(flash, true);
  407. if (result != SFUD_SUCCESS) {
  408. goto __exit;
  409. }
  410. cmd_data[0] = SFUD_CMD_ERASE_CHIP;
  411. /* dual-buffer write, like AT45DB series flash chip erase operate is different for other flash */
  412. if (flash->chip.write_mode & SFUD_WM_DUAL_BUFFER) {
  413. cmd_data[1] = 0x94;
  414. cmd_data[2] = 0x80;
  415. cmd_data[3] = 0x9A;
  416. result = spi->wr(spi, cmd_data, 4, NULL, 0);
  417. } else {
  418. result = spi->wr(spi, cmd_data, 1, NULL, 0);
  419. }
  420. if (result != SFUD_SUCCESS) {
  421. SFUD_INFO("Error: Flash chip erase SPI communicate error.");
  422. goto __exit;
  423. }
  424. result = wait_busy(flash);
  425. __exit:
  426. /* set the flash write disable */
  427. set_write_enabled(flash, false);
  428. /* unlock SPI */
  429. if (spi->unlock) {
  430. spi->unlock(spi);
  431. }
  432. return result;
  433. }
  434. /**
  435. * erase flash data
  436. *
  437. * @note It will erase align by erase granularity.
  438. *
  439. * @param flash flash device
  440. * @param addr start address
  441. * @param size erase size
  442. *
  443. * @return result
  444. */
  445. sfud_err sfud_erase(const sfud_flash *flash, uint32_t addr, size_t size) {
  446. extern size_t sfud_sfdp_get_suitable_eraser(const sfud_flash *flash, uint32_t addr, size_t erase_size);
  447. sfud_err result = SFUD_SUCCESS;
  448. const sfud_spi *spi = &flash->spi;
  449. uint8_t cmd_data[5], cmd_size, cur_erase_cmd;
  450. size_t cur_erase_size;
  451. SFUD_ASSERT(flash);
  452. /* must be call this function after initialize OK */
  453. SFUD_ASSERT(flash->init_ok);
  454. /* check the flash address bound */
  455. if (addr + size > flash->chip.capacity) {
  456. SFUD_INFO("Error: Flash address is out of bound.");
  457. return SFUD_ERR_ADDR_OUT_OF_BOUND;
  458. }
  459. if (addr == 0 && size == flash->chip.capacity) {
  460. return sfud_chip_erase(flash);
  461. }
  462. /* lock SPI */
  463. if (spi->lock) {
  464. spi->lock(spi);
  465. }
  466. /* loop erase operate. erase unit is erase granularity */
  467. while (size) {
  468. /* if this flash is support SFDP parameter, then used SFDP parameter supplies eraser */
  469. #ifdef SFUD_USING_SFDP
  470. size_t eraser_index;
  471. if (flash->sfdp.available) {
  472. /* get the suitable eraser for erase process from SFDP parameter */
  473. eraser_index = sfud_sfdp_get_suitable_eraser(flash, addr, size);
  474. cur_erase_cmd = flash->sfdp.eraser[eraser_index].cmd;
  475. cur_erase_size = flash->sfdp.eraser[eraser_index].size;
  476. } else {
  477. #else
  478. {
  479. #endif
  480. cur_erase_cmd = flash->chip.erase_gran_cmd;
  481. cur_erase_size = flash->chip.erase_gran;
  482. }
  483. /* set the flash write enable */
  484. result = set_write_enabled(flash, true);
  485. if (result != SFUD_SUCCESS) {
  486. goto __exit;
  487. }
  488. cmd_data[0] = cur_erase_cmd;
  489. make_adress_byte_array(flash, addr, &cmd_data[1]);
  490. cmd_size = flash->addr_in_4_byte ? 5 : 4;
  491. result = spi->wr(spi, cmd_data, cmd_size, NULL, 0);
  492. if (result != SFUD_SUCCESS) {
  493. SFUD_INFO("Error: Flash erase SPI communicate error.");
  494. goto __exit;
  495. }
  496. result = wait_busy(flash);
  497. if (result != SFUD_SUCCESS) {
  498. goto __exit;
  499. }
  500. /* make erase align and calculate next erase address */
  501. if (addr % cur_erase_size != 0) {
  502. if (size > cur_erase_size - (addr % cur_erase_size)) {
  503. size -= cur_erase_size - (addr % cur_erase_size);
  504. addr += cur_erase_size - (addr % cur_erase_size);
  505. } else {
  506. goto __exit;
  507. }
  508. } else {
  509. if (size > cur_erase_size) {
  510. size -= cur_erase_size;
  511. addr += cur_erase_size;
  512. } else {
  513. goto __exit;
  514. }
  515. }
  516. }
  517. __exit:
  518. /* set the flash write disable */
  519. set_write_enabled(flash, false);
  520. /* unlock SPI */
  521. if (spi->unlock) {
  522. spi->unlock(spi);
  523. }
  524. return result;
  525. }
  526. /**
  527. * write flash data (no erase operate) for write 1 to 256 bytes per page mode or byte write mode
  528. *
  529. * @param flash flash device
  530. * @param addr start address
  531. * @param size write size
  532. * @param write_gran write granularity bytes, only support 1 or 256
  533. * @param data write data
  534. *
  535. * @return result
  536. */
  537. static sfud_err page256_or_1_byte_write(const sfud_flash *flash, uint32_t addr, size_t size, uint16_t write_gran,
  538. const uint8_t *data) {
  539. sfud_err result = SFUD_SUCCESS;
  540. const sfud_spi *spi = &flash->spi;
  541. static uint8_t cmd_data[5 + SFUD_WRITE_MAX_PAGE_SIZE];
  542. uint8_t cmd_size;
  543. size_t data_size;
  544. SFUD_ASSERT(flash);
  545. /* only support 1 or 256 */
  546. SFUD_ASSERT(write_gran == 1 || write_gran == 256);
  547. /* must be call this function after initialize OK */
  548. SFUD_ASSERT(flash->init_ok);
  549. /* check the flash address bound */
  550. if (addr + size > flash->chip.capacity) {
  551. SFUD_INFO("Error: Flash address is out of bound.");
  552. return SFUD_ERR_ADDR_OUT_OF_BOUND;
  553. }
  554. /* lock SPI */
  555. if (spi->lock) {
  556. spi->lock(spi);
  557. }
  558. /* loop write operate. write unit is write granularity */
  559. while (size) {
  560. /* set the flash write enable */
  561. result = set_write_enabled(flash, true);
  562. if (result != SFUD_SUCCESS) {
  563. goto __exit;
  564. }
  565. cmd_data[0] = SFUD_CMD_PAGE_PROGRAM;
  566. make_adress_byte_array(flash, addr, &cmd_data[1]);
  567. cmd_size = flash->addr_in_4_byte ? 5 : 4;
  568. /* make write align and calculate next write address */
  569. if (addr % write_gran != 0) {
  570. if (size > write_gran - (addr % write_gran)) {
  571. data_size = write_gran - (addr % write_gran);
  572. } else {
  573. data_size = size;
  574. }
  575. } else {
  576. if (size > write_gran) {
  577. data_size = write_gran;
  578. } else {
  579. data_size = size;
  580. }
  581. }
  582. size -= data_size;
  583. addr += data_size;
  584. memcpy(&cmd_data[cmd_size], data, data_size);
  585. result = spi->wr(spi, cmd_data, cmd_size + data_size, NULL, 0);
  586. if (result != SFUD_SUCCESS) {
  587. SFUD_INFO("Error: Flash write SPI communicate error.");
  588. goto __exit;
  589. }
  590. result = wait_busy(flash);
  591. if (result != SFUD_SUCCESS) {
  592. goto __exit;
  593. }
  594. data += data_size;
  595. }
  596. __exit:
  597. /* set the flash write disable */
  598. set_write_enabled(flash, false);
  599. /* unlock SPI */
  600. if (spi->unlock) {
  601. spi->unlock(spi);
  602. }
  603. return result;
  604. }
  605. /**
  606. * write flash data (no erase operate) for auto address increment mode
  607. *
  608. * If the address is odd number, it will place one 0xFF before the start of data for protect the old data.
  609. * If the latest remain size is 1, it will append one 0xFF at the end of data for protect the old data.
  610. *
  611. * @param flash flash device
  612. * @param addr start address
  613. * @param size write size
  614. * @param data write data
  615. *
  616. * @return result
  617. */
  618. static sfud_err aai_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data) {
  619. sfud_err result = SFUD_SUCCESS;
  620. const sfud_spi *spi = &flash->spi;
  621. uint8_t cmd_data[6], cmd_size;
  622. bool first_write = true;
  623. SFUD_ASSERT(flash);
  624. SFUD_ASSERT(flash->init_ok);
  625. /* check the flash address bound */
  626. if (addr + size > flash->chip.capacity) {
  627. SFUD_INFO("Error: Flash address is out of bound.");
  628. return SFUD_ERR_ADDR_OUT_OF_BOUND;
  629. }
  630. /* lock SPI */
  631. if (spi->lock) {
  632. spi->lock(spi);
  633. }
  634. /* The address must be even for AAI write mode. So it must write one byte first when address is odd. */
  635. if (addr % 2 != 0) {
  636. result = page256_or_1_byte_write(flash, addr++, 1, 1, data++);
  637. if (result != SFUD_SUCCESS) {
  638. goto __exit;
  639. }
  640. size--;
  641. }
  642. /* set the flash write enable */
  643. result = set_write_enabled(flash, true);
  644. if (result != SFUD_SUCCESS) {
  645. goto __exit;
  646. }
  647. /* loop write operate. */
  648. cmd_data[0] = SFUD_CMD_AAI_WORD_PROGRAM;
  649. while (size >= 2) {
  650. if (first_write) {
  651. make_adress_byte_array(flash, addr, &cmd_data[1]);
  652. cmd_size = flash->addr_in_4_byte ? 5 : 4;
  653. cmd_data[cmd_size] = *data;
  654. cmd_data[cmd_size + 1] = *(data + 1);
  655. first_write = false;
  656. } else {
  657. cmd_size = 1;
  658. cmd_data[1] = *data;
  659. cmd_data[2] = *(data + 1);
  660. }
  661. result = spi->wr(spi, cmd_data, cmd_size + 2, NULL, 0);
  662. if (result != SFUD_SUCCESS) {
  663. SFUD_INFO("Error: Flash write SPI communicate error.");
  664. goto __exit;
  665. }
  666. result = wait_busy(flash);
  667. if (result != SFUD_SUCCESS) {
  668. goto __exit;
  669. }
  670. size -= 2;
  671. addr += 2;
  672. data += 2;
  673. }
  674. /* set the flash write disable for exit AAI mode */
  675. result = set_write_enabled(flash, false);
  676. /* write last one byte data when origin write size is odd */
  677. if (result == SFUD_SUCCESS && size == 1) {
  678. result = page256_or_1_byte_write(flash, addr, 1, 1, data);
  679. }
  680. __exit:
  681. if (result != SFUD_SUCCESS) {
  682. set_write_enabled(flash, false);
  683. }
  684. /* unlock SPI */
  685. if (spi->unlock) {
  686. spi->unlock(spi);
  687. }
  688. return result;
  689. }
  690. /**
  691. * write flash data (no erase operate)
  692. *
  693. * @param flash flash device
  694. * @param addr start address
  695. * @param size write size
  696. * @param data write data
  697. *
  698. * @return result
  699. */
  700. sfud_err sfud_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data) {
  701. sfud_err result = SFUD_SUCCESS;
  702. if (flash->chip.write_mode & SFUD_WM_PAGE_256B) {
  703. result = page256_or_1_byte_write(flash, addr, size, 256, data);
  704. } else if (flash->chip.write_mode & SFUD_WM_AAI) {
  705. result = aai_write(flash, addr, size, data);
  706. } else if (flash->chip.write_mode & SFUD_WM_DUAL_BUFFER) {
  707. //TODO dual-buffer write mode
  708. }
  709. return result;
  710. }
  711. /**
  712. * erase and write flash data
  713. *
  714. * @param flash flash device
  715. * @param addr start address
  716. * @param size write size
  717. * @param data write data
  718. *
  719. * @return result
  720. */
  721. sfud_err sfud_erase_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data) {
  722. sfud_err result = SFUD_SUCCESS;
  723. result = sfud_erase(flash, addr, size);
  724. if (result == SFUD_SUCCESS) {
  725. result = sfud_write(flash, addr, size, data);
  726. }
  727. return result;
  728. }
  729. static sfud_err reset(const sfud_flash *flash) {
  730. sfud_err result = SFUD_SUCCESS;
  731. const sfud_spi *spi = &flash->spi;
  732. uint8_t cmd_data[2];
  733. SFUD_ASSERT(flash);
  734. cmd_data[0] = SFUD_CMD_ENABLE_RESET;
  735. result = spi->wr(spi, cmd_data, 1, NULL, 0);
  736. if (result == SFUD_SUCCESS) {
  737. result = wait_busy(flash);
  738. } else {
  739. SFUD_INFO("Error: Flash device reset failed.");
  740. return result;
  741. }
  742. cmd_data[1] = SFUD_CMD_RESET;
  743. result = spi->wr(spi, &cmd_data[1], 1, NULL, 0);
  744. if (result == SFUD_SUCCESS) {
  745. result = wait_busy(flash);
  746. }
  747. if (result == SFUD_SUCCESS) {
  748. SFUD_DEBUG("Flash device reset success.");
  749. } else {
  750. SFUD_INFO("Error: Flash device reset failed.");
  751. }
  752. return result;
  753. }
  754. static sfud_err read_jedec_id(sfud_flash *flash) {
  755. sfud_err result = SFUD_SUCCESS;
  756. const sfud_spi *spi = &flash->spi;
  757. uint8_t cmd_data[1], recv_data[3];
  758. SFUD_ASSERT(flash);
  759. cmd_data[0] = SFUD_CMD_JEDEC_ID;
  760. result = spi->wr(spi, cmd_data, sizeof(cmd_data), recv_data, sizeof(recv_data));
  761. if (result == SFUD_SUCCESS) {
  762. flash->chip.mf_id = recv_data[0];
  763. flash->chip.type_id = recv_data[1];
  764. flash->chip.capacity_id = recv_data[2];
  765. SFUD_DEBUG("The flash device manufacturer ID is 0x%02X, memory type ID is 0x%02X, capacity ID is 0x%02X.",
  766. flash->chip.mf_id, flash->chip.type_id, flash->chip.capacity_id);
  767. } else {
  768. SFUD_INFO("Error: Read flash device JEDEC ID error.");
  769. }
  770. return result;
  771. }
  772. /**
  773. * set the flash write enable or write disable
  774. *
  775. * @param flash flash device
  776. * @param enabled true: enable false: disable
  777. *
  778. * @return result
  779. */
  780. static sfud_err set_write_enabled(const sfud_flash *flash, bool enabled) {
  781. sfud_err result = SFUD_SUCCESS;
  782. uint8_t cmd, register_status;
  783. SFUD_ASSERT(flash);
  784. if (enabled) {
  785. cmd = SFUD_CMD_WRITE_ENABLE;
  786. } else {
  787. cmd = SFUD_CMD_WRITE_DISABLE;
  788. }
  789. result = flash->spi.wr(&flash->spi, &cmd, 1, NULL, 0);
  790. if (result == SFUD_SUCCESS) {
  791. result = sfud_read_status(flash, &register_status);
  792. }
  793. if (result == SFUD_SUCCESS) {
  794. if (enabled && (register_status & SFUD_STATUS_REGISTER_WEL) == 0) {
  795. SFUD_INFO("Error: Can't enable write status.");
  796. return SFUD_ERR_WRITE;
  797. } else if (!enabled && (register_status & SFUD_STATUS_REGISTER_WEL) == 1) {
  798. SFUD_INFO("Error: Can't disable write status.");
  799. return SFUD_ERR_WRITE;
  800. }
  801. }
  802. return result;
  803. }
  804. /**
  805. * enable or disable 4-Byte addressing for flash
  806. *
  807. * @note The 4-Byte addressing just supported for the flash capacity which is large then 16MB (256Mb).
  808. *
  809. * @param flash flash device
  810. * @param enabled true: enable false: disable
  811. *
  812. * @return result
  813. */
  814. static sfud_err set_4_byte_address_mode(sfud_flash *flash, bool enabled) {
  815. sfud_err result = SFUD_SUCCESS;
  816. uint8_t cmd;
  817. SFUD_ASSERT(flash);
  818. /* set the flash write enable */
  819. result = set_write_enabled(flash, true);
  820. if (result != SFUD_SUCCESS) {
  821. return result;
  822. }
  823. if (enabled) {
  824. cmd = SFUD_CMD_ENTER_4B_ADDRESS_MODE;
  825. } else {
  826. cmd = SFUD_CMD_EXIT_4B_ADDRESS_MODE;
  827. }
  828. result = flash->spi.wr(&flash->spi, &cmd, 1, NULL, 0);
  829. if (result == SFUD_SUCCESS) {
  830. flash->addr_in_4_byte = enabled ? true : false;
  831. SFUD_DEBUG("%s 4-Byte addressing mode success.", enabled ? "Enter" : "Exit");
  832. } else {
  833. SFUD_INFO("Error: %s 4-Byte addressing mode failed.", enabled ? "Enter" : "Exit");
  834. }
  835. return result;
  836. }
  837. /**
  838. * read flash register status
  839. *
  840. * @param flash flash device
  841. * @param status register status
  842. *
  843. * @return result
  844. */
  845. sfud_err sfud_read_status(const sfud_flash *flash, uint8_t *status) {
  846. uint8_t cmd = SFUD_CMD_READ_STATUS_REGISTER;
  847. SFUD_ASSERT(flash);
  848. SFUD_ASSERT(status);
  849. return flash->spi.wr(&flash->spi, &cmd, 1, status, 1);
  850. }
  851. static sfud_err wait_busy(const sfud_flash *flash) {
  852. sfud_err result = SFUD_SUCCESS;
  853. uint8_t status;
  854. size_t retry_times = flash->retry.times;
  855. SFUD_ASSERT(flash);
  856. while (true) {
  857. result = sfud_read_status(flash, &status);
  858. if (result == SFUD_SUCCESS && ((status & SFUD_STATUS_REGISTER_BUSY)) == 0) {
  859. break;
  860. }
  861. /* retry counts */
  862. SFUD_RETRY_PROCESS(flash->retry.delay, retry_times, result);
  863. }
  864. if (result != SFUD_SUCCESS || ((status & SFUD_STATUS_REGISTER_BUSY)) != 0) {
  865. SFUD_INFO("Error: Flash wait busy has an error.");
  866. }
  867. return result;
  868. }
  869. static void make_adress_byte_array(const sfud_flash *flash, uint32_t addr, uint8_t *array) {
  870. uint8_t len, i;
  871. SFUD_ASSERT(flash);
  872. SFUD_ASSERT(array);
  873. len = flash->addr_in_4_byte ? 4 : 3;
  874. for (i = 0; i < len; i++) {
  875. array[i] = (addr >> ((len - (i + 1)) * 8)) & 0xFF;
  876. }
  877. }
  878. /**
  879. * write status register
  880. *
  881. * @param flash flash device
  882. * @param is_volatile true: volatile mode, false: non-volatile mode
  883. * @param status register status
  884. *
  885. * @return result
  886. */
  887. sfud_err sfud_write_status(const sfud_flash *flash, bool is_volatile, uint8_t status) {
  888. sfud_err result = SFUD_SUCCESS;
  889. const sfud_spi *spi = &flash->spi;
  890. uint8_t cmd_data[2];
  891. SFUD_ASSERT(flash);
  892. if (is_volatile) {
  893. cmd_data[0] = SFUD_VOLATILE_SR_WRITE_ENABLE;
  894. result = spi->wr(spi, cmd_data, 1, NULL, 0);
  895. } else {
  896. result = set_write_enabled(flash, true);
  897. }
  898. if (result == SFUD_SUCCESS) {
  899. cmd_data[0] = SFUD_CMD_WRITE_STATUS_REGISTER;
  900. cmd_data[1] = status;
  901. result = spi->wr(spi, cmd_data, 2, NULL, 0);
  902. }
  903. if (result != SFUD_SUCCESS) {
  904. SFUD_INFO("Error: Write_status register failed.");
  905. }
  906. return result;
  907. }