sfud.c 33 KB

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