dev_spi_flash_sfud.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2016-09-28 armink first version.
  9. * 2025-10-30 wdfk-prog enable interrupt-safe operations using spinlocks
  10. */
  11. #include <stdint.h>
  12. #include <string.h>
  13. #include <rtdevice.h>
  14. #include "dev_spi_flash.h"
  15. #include "dev_spi_flash_sfud.h"
  16. #ifdef RT_USING_SFUD
  17. #ifndef RT_SFUD_DEFAULT_SPI_CFG
  18. #ifndef RT_SFUD_SPI_MAX_HZ
  19. #define RT_SFUD_SPI_MAX_HZ 50000000
  20. #endif
  21. /* read the JEDEC SFDP command must run at 50 MHz or less */
  22. #define RT_SFUD_DEFAULT_SPI_CFG \
  23. { \
  24. .mode = RT_SPI_MODE_0 | RT_SPI_MSB, \
  25. .data_width = 8, \
  26. .max_hz = RT_SFUD_SPI_MAX_HZ, \
  27. }
  28. #endif /* RT_SFUD_DEFAULT_SPI_CFG */
  29. #ifdef SFUD_USING_QSPI
  30. #define RT_SFUD_DEFAULT_QSPI_CFG \
  31. { \
  32. RT_SFUD_DEFAULT_SPI_CFG, \
  33. .medium_size = 0x800000, \
  34. .ddr_mode = 0, \
  35. .qspi_dl_width = 4, \
  36. }
  37. #endif /* SFUD_USING_QSPI */
  38. static rt_err_t rt_sfud_control(rt_device_t dev, int cmd, void *args) {
  39. RT_ASSERT(dev);
  40. switch (cmd) {
  41. case RT_DEVICE_CTRL_BLK_GETGEOME: {
  42. struct rt_device_blk_geometry *geometry = (struct rt_device_blk_geometry *) args;
  43. struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (dev->user_data);
  44. if (rtt_dev == RT_NULL || geometry == RT_NULL) {
  45. return -RT_ERROR;
  46. }
  47. geometry->bytes_per_sector = rtt_dev->geometry.bytes_per_sector;
  48. geometry->sector_count = rtt_dev->geometry.sector_count;
  49. geometry->block_size = rtt_dev->geometry.block_size;
  50. break;
  51. }
  52. case RT_DEVICE_CTRL_BLK_ERASE: {
  53. rt_uint32_t *addrs = (rt_uint32_t *) args, start_addr = addrs[0], end_addr = addrs[1], phy_start_addr;
  54. struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (dev->user_data);
  55. sfud_flash *sfud_dev = (sfud_flash *) (rtt_dev->user_data);
  56. rt_size_t phy_size;
  57. if (addrs == RT_NULL || start_addr > end_addr || rtt_dev == RT_NULL || sfud_dev == RT_NULL) {
  58. return -RT_ERROR;
  59. }
  60. if (end_addr == start_addr) {
  61. end_addr ++;
  62. }
  63. phy_start_addr = start_addr * rtt_dev->geometry.bytes_per_sector;
  64. phy_size = (end_addr - start_addr) * rtt_dev->geometry.bytes_per_sector;
  65. if (sfud_erase(sfud_dev, phy_start_addr, phy_size) != SFUD_SUCCESS) {
  66. return -RT_ERROR;
  67. }
  68. break;
  69. }
  70. }
  71. return RT_EOK;
  72. }
  73. static rt_ssize_t rt_sfud_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) {
  74. struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (dev->user_data);
  75. sfud_flash *sfud_dev = (sfud_flash *) (rtt_dev->user_data);
  76. RT_ASSERT(dev);
  77. RT_ASSERT(rtt_dev);
  78. RT_ASSERT(sfud_dev);
  79. /* change the block device's logic address to physical address */
  80. rt_off_t phy_pos = pos * rtt_dev->geometry.bytes_per_sector;
  81. rt_size_t phy_size = size * rtt_dev->geometry.bytes_per_sector;
  82. if (sfud_read(sfud_dev, phy_pos, phy_size, buffer) != SFUD_SUCCESS) {
  83. return 0;
  84. } else {
  85. return size;
  86. }
  87. }
  88. static rt_ssize_t rt_sfud_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) {
  89. struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (dev->user_data);
  90. sfud_flash *sfud_dev = (sfud_flash *) (rtt_dev->user_data);
  91. RT_ASSERT(dev);
  92. RT_ASSERT(rtt_dev);
  93. RT_ASSERT(sfud_dev);
  94. /* change the block device's logic address to physical address */
  95. rt_off_t phy_pos = pos * rtt_dev->geometry.bytes_per_sector;
  96. rt_size_t phy_size = size * rtt_dev->geometry.bytes_per_sector;
  97. if (sfud_erase_write(sfud_dev, phy_pos, phy_size, buffer) != SFUD_SUCCESS) {
  98. return 0;
  99. } else {
  100. return size;
  101. }
  102. }
  103. /**
  104. * SPI write data then read data
  105. */
  106. static sfud_err spi_write_read(const sfud_spi *spi, const uint8_t *write_buf, size_t write_size, uint8_t *read_buf,
  107. size_t read_size) {
  108. sfud_err result = SFUD_SUCCESS;
  109. sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data);
  110. struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data);
  111. RT_ASSERT(spi);
  112. RT_ASSERT(sfud_dev);
  113. RT_ASSERT(rtt_dev);
  114. #ifdef SFUD_USING_QSPI
  115. struct rt_qspi_device *qspi_dev = RT_NULL;
  116. #endif
  117. if (write_size) {
  118. RT_ASSERT(write_buf);
  119. }
  120. if (read_size) {
  121. RT_ASSERT(read_buf);
  122. }
  123. #ifdef SFUD_USING_QSPI
  124. if(rtt_dev->rt_spi_device->bus->mode & RT_SPI_BUS_MODE_QSPI) {
  125. qspi_dev = (struct rt_qspi_device *) (rtt_dev->rt_spi_device);
  126. if (write_size && read_size) {
  127. if (rt_qspi_send_then_recv(qspi_dev, write_buf, write_size, read_buf, read_size) <= 0) {
  128. result = SFUD_ERR_TIMEOUT;
  129. }
  130. } else if (write_size) {
  131. if (rt_qspi_send(qspi_dev, write_buf, write_size) <= 0) {
  132. result = SFUD_ERR_TIMEOUT;
  133. }
  134. }
  135. }
  136. else
  137. #endif
  138. {
  139. if (write_size && read_size) {
  140. if (rt_spi_send_then_recv(rtt_dev->rt_spi_device, write_buf, write_size, read_buf, read_size) != RT_EOK) {
  141. result = SFUD_ERR_TIMEOUT;
  142. }
  143. } else if (write_size) {
  144. if (rt_spi_send(rtt_dev->rt_spi_device, write_buf, write_size) <= 0) {
  145. result = SFUD_ERR_TIMEOUT;
  146. }
  147. } else {
  148. if (rt_spi_recv(rtt_dev->rt_spi_device, read_buf, read_size) <= 0) {
  149. result = SFUD_ERR_TIMEOUT;
  150. }
  151. }
  152. }
  153. return result;
  154. }
  155. #ifdef SFUD_USING_QSPI
  156. /**
  157. * QSPI fast read data
  158. */
  159. static sfud_err qspi_read(const struct __sfud_spi *spi, uint32_t addr, sfud_qspi_read_cmd_format *qspi_read_cmd_format, uint8_t *read_buf, size_t read_size) {
  160. struct rt_qspi_message message;
  161. sfud_err result = SFUD_SUCCESS;
  162. sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data);
  163. struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data);
  164. struct rt_qspi_device *qspi_dev = (struct rt_qspi_device *) (rtt_dev->rt_spi_device);
  165. RT_ASSERT(spi);
  166. RT_ASSERT(sfud_dev);
  167. RT_ASSERT(rtt_dev);
  168. RT_ASSERT(qspi_dev);
  169. /* set message struct */
  170. message.instruction.content = qspi_read_cmd_format->instruction;
  171. message.instruction.qspi_lines = qspi_read_cmd_format->instruction_lines;
  172. message.address.content = addr;
  173. message.address.size = qspi_read_cmd_format->address_size;
  174. message.address.qspi_lines = qspi_read_cmd_format->address_lines;
  175. message.alternate_bytes.content = 0;
  176. message.alternate_bytes.size = 0;
  177. message.alternate_bytes.qspi_lines = 0;
  178. message.dummy_cycles = qspi_read_cmd_format->dummy_cycles;
  179. message.parent.send_buf = RT_NULL;
  180. message.parent.recv_buf = read_buf;
  181. message.parent.length = read_size;
  182. message.parent.cs_release = 1;
  183. message.parent.cs_take = 1;
  184. message.qspi_data_lines = qspi_read_cmd_format->data_lines;
  185. /* set next */
  186. /* Ensure correct QSPI message chaining by setting next pointer to NULL, preventing unintended data transmission issues.*/
  187. message.parent.next = RT_NULL;
  188. if (rt_qspi_transfer_message(qspi_dev, &message) != read_size) {
  189. result = SFUD_ERR_TIMEOUT;
  190. }
  191. return result;
  192. }
  193. #endif
  194. static void spi_lock(const sfud_spi *spi) {
  195. sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data);
  196. struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data);
  197. RT_ASSERT(spi);
  198. RT_ASSERT(sfud_dev);
  199. RT_ASSERT(rtt_dev);
  200. /* If the scheduler is started and in thread context */
  201. if (rt_scheduler_is_available())
  202. {
  203. rt_mutex_take(&(rtt_dev->lock), RT_WAITING_FOREVER);
  204. }
  205. else
  206. {
  207. #ifdef RT_USING_SPI_ISR
  208. rtt_dev->_isr_lvl = rt_spin_lock_irqsave(&rtt_dev->_spinlock);
  209. #endif /* RT_USING_SPI_ISR */
  210. }
  211. }
  212. static void spi_unlock(const sfud_spi *spi) {
  213. sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data);
  214. struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data);
  215. RT_ASSERT(spi);
  216. RT_ASSERT(sfud_dev);
  217. RT_ASSERT(rtt_dev);
  218. /* If the scheduler is started and in thread context */
  219. if (rt_scheduler_is_available())
  220. {
  221. rt_mutex_release(&(rtt_dev->lock));
  222. }
  223. else
  224. {
  225. #ifdef RT_USING_SPI_ISR
  226. rt_spin_unlock_irqrestore(&rtt_dev->_spinlock, rtt_dev->_isr_lvl);
  227. #endif /* RT_USING_SPI_ISR */
  228. }
  229. }
  230. static void retry_delay_100us(void) {
  231. /* 100 microsecond delay */
  232. if (rt_scheduler_is_available())
  233. {
  234. rt_thread_delay((RT_TICK_PER_SECOND * 1 + 9999) / 10000);
  235. }
  236. else
  237. {
  238. #ifdef RT_USING_SPI_ISR
  239. extern void rt_hw_us_delay(rt_uint32_t us);
  240. rt_hw_us_delay(100);
  241. #endif /* RT_USING_SPI_ISR */
  242. }
  243. }
  244. sfud_err sfud_spi_port_init(sfud_flash *flash) {
  245. sfud_err result = SFUD_SUCCESS;
  246. RT_ASSERT(flash);
  247. /* port SPI device interface */
  248. flash->spi.wr = spi_write_read;
  249. #ifdef SFUD_USING_QSPI
  250. flash->spi.qspi_read = qspi_read;
  251. #endif
  252. flash->spi.lock = spi_lock;
  253. flash->spi.unlock = spi_unlock;
  254. flash->spi.user_data = flash;
  255. if (RT_TICK_PER_SECOND < 1000) {
  256. LOG_W("[SFUD] Warning: The OS tick(%d) is less than 1000. So the flash write will take more time.", RT_TICK_PER_SECOND);
  257. }
  258. /* 100 microsecond delay */
  259. flash->retry.delay = retry_delay_100us;
  260. /* 60 seconds timeout */
  261. flash->retry.times = 60 * 10000;
  262. return result;
  263. }
  264. #ifdef RT_USING_DEVICE_OPS
  265. const static struct rt_device_ops flash_device_ops =
  266. {
  267. RT_NULL,
  268. RT_NULL,
  269. RT_NULL,
  270. rt_sfud_read,
  271. rt_sfud_write,
  272. rt_sfud_control
  273. };
  274. #endif
  275. /**
  276. * Probe SPI flash by SFUD (Serial Flash Universal Driver) driver library and though SPI device by specified configuration.
  277. *
  278. * @param spi_flash_dev_name the name which will create SPI flash device
  279. * @param spi_dev_name using SPI device name
  280. * @param spi_cfg SPI device configuration
  281. * @param qspi_cfg QSPI device configuration
  282. *
  283. * @return probed SPI flash device, probe failed will return RT_NULL
  284. */
  285. rt_spi_flash_device_t rt_sfud_flash_probe_ex(const char *spi_flash_dev_name, const char *spi_dev_name,
  286. struct rt_spi_configuration *spi_cfg, struct rt_qspi_configuration *qspi_cfg)
  287. {
  288. rt_spi_flash_device_t rtt_dev = RT_NULL;
  289. sfud_flash *sfud_dev = RT_NULL;
  290. char *spi_flash_dev_name_bak = RT_NULL, *spi_dev_name_bak = RT_NULL;
  291. extern sfud_err sfud_device_init(sfud_flash *flash);
  292. #ifdef SFUD_USING_QSPI
  293. struct rt_qspi_device *qspi_dev = RT_NULL;
  294. #endif
  295. RT_ASSERT(spi_flash_dev_name);
  296. RT_ASSERT(spi_dev_name);
  297. rtt_dev = (rt_spi_flash_device_t) rt_malloc(sizeof(struct spi_flash_device));
  298. sfud_dev = (sfud_flash_t) rt_malloc(sizeof(sfud_flash));
  299. spi_flash_dev_name_bak = (char *) rt_malloc(rt_strlen(spi_flash_dev_name) + 1);
  300. spi_dev_name_bak = (char *) rt_malloc(rt_strlen(spi_dev_name) + 1);
  301. if (rtt_dev) {
  302. rt_memset(rtt_dev, 0, sizeof(struct spi_flash_device));
  303. /* initialize lock */
  304. #ifdef RT_USING_SPI_ISR
  305. rt_spin_lock_init(&rtt_dev->_spinlock);
  306. #endif /* RT_USING_SPI_ISR */
  307. rt_mutex_init(&(rtt_dev->lock), spi_flash_dev_name, RT_IPC_FLAG_PRIO);
  308. }
  309. if (rtt_dev && sfud_dev && spi_flash_dev_name_bak && spi_dev_name_bak) {
  310. rt_memset(sfud_dev, 0, sizeof(sfud_flash));
  311. rt_strncpy(spi_flash_dev_name_bak, spi_flash_dev_name, rt_strlen(spi_flash_dev_name));
  312. rt_strncpy(spi_dev_name_bak, spi_dev_name, rt_strlen(spi_dev_name));
  313. /* make string end sign */
  314. spi_flash_dev_name_bak[rt_strlen(spi_flash_dev_name)] = '\0';
  315. spi_dev_name_bak[rt_strlen(spi_dev_name)] = '\0';
  316. /* SPI configure */
  317. {
  318. /* RT-Thread SPI device initialize */
  319. rtt_dev->rt_spi_device = (struct rt_spi_device *) rt_device_find(spi_dev_name);
  320. if (rtt_dev->rt_spi_device == RT_NULL || rtt_dev->rt_spi_device->parent.type != RT_Device_Class_SPIDevice) {
  321. LOG_E("ERROR: SPI device %s not found!", spi_dev_name);
  322. goto error;
  323. }
  324. sfud_dev->spi.name = spi_dev_name_bak;
  325. #ifdef SFUD_USING_QSPI
  326. /* set the qspi line number and configure the QSPI bus */
  327. if(rtt_dev->rt_spi_device->bus->mode &RT_SPI_BUS_MODE_QSPI) {
  328. qspi_dev = (struct rt_qspi_device *)rtt_dev->rt_spi_device;
  329. qspi_cfg->qspi_dl_width = qspi_dev->config.qspi_dl_width;
  330. rt_qspi_configure(qspi_dev, qspi_cfg);
  331. }
  332. else
  333. #endif
  334. rt_spi_configure(rtt_dev->rt_spi_device, spi_cfg);
  335. }
  336. /* SFUD flash device initialize */
  337. {
  338. sfud_dev->name = spi_flash_dev_name_bak;
  339. /* accessed each other */
  340. rtt_dev->user_data = sfud_dev;
  341. rtt_dev->rt_spi_device->user_data = rtt_dev;
  342. rtt_dev->flash_device.user_data = rtt_dev;
  343. sfud_dev->user_data = rtt_dev;
  344. /* initialize SFUD device */
  345. if (sfud_device_init(sfud_dev) != SFUD_SUCCESS) {
  346. LOG_E("ERROR: SPI flash probe failed by SPI device %s.", spi_dev_name);
  347. goto error;
  348. }
  349. /* when initialize success, then copy SFUD flash device's geometry to RT-Thread SPI flash device */
  350. rtt_dev->geometry.sector_count = sfud_dev->chip.capacity / sfud_dev->chip.erase_gran;
  351. rtt_dev->geometry.bytes_per_sector = sfud_dev->chip.erase_gran;
  352. rtt_dev->geometry.block_size = sfud_dev->chip.erase_gran;
  353. #ifdef SFUD_USING_QSPI
  354. /* reconfigure the QSPI bus for medium size */
  355. if(rtt_dev->rt_spi_device->bus->mode &RT_SPI_BUS_MODE_QSPI) {
  356. qspi_cfg->medium_size = sfud_dev->chip.capacity;
  357. rt_qspi_configure(qspi_dev, qspi_cfg);
  358. if(qspi_dev->enter_qspi_mode != RT_NULL)
  359. qspi_dev->enter_qspi_mode(qspi_dev);
  360. /* set data lines width */
  361. sfud_qspi_fast_read_enable(sfud_dev, qspi_dev->config.qspi_dl_width);
  362. }
  363. #endif /* SFUD_USING_QSPI */
  364. }
  365. /* register device */
  366. rtt_dev->flash_device.type = RT_Device_Class_Block;
  367. #ifdef RT_USING_DEVICE_OPS
  368. rtt_dev->flash_device.ops = &flash_device_ops;
  369. #else
  370. rtt_dev->flash_device.init = RT_NULL;
  371. rtt_dev->flash_device.open = RT_NULL;
  372. rtt_dev->flash_device.close = RT_NULL;
  373. rtt_dev->flash_device.read = rt_sfud_read;
  374. rtt_dev->flash_device.write = rt_sfud_write;
  375. rtt_dev->flash_device.control = rt_sfud_control;
  376. #endif
  377. rt_device_register(&(rtt_dev->flash_device), spi_flash_dev_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
  378. LOG_I("Probe SPI flash %s by SPI device %s success.",spi_flash_dev_name, spi_dev_name);
  379. return rtt_dev;
  380. } else {
  381. LOG_E("ERROR: Low memory.");
  382. goto error;
  383. }
  384. error:
  385. if (rtt_dev) {
  386. rt_mutex_detach(&(rtt_dev->lock));
  387. }
  388. /* may be one of objects memory was malloc success, so need free all */
  389. rt_free(rtt_dev);
  390. rt_free(sfud_dev);
  391. rt_free(spi_flash_dev_name_bak);
  392. rt_free(spi_dev_name_bak);
  393. return RT_NULL;
  394. }
  395. /**
  396. * Probe SPI flash by SFUD(Serial Flash Universal Driver) driver library and though SPI device.
  397. *
  398. * @param spi_flash_dev_name the name which will create SPI flash device
  399. * @param spi_dev_name using SPI device name
  400. *
  401. * @return probed SPI flash device, probe failed will return RT_NULL
  402. */
  403. rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const char *spi_dev_name)
  404. {
  405. struct rt_spi_configuration cfg = RT_SFUD_DEFAULT_SPI_CFG;
  406. #ifndef SFUD_USING_QSPI
  407. return rt_sfud_flash_probe_ex(spi_flash_dev_name, spi_dev_name, &cfg, RT_NULL);
  408. #else
  409. struct rt_qspi_configuration qspi_cfg = RT_SFUD_DEFAULT_QSPI_CFG;
  410. return rt_sfud_flash_probe_ex(spi_flash_dev_name, spi_dev_name, &cfg, &qspi_cfg);
  411. #endif
  412. }
  413. /**
  414. * Delete SPI flash device
  415. *
  416. * @param spi_flash_dev SPI flash device
  417. *
  418. * @return the operation status, RT_EOK on successful
  419. */
  420. rt_err_t rt_sfud_flash_delete(rt_spi_flash_device_t spi_flash_dev) {
  421. sfud_flash *sfud_flash_dev = (sfud_flash *) (spi_flash_dev->user_data);
  422. RT_ASSERT(spi_flash_dev);
  423. RT_ASSERT(sfud_flash_dev);
  424. rt_device_unregister(&(spi_flash_dev->flash_device));
  425. rt_mutex_detach(&(spi_flash_dev->lock));
  426. rt_free(sfud_flash_dev->spi.name);
  427. rt_free(sfud_flash_dev->name);
  428. rt_free(sfud_flash_dev);
  429. rt_free(spi_flash_dev);
  430. return RT_EOK;
  431. }
  432. sfud_flash_t rt_sfud_flash_find(const char *spi_dev_name)
  433. {
  434. rt_spi_flash_device_t rtt_dev = RT_NULL;
  435. struct rt_spi_device *rt_spi_device = RT_NULL;
  436. sfud_flash_t sfud_dev = RT_NULL;
  437. rt_spi_device = (struct rt_spi_device *) rt_device_find(spi_dev_name);
  438. if (rt_spi_device == RT_NULL || rt_spi_device->parent.type != RT_Device_Class_SPIDevice) {
  439. LOG_E("ERROR: SPI device %s not found!", spi_dev_name);
  440. goto __error;
  441. }
  442. rtt_dev = (rt_spi_flash_device_t) (rt_spi_device->user_data);
  443. if (rtt_dev && rtt_dev->user_data) {
  444. sfud_dev = (sfud_flash_t) (rtt_dev->user_data);
  445. return sfud_dev;
  446. } else {
  447. LOG_E("ERROR: SFUD flash device not found!");
  448. goto __error;
  449. }
  450. __error:
  451. return RT_NULL;
  452. }
  453. sfud_flash_t rt_sfud_flash_find_by_dev_name(const char *flash_dev_name)
  454. {
  455. rt_spi_flash_device_t rtt_dev = RT_NULL;
  456. sfud_flash_t sfud_dev = RT_NULL;
  457. rtt_dev = (rt_spi_flash_device_t) rt_device_find(flash_dev_name);
  458. if (rtt_dev == RT_NULL || rtt_dev->flash_device.type != RT_Device_Class_Block) {
  459. LOG_E("ERROR: Flash device %s not found!", flash_dev_name);
  460. goto __error;
  461. }
  462. if (rtt_dev->user_data) {
  463. sfud_dev = (sfud_flash_t) (rtt_dev->user_data);
  464. return sfud_dev;
  465. } else {
  466. LOG_E("ERROR: SFUD flash device not found!");
  467. goto __error;
  468. }
  469. __error:
  470. return RT_NULL;
  471. }
  472. #if defined(RT_USING_FINSH)
  473. #include <finsh.h>
  474. static void sf(uint8_t argc, char **argv) {
  475. #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
  476. #define HEXDUMP_WIDTH 16
  477. #define CMD_PROBE_INDEX 0
  478. #define CMD_READ_INDEX 1
  479. #define CMD_WRITE_INDEX 2
  480. #define CMD_ERASE_INDEX 3
  481. #define CMD_RW_STATUS_INDEX 4
  482. #define CMD_BENCH_INDEX 5
  483. sfud_err result = SFUD_SUCCESS;
  484. static const sfud_flash *sfud_dev = NULL;
  485. static rt_spi_flash_device_t rtt_dev = NULL, rtt_dev_bak = NULL;
  486. size_t i = 0, j = 0;
  487. const char* sf_help_info[] = {
  488. [CMD_PROBE_INDEX] = "sf probe [spi_device] - probe and init SPI flash by given 'spi_device'",
  489. [CMD_READ_INDEX] = "sf read addr size - read 'size' bytes starting at 'addr'",
  490. [CMD_WRITE_INDEX] = "sf write addr data1 ... dataN - write some bytes 'data' to flash starting at 'addr'",
  491. [CMD_ERASE_INDEX] = "sf erase addr size - erase 'size' bytes starting at 'addr'",
  492. [CMD_RW_STATUS_INDEX] = "sf status [<volatile> <status>] - read or write '1:volatile|0:non-volatile' 'status'",
  493. [CMD_BENCH_INDEX] = "sf bench - full chip benchmark. DANGER: It will erase full chip!",
  494. };
  495. if (argc < 2) {
  496. rt_kprintf("Usage:\n");
  497. for (i = 0; i < sizeof(sf_help_info) / sizeof(char*); i++) {
  498. rt_kprintf("%s\n", sf_help_info[i]);
  499. }
  500. rt_kprintf("\n");
  501. } else {
  502. const char *operator = argv[1];
  503. uint32_t addr, size;
  504. if (!strcmp(operator, "probe")) {
  505. if (argc < 3) {
  506. rt_kprintf("Usage: %s.\n", sf_help_info[CMD_PROBE_INDEX]);
  507. } else {
  508. char *spi_dev_name = argv[2];
  509. rtt_dev_bak = rtt_dev;
  510. /* delete the old SPI flash device */
  511. if(rtt_dev_bak) {
  512. rt_sfud_flash_delete(rtt_dev_bak);
  513. }
  514. rtt_dev = rt_sfud_flash_probe("sf_cmd", spi_dev_name);
  515. if (!rtt_dev) {
  516. return;
  517. }
  518. sfud_dev = (sfud_flash_t)rtt_dev->user_data;
  519. if (sfud_dev->chip.capacity < 1024 * 1024) {
  520. rt_kprintf("%ld KB %s is current selected device.\n", sfud_dev->chip.capacity / 1024, sfud_dev->name);
  521. } else {
  522. rt_kprintf("%ld MB %s is current selected device.\n", sfud_dev->chip.capacity / 1024 / 1024,
  523. sfud_dev->name);
  524. }
  525. }
  526. } else {
  527. if (!sfud_dev) {
  528. rt_kprintf("No flash device selected. Please run 'sf probe'.\n");
  529. return;
  530. }
  531. if (!rt_strcmp(operator, "read")) {
  532. if (argc < 4) {
  533. rt_kprintf("Usage: %s.\n", sf_help_info[CMD_READ_INDEX]);
  534. return;
  535. } else {
  536. addr = strtol(argv[2], NULL, 0);
  537. size = strtol(argv[3], NULL, 0);
  538. uint8_t *data = rt_malloc(size);
  539. if (data) {
  540. result = sfud_read(sfud_dev, addr, size, data);
  541. if (result == SFUD_SUCCESS) {
  542. rt_kprintf("Read the %s flash data success. Start from 0x%08lX, size is %ld. The data is:\n",
  543. sfud_dev->name, addr, size);
  544. rt_kprintf("Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
  545. for (i = 0; i < size; i += HEXDUMP_WIDTH)
  546. {
  547. rt_kprintf("[%08lX] ", addr + i);
  548. /* dump hex */
  549. for (j = 0; j < HEXDUMP_WIDTH; j++) {
  550. if (i + j < size) {
  551. rt_kprintf("%02X ", data[i + j]);
  552. } else {
  553. rt_kprintf(" ");
  554. }
  555. }
  556. /* dump char for hex */
  557. for (j = 0; j < HEXDUMP_WIDTH; j++) {
  558. if (i + j < size) {
  559. rt_kprintf("%c", __is_print(data[i + j]) ? data[i + j] : '.');
  560. }
  561. }
  562. rt_kprintf("\n");
  563. }
  564. rt_kprintf("\n");
  565. }
  566. rt_free(data);
  567. } else {
  568. rt_kprintf("Low memory!\n");
  569. }
  570. }
  571. } else if (!rt_strcmp(operator, "write")) {
  572. if (argc < 4) {
  573. rt_kprintf("Usage: %s.\n", sf_help_info[CMD_WRITE_INDEX]);
  574. return;
  575. } else {
  576. addr = strtol(argv[2], NULL, 0);
  577. size = argc - 3;
  578. uint8_t *data = rt_malloc(size);
  579. if (data) {
  580. for (i = 0; i < size; i++) {
  581. data[i] = strtol(argv[3 + i], NULL, 0);
  582. }
  583. result = sfud_write(sfud_dev, addr, size, data);
  584. if (result == SFUD_SUCCESS) {
  585. rt_kprintf("Write the %s flash data success. Start from 0x%08lX, size is %ld.\n",
  586. sfud_dev->name, addr, size);
  587. rt_kprintf("Write data: ");
  588. for (i = 0; i < size; i++) {
  589. rt_kprintf("%d ", data[i]);
  590. }
  591. rt_kprintf(".\n");
  592. }
  593. rt_free(data);
  594. } else {
  595. rt_kprintf("Low memory!\n");
  596. }
  597. }
  598. } else if (!rt_strcmp(operator, "erase")) {
  599. if (argc < 4) {
  600. rt_kprintf("Usage: %s.\n", sf_help_info[CMD_ERASE_INDEX]);
  601. return;
  602. } else {
  603. addr = strtol(argv[2], NULL, 0);
  604. size = strtol(argv[3], NULL, 0);
  605. result = sfud_erase(sfud_dev, addr, size);
  606. if (result == SFUD_SUCCESS) {
  607. rt_kprintf("Erase the %s flash data success. Start from 0x%08lX, size is %ld.\n", sfud_dev->name,
  608. addr, size);
  609. }
  610. }
  611. } else if (!rt_strcmp(operator, "status")) {
  612. if (argc < 3) {
  613. uint8_t status;
  614. result = sfud_read_status(sfud_dev, &status);
  615. if (result == SFUD_SUCCESS) {
  616. rt_kprintf("The %s flash status register current value is 0x%02X.\n", sfud_dev->name, status);
  617. }
  618. } else if (argc == 4) {
  619. bool is_volatile = strtol(argv[2], NULL, 0);
  620. uint8_t status = strtol(argv[3], NULL, 0);
  621. result = sfud_write_status(sfud_dev, is_volatile, status);
  622. if (result == SFUD_SUCCESS) {
  623. rt_kprintf("Write the %s flash status register to 0x%02X success.\n", sfud_dev->name, status);
  624. }
  625. } else {
  626. rt_kprintf("Usage: %s.\n", sf_help_info[CMD_RW_STATUS_INDEX]);
  627. return;
  628. }
  629. } else if (!rt_strcmp(operator, "bench")) {
  630. if ((argc > 2 && rt_strcmp(argv[2], "yes")) || argc < 3) {
  631. rt_kprintf("DANGER: It will erase full chip! Please run 'sf bench yes'.\n");
  632. return;
  633. }
  634. /* full chip benchmark test */
  635. addr = 0;
  636. size = sfud_dev->chip.capacity;
  637. uint32_t start_time, time_cast;
  638. size_t write_size = SFUD_WRITE_MAX_PAGE_SIZE, read_size = SFUD_WRITE_MAX_PAGE_SIZE, cur_op_size;
  639. uint8_t *write_data = rt_malloc(write_size), *read_data = rt_malloc(read_size);
  640. if (write_data && read_data) {
  641. for (i = 0; i < write_size; i ++) {
  642. write_data[i] = i & 0xFF;
  643. }
  644. /* benchmark testing */
  645. rt_kprintf("Erasing the %s %ld bytes data, waiting...\n", sfud_dev->name, size);
  646. start_time = rt_tick_get();
  647. result = sfud_erase(sfud_dev, addr, size);
  648. if (result == SFUD_SUCCESS) {
  649. time_cast = rt_tick_get() - start_time;
  650. rt_kprintf("Erase benchmark success, total time: %ld.%03ldS.\n", time_cast / RT_TICK_PER_SECOND,
  651. time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
  652. } else {
  653. rt_kprintf("Erase benchmark has an error. Error code: %d.\n", result);
  654. }
  655. /* write test */
  656. rt_kprintf("Writing the %s %ld bytes data, waiting...\n", sfud_dev->name, size);
  657. start_time = rt_tick_get();
  658. for (i = 0; i < size; i += write_size) {
  659. if (i + write_size <= size) {
  660. cur_op_size = write_size;
  661. } else {
  662. cur_op_size = size - i;
  663. }
  664. result = sfud_write(sfud_dev, addr + i, cur_op_size, write_data);
  665. if (result != SFUD_SUCCESS) {
  666. rt_kprintf("Writing %s failed, already wr for %u bytes, write %d each time\n", sfud_dev->name, i, write_size);
  667. break;
  668. }
  669. }
  670. if (result == SFUD_SUCCESS) {
  671. time_cast = rt_tick_get() - start_time;
  672. rt_kprintf("Write benchmark success, total time: %ld.%03ldS.\n", time_cast / RT_TICK_PER_SECOND,
  673. time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
  674. } else {
  675. rt_kprintf("Write benchmark has an error. Error code: %d.\n", result);
  676. }
  677. /* read test */
  678. rt_kprintf("Reading the %s %ld bytes data, waiting...\n", sfud_dev->name, size);
  679. start_time = rt_tick_get();
  680. for (i = 0; i < size; i += read_size) {
  681. if (i + read_size <= size) {
  682. cur_op_size = read_size;
  683. } else {
  684. cur_op_size = size - i;
  685. }
  686. result = sfud_read(sfud_dev, addr + i, cur_op_size, read_data);
  687. /* data check */
  688. if (memcmp(write_data, read_data, cur_op_size))
  689. {
  690. rt_kprintf("Data check ERROR! Please check you flash by other command.\n");
  691. result = SFUD_ERR_READ;
  692. }
  693. if (result != SFUD_SUCCESS) {
  694. rt_kprintf("Read %s failed, already rd for %u bytes, read %d each time\n", sfud_dev->name, i, read_size);
  695. break;
  696. }
  697. }
  698. if (result == SFUD_SUCCESS) {
  699. time_cast = rt_tick_get() - start_time;
  700. rt_kprintf("Read benchmark success, total time: %ld.%03ldS.\n", time_cast / RT_TICK_PER_SECOND,
  701. time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
  702. } else {
  703. rt_kprintf("Read benchmark has an error. Error code: %d.\n", result);
  704. }
  705. } else {
  706. rt_kprintf("Low memory!\n");
  707. }
  708. rt_free(write_data);
  709. rt_free(read_data);
  710. } else {
  711. rt_kprintf("Usage:\n");
  712. for (i = 0; i < sizeof(sf_help_info) / sizeof(char*); i++) {
  713. rt_kprintf("%s\n", sf_help_info[i]);
  714. }
  715. rt_kprintf("\n");
  716. return;
  717. }
  718. if (result != SFUD_SUCCESS) {
  719. rt_kprintf("This flash operate has an error. Error code: %d.\n", result);
  720. }
  721. }
  722. }
  723. }
  724. MSH_CMD_EXPORT(sf, SPI Flash operate.);
  725. #endif /* defined(RT_USING_FINSH) */
  726. #endif /* RT_USING_SFUD */