spi_flash_sfud.c 30 KB

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