sfud.c 27 KB

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