sfud.c 34 KB

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