sfud.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  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_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(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. 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], cmd_size;
  363. SFUD_ASSERT(flash);
  364. SFUD_ASSERT(data);
  365. /* must be call this function after initialize OK */
  366. SFUD_ASSERT(flash->init_ok);
  367. /* check the flash address bound */
  368. if (addr + size > flash->chip.capacity) {
  369. SFUD_INFO("Error: Flash address is out of bound.");
  370. return SFUD_ERR_ADDR_OUT_OF_BOUND;
  371. }
  372. /* lock SPI */
  373. if (spi->lock) {
  374. spi->lock(spi);
  375. }
  376. result = wait_busy(flash);
  377. if (result == SFUD_SUCCESS) {
  378. #ifdef SFUD_USING_QSPI
  379. if (flash->read_cmd_format.instruction != SFUD_CMD_READ_DATA) {
  380. result = spi->qspi_read(spi, addr, (sfud_qspi_read_cmd_format *)&flash->read_cmd_format, data, size);
  381. } else
  382. #endif
  383. {
  384. cmd_data[0] = SFUD_CMD_READ_DATA;
  385. make_address_byte_array(flash, addr, &cmd_data[1]);
  386. cmd_size = flash->addr_in_4_byte ? 5 : 4;
  387. result = spi->wr(spi, cmd_data, cmd_size, data, size);
  388. }
  389. }
  390. /* unlock SPI */
  391. if (spi->unlock) {
  392. spi->unlock(spi);
  393. }
  394. return result;
  395. }
  396. /**
  397. * erase all flash data
  398. *
  399. * @param flash flash device
  400. *
  401. * @return result
  402. */
  403. sfud_err sfud_chip_erase(const sfud_flash *flash) {
  404. sfud_err result = SFUD_SUCCESS;
  405. const sfud_spi *spi = &flash->spi;
  406. uint8_t cmd_data[4];
  407. SFUD_ASSERT(flash);
  408. /* must be call this function after initialize OK */
  409. SFUD_ASSERT(flash->init_ok);
  410. /* lock SPI */
  411. if (spi->lock) {
  412. spi->lock(spi);
  413. }
  414. /* set the flash write enable */
  415. result = set_write_enabled(flash, true);
  416. if (result != SFUD_SUCCESS) {
  417. goto __exit;
  418. }
  419. cmd_data[0] = SFUD_CMD_ERASE_CHIP;
  420. /* dual-buffer write, like AT45DB series flash chip erase operate is different for other flash */
  421. if (flash->chip.write_mode & SFUD_WM_DUAL_BUFFER) {
  422. cmd_data[1] = 0x94;
  423. cmd_data[2] = 0x80;
  424. cmd_data[3] = 0x9A;
  425. result = spi->wr(spi, cmd_data, 4, NULL, 0);
  426. } else {
  427. result = spi->wr(spi, cmd_data, 1, NULL, 0);
  428. }
  429. if (result != SFUD_SUCCESS) {
  430. SFUD_INFO("Error: Flash chip erase SPI communicate error.");
  431. goto __exit;
  432. }
  433. result = wait_busy(flash);
  434. __exit:
  435. /* set the flash write disable */
  436. set_write_enabled(flash, false);
  437. /* unlock SPI */
  438. if (spi->unlock) {
  439. spi->unlock(spi);
  440. }
  441. return result;
  442. }
  443. /**
  444. * erase flash data
  445. *
  446. * @note It will erase align by erase granularity.
  447. *
  448. * @param flash flash device
  449. * @param addr start address
  450. * @param size erase size
  451. *
  452. * @return result
  453. */
  454. sfud_err sfud_erase(const sfud_flash *flash, uint32_t addr, size_t size) {
  455. extern size_t sfud_sfdp_get_suitable_eraser(const sfud_flash *flash, uint32_t addr, size_t erase_size);
  456. sfud_err result = SFUD_SUCCESS;
  457. const sfud_spi *spi = &flash->spi;
  458. uint8_t cmd_data[5], cmd_size, cur_erase_cmd;
  459. size_t cur_erase_size;
  460. SFUD_ASSERT(flash);
  461. /* must be call this function after initialize OK */
  462. SFUD_ASSERT(flash->init_ok);
  463. /* check the flash address bound */
  464. if (addr + size > flash->chip.capacity) {
  465. SFUD_INFO("Error: Flash address is out of bound.");
  466. return SFUD_ERR_ADDR_OUT_OF_BOUND;
  467. }
  468. if (addr == 0 && size == flash->chip.capacity) {
  469. return sfud_chip_erase(flash);
  470. }
  471. /* lock SPI */
  472. if (spi->lock) {
  473. spi->lock(spi);
  474. }
  475. /* loop erase operate. erase unit is erase granularity */
  476. while (size) {
  477. /* if this flash is support SFDP parameter, then used SFDP parameter supplies eraser */
  478. #ifdef SFUD_USING_SFDP
  479. size_t eraser_index;
  480. if (flash->sfdp.available) {
  481. /* get the suitable eraser for erase process from SFDP parameter */
  482. eraser_index = sfud_sfdp_get_suitable_eraser(flash, addr, size);
  483. cur_erase_cmd = flash->sfdp.eraser[eraser_index].cmd;
  484. cur_erase_size = flash->sfdp.eraser[eraser_index].size;
  485. } else {
  486. #else
  487. {
  488. #endif
  489. cur_erase_cmd = flash->chip.erase_gran_cmd;
  490. cur_erase_size = flash->chip.erase_gran;
  491. }
  492. /* set the flash write enable */
  493. result = set_write_enabled(flash, true);
  494. if (result != SFUD_SUCCESS) {
  495. goto __exit;
  496. }
  497. cmd_data[0] = cur_erase_cmd;
  498. make_address_byte_array(flash, addr, &cmd_data[1]);
  499. cmd_size = flash->addr_in_4_byte ? 5 : 4;
  500. result = spi->wr(spi, cmd_data, cmd_size, NULL, 0);
  501. if (result != SFUD_SUCCESS) {
  502. SFUD_INFO("Error: Flash erase SPI communicate error.");
  503. goto __exit;
  504. }
  505. result = wait_busy(flash);
  506. if (result != SFUD_SUCCESS) {
  507. goto __exit;
  508. }
  509. /* make erase align and calculate next erase address */
  510. if (addr % cur_erase_size != 0) {
  511. if (size > cur_erase_size - (addr % cur_erase_size)) {
  512. size -= cur_erase_size - (addr % cur_erase_size);
  513. addr += cur_erase_size - (addr % cur_erase_size);
  514. } else {
  515. goto __exit;
  516. }
  517. } else {
  518. if (size > cur_erase_size) {
  519. size -= cur_erase_size;
  520. addr += cur_erase_size;
  521. } else {
  522. goto __exit;
  523. }
  524. }
  525. }
  526. __exit:
  527. /* set the flash write disable */
  528. set_write_enabled(flash, false);
  529. /* unlock SPI */
  530. if (spi->unlock) {
  531. spi->unlock(spi);
  532. }
  533. return result;
  534. }
  535. /**
  536. * write flash data (no erase operate) for write 1 to 256 bytes per page mode or byte write mode
  537. *
  538. * @param flash flash device
  539. * @param addr start address
  540. * @param size write size
  541. * @param write_gran write granularity bytes, only support 1 or 256
  542. * @param data write data
  543. *
  544. * @return result
  545. */
  546. static sfud_err page256_or_1_byte_write(const sfud_flash *flash, uint32_t addr, size_t size, uint16_t write_gran,
  547. const uint8_t *data) {
  548. sfud_err result = SFUD_SUCCESS;
  549. const sfud_spi *spi = &flash->spi;
  550. static uint8_t cmd_data[5 + SFUD_WRITE_MAX_PAGE_SIZE];
  551. uint8_t cmd_size;
  552. size_t data_size;
  553. SFUD_ASSERT(flash);
  554. /* only support 1 or 256 */
  555. SFUD_ASSERT(write_gran == 1 || write_gran == 256);
  556. /* must be call this function after initialize OK */
  557. SFUD_ASSERT(flash->init_ok);
  558. /* check the flash address bound */
  559. if (addr + size > flash->chip.capacity) {
  560. SFUD_INFO("Error: Flash address is out of bound.");
  561. return SFUD_ERR_ADDR_OUT_OF_BOUND;
  562. }
  563. /* lock SPI */
  564. if (spi->lock) {
  565. spi->lock(spi);
  566. }
  567. /* loop write operate. write unit is write granularity */
  568. while (size) {
  569. /* set the flash write enable */
  570. result = set_write_enabled(flash, true);
  571. if (result != SFUD_SUCCESS) {
  572. goto __exit;
  573. }
  574. cmd_data[0] = SFUD_CMD_PAGE_PROGRAM;
  575. make_address_byte_array(flash, addr, &cmd_data[1]);
  576. cmd_size = flash->addr_in_4_byte ? 5 : 4;
  577. /* make write align and calculate next write address */
  578. if (addr % write_gran != 0) {
  579. if (size > write_gran - (addr % write_gran)) {
  580. data_size = write_gran - (addr % write_gran);
  581. } else {
  582. data_size = size;
  583. }
  584. } else {
  585. if (size > write_gran) {
  586. data_size = write_gran;
  587. } else {
  588. data_size = size;
  589. }
  590. }
  591. size -= data_size;
  592. addr += data_size;
  593. rt_memcpy(&cmd_data[cmd_size], data, data_size);
  594. result = spi->wr(spi, cmd_data, cmd_size + data_size, NULL, 0);
  595. if (result != SFUD_SUCCESS) {
  596. SFUD_INFO("Error: Flash write SPI communicate error.");
  597. goto __exit;
  598. }
  599. result = wait_busy(flash);
  600. if (result != SFUD_SUCCESS) {
  601. goto __exit;
  602. }
  603. data += data_size;
  604. }
  605. __exit:
  606. /* set the flash write disable */
  607. set_write_enabled(flash, false);
  608. /* unlock SPI */
  609. if (spi->unlock) {
  610. spi->unlock(spi);
  611. }
  612. return result;
  613. }
  614. /**
  615. * write flash data (no erase operate) for auto address increment mode
  616. *
  617. * If the address is odd number, it will place one 0xFF before the start of data for protect the old data.
  618. * If the latest remain size is 1, it will append one 0xFF at the end of data for protect the old data.
  619. *
  620. * @param flash flash device
  621. * @param addr start address
  622. * @param size write size
  623. * @param data write data
  624. *
  625. * @return result
  626. */
  627. static sfud_err aai_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data) {
  628. sfud_err result = SFUD_SUCCESS;
  629. const sfud_spi *spi = &flash->spi;
  630. uint8_t cmd_data[8], cmd_size;
  631. bool first_write = true;
  632. SFUD_ASSERT(flash);
  633. SFUD_ASSERT(flash->init_ok);
  634. /* check the flash address bound */
  635. if (addr + size > flash->chip.capacity) {
  636. SFUD_INFO("Error: Flash address is out of bound.");
  637. return SFUD_ERR_ADDR_OUT_OF_BOUND;
  638. }
  639. /* lock SPI */
  640. if (spi->lock) {
  641. spi->lock(spi);
  642. }
  643. /* The address must be even for AAI write mode. So it must write one byte first when address is odd. */
  644. if (addr % 2 != 0) {
  645. result = page256_or_1_byte_write(flash, addr++, 1, 1, data++);
  646. if (result != SFUD_SUCCESS) {
  647. goto __exit;
  648. }
  649. size--;
  650. }
  651. /* set the flash write enable */
  652. result = set_write_enabled(flash, true);
  653. if (result != SFUD_SUCCESS) {
  654. goto __exit;
  655. }
  656. /* loop write operate. */
  657. cmd_data[0] = SFUD_CMD_AAI_WORD_PROGRAM;
  658. while (size >= 2) {
  659. if (first_write) {
  660. make_address_byte_array(flash, addr, &cmd_data[1]);
  661. cmd_size = flash->addr_in_4_byte ? 5 : 4;
  662. cmd_data[cmd_size] = *data;
  663. cmd_data[cmd_size + 1] = *(data + 1);
  664. first_write = false;
  665. } else {
  666. cmd_size = 1;
  667. cmd_data[1] = *data;
  668. cmd_data[2] = *(data + 1);
  669. }
  670. result = spi->wr(spi, cmd_data, cmd_size + 2, NULL, 0);
  671. if (result != SFUD_SUCCESS) {
  672. SFUD_INFO("Error: Flash write SPI communicate error.");
  673. goto __exit;
  674. }
  675. result = wait_busy(flash);
  676. if (result != SFUD_SUCCESS) {
  677. goto __exit;
  678. }
  679. size -= 2;
  680. addr += 2;
  681. data += 2;
  682. }
  683. /* set the flash write disable for exit AAI mode */
  684. result = set_write_enabled(flash, false);
  685. /* write last one byte data when origin write size is odd */
  686. if (result == SFUD_SUCCESS && size == 1) {
  687. result = page256_or_1_byte_write(flash, addr, 1, 1, data);
  688. }
  689. __exit:
  690. if (result != SFUD_SUCCESS) {
  691. set_write_enabled(flash, false);
  692. }
  693. /* unlock SPI */
  694. if (spi->unlock) {
  695. spi->unlock(spi);
  696. }
  697. return result;
  698. }
  699. /**
  700. * write flash data (no erase operate)
  701. *
  702. * @param flash flash device
  703. * @param addr start address
  704. * @param size write size
  705. * @param data write data
  706. *
  707. * @return result
  708. */
  709. sfud_err sfud_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data) {
  710. sfud_err result = SFUD_SUCCESS;
  711. if (flash->chip.write_mode & SFUD_WM_PAGE_256B) {
  712. result = page256_or_1_byte_write(flash, addr, size, 256, data);
  713. } else if (flash->chip.write_mode & SFUD_WM_AAI) {
  714. result = aai_write(flash, addr, size, data);
  715. } else if (flash->chip.write_mode & SFUD_WM_DUAL_BUFFER) {
  716. //TODO dual-buffer write mode
  717. }
  718. return result;
  719. }
  720. /**
  721. * erase and write flash data
  722. *
  723. * @param flash flash device
  724. * @param addr start address
  725. * @param size write size
  726. * @param data write data
  727. *
  728. * @return result
  729. */
  730. sfud_err sfud_erase_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data) {
  731. sfud_err result = SFUD_SUCCESS;
  732. result = sfud_erase(flash, addr, size);
  733. if (result == SFUD_SUCCESS) {
  734. result = sfud_write(flash, addr, size, data);
  735. }
  736. return result;
  737. }
  738. static sfud_err reset(const sfud_flash *flash) {
  739. sfud_err result = SFUD_SUCCESS;
  740. const sfud_spi *spi = &flash->spi;
  741. uint8_t cmd_data[2];
  742. SFUD_ASSERT(flash);
  743. cmd_data[0] = SFUD_CMD_ENABLE_RESET;
  744. result = spi->wr(spi, cmd_data, 1, NULL, 0);
  745. if (result == SFUD_SUCCESS) {
  746. result = wait_busy(flash);
  747. } else {
  748. SFUD_INFO("Error: Flash device reset failed.");
  749. return result;
  750. }
  751. cmd_data[1] = SFUD_CMD_RESET;
  752. result = spi->wr(spi, &cmd_data[1], 1, NULL, 0);
  753. if (result == SFUD_SUCCESS) {
  754. result = wait_busy(flash);
  755. }
  756. if (result == SFUD_SUCCESS) {
  757. SFUD_DEBUG("Flash device reset success.");
  758. } else {
  759. SFUD_INFO("Error: Flash device reset failed.");
  760. }
  761. return result;
  762. }
  763. static sfud_err read_jedec_id(sfud_flash *flash) {
  764. sfud_err result = SFUD_SUCCESS;
  765. const sfud_spi *spi = &flash->spi;
  766. uint8_t cmd_data[1], recv_data[3];
  767. SFUD_ASSERT(flash);
  768. cmd_data[0] = SFUD_CMD_JEDEC_ID;
  769. result = spi->wr(spi, cmd_data, sizeof(cmd_data), recv_data, sizeof(recv_data));
  770. if (result == SFUD_SUCCESS) {
  771. flash->chip.mf_id = recv_data[0];
  772. flash->chip.type_id = recv_data[1];
  773. flash->chip.capacity_id = recv_data[2];
  774. SFUD_DEBUG("The flash device manufacturer ID is 0x%02X, memory type ID is 0x%02X, capacity ID is 0x%02X.",
  775. flash->chip.mf_id, flash->chip.type_id, flash->chip.capacity_id);
  776. } else {
  777. SFUD_INFO("Error: Read flash device JEDEC ID error.");
  778. }
  779. return result;
  780. }
  781. /**
  782. * set the flash write enable or write disable
  783. *
  784. * @param flash flash device
  785. * @param enabled true: enable false: disable
  786. *
  787. * @return result
  788. */
  789. static sfud_err set_write_enabled(const sfud_flash *flash, bool enabled) {
  790. sfud_err result = SFUD_SUCCESS;
  791. uint8_t cmd, register_status;
  792. SFUD_ASSERT(flash);
  793. if (enabled) {
  794. cmd = SFUD_CMD_WRITE_ENABLE;
  795. } else {
  796. cmd = SFUD_CMD_WRITE_DISABLE;
  797. }
  798. result = flash->spi.wr(&flash->spi, &cmd, 1, NULL, 0);
  799. if (result == SFUD_SUCCESS) {
  800. result = sfud_read_status(flash, &register_status);
  801. }
  802. if (result == SFUD_SUCCESS) {
  803. if (enabled && (register_status & SFUD_STATUS_REGISTER_WEL) == 0) {
  804. SFUD_INFO("Error: Can't enable write status.");
  805. return SFUD_ERR_WRITE;
  806. } else if (!enabled && (register_status & SFUD_STATUS_REGISTER_WEL) != 0) {
  807. SFUD_INFO("Error: Can't disable write status.");
  808. return SFUD_ERR_WRITE;
  809. }
  810. }
  811. return result;
  812. }
  813. /**
  814. * enable or disable 4-Byte addressing for flash
  815. *
  816. * @note The 4-Byte addressing just supported for the flash capacity which is large then 16MB (256Mb).
  817. *
  818. * @param flash flash device
  819. * @param enabled true: enable false: disable
  820. *
  821. * @return result
  822. */
  823. static sfud_err set_4_byte_address_mode(sfud_flash *flash, bool enabled) {
  824. sfud_err result = SFUD_SUCCESS;
  825. uint8_t cmd;
  826. SFUD_ASSERT(flash);
  827. /* set the flash write enable */
  828. result = set_write_enabled(flash, true);
  829. if (result != SFUD_SUCCESS) {
  830. return result;
  831. }
  832. if (enabled) {
  833. cmd = SFUD_CMD_ENTER_4B_ADDRESS_MODE;
  834. } else {
  835. cmd = SFUD_CMD_EXIT_4B_ADDRESS_MODE;
  836. }
  837. result = flash->spi.wr(&flash->spi, &cmd, 1, NULL, 0);
  838. if (result == SFUD_SUCCESS) {
  839. flash->addr_in_4_byte = enabled ? true : false;
  840. SFUD_DEBUG("%s 4-Byte addressing mode success.", enabled ? "Enter" : "Exit");
  841. } else {
  842. SFUD_INFO("Error: %s 4-Byte addressing mode failed.", enabled ? "Enter" : "Exit");
  843. }
  844. return result;
  845. }
  846. /**
  847. * read flash register status
  848. *
  849. * @param flash flash device
  850. * @param status register status
  851. *
  852. * @return result
  853. */
  854. sfud_err sfud_read_status(const sfud_flash *flash, uint8_t *status) {
  855. uint8_t cmd = SFUD_CMD_READ_STATUS_REGISTER;
  856. SFUD_ASSERT(flash);
  857. SFUD_ASSERT(status);
  858. return flash->spi.wr(&flash->spi, &cmd, 1, status, 1);
  859. }
  860. static sfud_err wait_busy(const sfud_flash *flash) {
  861. sfud_err result = SFUD_SUCCESS;
  862. uint8_t status;
  863. size_t retry_times = flash->retry.times;
  864. SFUD_ASSERT(flash);
  865. while (true) {
  866. result = sfud_read_status(flash, &status);
  867. if (result == SFUD_SUCCESS && ((status & SFUD_STATUS_REGISTER_BUSY)) == 0) {
  868. break;
  869. }
  870. /* retry counts */
  871. SFUD_RETRY_PROCESS(flash->retry.delay, retry_times, result);
  872. }
  873. if (result != SFUD_SUCCESS || ((status & SFUD_STATUS_REGISTER_BUSY)) != 0) {
  874. SFUD_INFO("Error: Flash wait busy has an error.");
  875. }
  876. return result;
  877. }
  878. static void make_address_byte_array(const sfud_flash *flash, uint32_t addr, uint8_t *array) {
  879. uint8_t len, i;
  880. SFUD_ASSERT(flash);
  881. SFUD_ASSERT(array);
  882. len = flash->addr_in_4_byte ? 4 : 3;
  883. for (i = 0; i < len; i++) {
  884. array[i] = (addr >> ((len - (i + 1)) * 8)) & 0xFF;
  885. }
  886. }
  887. /**
  888. * write status register
  889. *
  890. * @param flash flash device
  891. * @param is_volatile true: volatile mode, false: non-volatile mode
  892. * @param status register status
  893. *
  894. * @return result
  895. */
  896. sfud_err sfud_write_status(const sfud_flash *flash, bool is_volatile, uint8_t status) {
  897. sfud_err result = SFUD_SUCCESS;
  898. const sfud_spi *spi = &flash->spi;
  899. uint8_t cmd_data[2];
  900. SFUD_ASSERT(flash);
  901. if (is_volatile) {
  902. cmd_data[0] = SFUD_VOLATILE_SR_WRITE_ENABLE;
  903. result = spi->wr(spi, cmd_data, 1, NULL, 0);
  904. } else {
  905. result = set_write_enabled(flash, true);
  906. }
  907. if (result == SFUD_SUCCESS) {
  908. cmd_data[0] = SFUD_CMD_WRITE_STATUS_REGISTER;
  909. cmd_data[1] = status;
  910. result = spi->wr(spi, cmd_data, 2, NULL, 0);
  911. }
  912. if (result != SFUD_SUCCESS) {
  913. SFUD_INFO("Error: Write_status register failed.");
  914. }
  915. return result;
  916. }