sfud.c 33 KB

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