1
0

dev_sflash.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2011-05-06 onelife Initial creation by using USART module
  9. */
  10. /***************************************************************************//**
  11. * @addtogroup efm32
  12. * @{
  13. ******************************************************************************/
  14. /* Includes ------------------------------------------------------------------*/
  15. #include "board.h"
  16. #include "drv_usart.h"
  17. #include "dev_sflash.h"
  18. #if defined(EFM32_USING_SFLASH)
  19. /* Private typedef -------------------------------------------------------------*/
  20. typedef struct
  21. {
  22. rt_uint8_t code;
  23. rt_uint32_t address:24;
  24. rt_uint32_t dummy:8;
  25. } sflash_instruction;
  26. /* Private define --------------------------------------------------------------*/
  27. /* Private macro --------------------------------------------------------------*/
  28. #ifdef EFM32_SFLASH_DEBUG
  29. #define sflash_debug(format,args...) rt_kprintf(format, ##args)
  30. #else
  31. #define sflash_debug(format,args...)
  32. #endif
  33. /* Private constants -----------------------------------------------------------*/
  34. static rt_uint8_t sflash_inst_code_tbl[] =
  35. {
  36. /* Instruction only */
  37. SFLASH_INST_CODE_WREN,
  38. SFLASH_INST_CODE_WRDI,
  39. SFLASH_INST_CODE_RDID_L,
  40. SFLASH_INST_CODE_RDID_S,
  41. SFLASH_INST_CODE_RDSR,
  42. SFLASH_INST_CODE_WRSR,
  43. SFLASH_INST_CODE_BE,
  44. SFLASH_INST_CODE_DP,
  45. SFLASH_INST_CODE_RDP,
  46. /* Instruction and address */
  47. SFLASH_INST_CODE_WRLR,
  48. SFLASH_INST_CODE_RDLR,
  49. SFLASH_INST_CODE_READ,
  50. SFLASH_INST_CODE_POTP,
  51. SFLASH_INST_CODE_PP,
  52. SFLASH_INST_CODE_DIFP,
  53. SFLASH_INST_CODE_SSE,
  54. SFLASH_INST_CODE_SE,
  55. /* Instruction, address and dummy read */
  56. SFLASH_INST_CODE_READ_F,
  57. SFLASH_INST_CODE_DOFR,
  58. SFLASH_INST_CODE_ROTP
  59. };
  60. static rt_uint16_t sflash_data_len_tbl[] =
  61. {
  62. /* Instruction only */
  63. SFLASH_REPLY_LEN_WREN,
  64. SFLASH_REPLY_LEN_WRDI,
  65. SFLASH_REPLY_LEN_RDID_L,
  66. SFLASH_REPLY_LEN_RDID_S,
  67. SFLASH_REPLY_LEN_RDSR,
  68. SFLASH_REPLY_LEN_WRSR,
  69. SFLASH_REPLY_LEN_BE,
  70. SFLASH_REPLY_LEN_DP,
  71. SFLASH_REPLY_LEN_RDP,
  72. /* Instruction and address */
  73. SFLASH_REPLY_LEN_WRLR,
  74. SFLASH_REPLY_LEN_RDLR,
  75. SFLASH_REPLY_LEN_READ,
  76. SFLASH_REPLY_LEN_POTP,
  77. SFLASH_REPLY_LEN_PP,
  78. SFLASH_REPLY_LEN_DIFP,
  79. SFLASH_REPLY_LEN_SSE,
  80. SFLASH_REPLY_LEN_SE,
  81. /* Instruction, address and dummy read */
  82. SFLASH_REPLY_LEN_READ_F,
  83. SFLASH_REPLY_LEN_DOFR,
  84. SFLASH_REPLY_LEN_ROTP
  85. };
  86. static rt_bool_t sflash_read_inst_tbl[] =
  87. {
  88. /* Instruction only */
  89. false,
  90. false,
  91. true,
  92. true,
  93. true,
  94. false,
  95. false,
  96. false,
  97. false,
  98. /* Instruction and address */
  99. false,
  100. true,
  101. true,
  102. false,
  103. false,
  104. false,
  105. false,
  106. false,
  107. /* Instruction, address and dummy read */
  108. true,
  109. true,
  110. true
  111. };
  112. /* Private variables ------------------------------------------------------------*/
  113. static rt_device_t sFlash = RT_NULL;
  114. static rt_bool_t sFlashAutoCs = true;
  115. /* Private function prototypes ---------------------------------------------------*/
  116. /* Private functions ------------------------------------------------------------*/
  117. /******************************************************************//**
  118. * @brief
  119. * Initialize the SPI Flash
  120. *
  121. * @details
  122. *
  123. * @note
  124. *
  125. * @return
  126. * Error code
  127. *********************************************************************/
  128. rt_err_t efm_spiFlash_init(void)
  129. {
  130. struct efm32_usart_device_t *usart;
  131. usart = (struct efm32_usart_device_t *)(sFlash->user_data);
  132. #if defined(EFM32_GXXX_DK)
  133. /* Enable SPI access to Flash */
  134. DVK_writeRegister(BC_SPI_CFG, 0);
  135. #endif
  136. do
  137. {
  138. /* Find SPI device */
  139. sFlash = rt_device_find(SFLASH_USING_DEVICE_NAME);
  140. if (sFlash == RT_NULL)
  141. {
  142. sflash_debug("SFLASH: Can't find device %s!\n",
  143. SFLASH_USING_DEVICE_NAME);
  144. break;
  145. }
  146. sflash_debug("SFLASH: Find device %s\n", SFLASH_USING_DEVICE_NAME);
  147. /* Config chip slect pin */
  148. if (!(usart->state & USART_STATE_AUTOCS))
  149. {
  150. GPIO_PinModeSet(SFLASH_CS_PORT, SFLASH_CS_PIN, gpioModePushPull, 1);
  151. sFlashAutoCs = false;
  152. }
  153. /* Open SPI device */
  154. if (sFlash->open(sFlash, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
  155. {
  156. break;
  157. }
  158. return RT_EOK;
  159. } while(0);
  160. sflash_debug("SFLASH: Init failed!\n");
  161. return -RT_ERROR;
  162. }
  163. /******************************************************************//**
  164. * @brief
  165. * De-initialize the SPI Flash
  166. *
  167. * @details
  168. *
  169. * @note
  170. *
  171. * @return
  172. * Error code
  173. *********************************************************************/
  174. rt_err_t efm_spiFlash_deinit(void)
  175. {
  176. do
  177. {
  178. if (sFlash == RT_NULL)
  179. {
  180. sflash_debug("SFLASH: Already deinit!\n");
  181. break;
  182. }
  183. /* Close SPI device */
  184. if (sFlash->close(sFlash) != RT_EOK)
  185. {
  186. break;
  187. }
  188. sFlash = RT_NULL;
  189. sflash_debug("SFLASH: Close device %s\n", SFLASH_USING_DEVICE_NAME);
  190. return RT_EOK;
  191. } while(0);
  192. sflash_debug("SFLASH: Deinit failed!\n");
  193. return -RT_ERROR;
  194. }
  195. /******************************************************************//**
  196. * @brief
  197. * Set/Clear chip select
  198. *
  199. * @details
  200. *
  201. * @note
  202. *
  203. * @param[in] enable
  204. * Chip select pin setting
  205. *********************************************************************/
  206. static void efm_spiFlash_cs(rt_uint8_t enable)
  207. {
  208. if (!sFlashAutoCs)
  209. {
  210. if (enable)
  211. {
  212. GPIO_PinOutClear(SFLASH_CS_PORT, SFLASH_CS_PIN);
  213. }
  214. else
  215. {
  216. GPIO_PinOutSet(SFLASH_CS_PORT, SFLASH_CS_PIN);
  217. }
  218. }
  219. }
  220. /******************************************************************//**
  221. * @brief
  222. * Execute a command
  223. *
  224. * @details
  225. *
  226. * @note
  227. *
  228. * @param[in] command
  229. * SPI Flash instruction
  230. *
  231. * @param[in] address
  232. * Memory address
  233. *
  234. * @param[in] buffer
  235. * Poniter to the read/write buffer
  236. *
  237. * @param[in] size
  238. * Buffer size in byte
  239. *
  240. * @return
  241. * Number of read/written bytes
  242. *********************************************************************/
  243. rt_uint32_t efm_spiFlash_cmd(
  244. enum sflash_inst_type_t command,
  245. rt_uint32_t address,
  246. rt_uint8_t *buffer,
  247. rt_uint32_t size)
  248. {
  249. RT_ASSERT(sFlash != RT_NULL);
  250. sflash_instruction *inst;
  251. rt_uint8_t *inst_buf;
  252. rt_uint8_t inst_len, head_len;
  253. rt_uint32_t data_len;
  254. sflash_debug("SFLASH: Inst %x\n", sflash_inst_code_tbl[command]);
  255. if (sflash_data_len_tbl[command] && !size)
  256. {
  257. sflash_debug("SFLASH: No data!\n");
  258. return 0x00;
  259. }
  260. data_len = (sflash_data_len_tbl[command] < size)? \
  261. sflash_data_len_tbl[command] : size;
  262. if (data_len && (buffer == RT_NULL))
  263. {
  264. sflash_debug("SFLASH: No buffer specified!\n");
  265. return 0x00;
  266. }
  267. /* Allocate memory for write buffer */
  268. if (sflash_read_inst_tbl[command])
  269. {
  270. inst_buf = rt_malloc(6 + 4);
  271. inst = (sflash_instruction *)(inst_buf + 1);
  272. head_len = 1;
  273. }
  274. else
  275. {
  276. inst_buf = rt_malloc(5 + data_len);
  277. inst = (sflash_instruction *)inst_buf;
  278. head_len = 0;
  279. }
  280. /* Fill in instruction */
  281. inst->code = sflash_inst_code_tbl[command];
  282. if (command >= sflash_inst_wrlr)
  283. {
  284. /* MSB first */
  285. inst->address = ((address & 0x000000FF) << 16) | \
  286. (address & 0x0000FF00) | \
  287. ((address & 0x00FF0000) >> 16);
  288. if (command >= sflash_inst_read_f)
  289. {
  290. inst->dummy = 0x00;
  291. inst_len = 5;
  292. }
  293. else
  294. {
  295. inst_len = 4;
  296. }
  297. }
  298. else
  299. {
  300. inst_len = 1;
  301. }
  302. head_len += inst_len;
  303. /* Fill in data and send the buffer */
  304. if (sflash_read_inst_tbl[command])
  305. {
  306. rt_off_t skip;
  307. inst_buf[0] = inst_len;
  308. *(rt_uint8_t **)(inst_buf + head_len) = buffer;
  309. if (command == sflash_inst_read)
  310. {
  311. skip = SFLASH_SPI_READ_SKIP;
  312. }
  313. else
  314. {
  315. skip = SFLASH_SPI_COMMAND_SKIP;
  316. }
  317. efm_spiFlash_cs(1);
  318. if (sFlash->read(sFlash, skip, inst_buf, \
  319. (data_len == size)? data_len - 1 : data_len) == 0)
  320. {
  321. sflash_debug("SFLASH: Read failed!\n");
  322. return 0x00;
  323. }
  324. efm_spiFlash_cs(0);
  325. buffer[data_len] = 0x00;
  326. sflash_debug("SFLASH: Read %d bytes data to 0x%x\n", data_len, buffer);
  327. }
  328. else
  329. {
  330. if (data_len)
  331. {
  332. rt_memcpy((inst_buf + head_len), buffer, data_len);
  333. }
  334. efm_spiFlash_cs(1);
  335. if (sFlash->write(sFlash, EFM32_NO_DATA, inst_buf, \
  336. head_len + data_len) == 0)
  337. {
  338. sflash_debug("SFLASH: Write failed!\n");
  339. return 0x00;
  340. }
  341. efm_spiFlash_cs(0);
  342. sflash_debug("SFLASH: Write %d/%d bytes data\n", data_len, \
  343. head_len + data_len);
  344. }
  345. /* Free the buffer */
  346. rt_free(inst_buf);
  347. return data_len;
  348. }
  349. /*********************************************************************
  350. * Export to FINSH
  351. *********************************************************************/
  352. #ifdef RT_USING_FINSH
  353. #include <finsh.h>
  354. void list_sflash(void)
  355. {
  356. rt_uint8_t buf[4];
  357. efm_spiFlash_cmd(sflash_inst_rdid_s, EFM32_NO_DATA, buf, sizeof(buf));
  358. rt_kprintf(" spi flash on %s\n", SFLASH_USING_DEVICE_NAME);
  359. rt_kprintf(" ------------------------------\n");
  360. rt_kprintf(" Manufacturer ID:\t%x\n", buf[0]);
  361. rt_kprintf(" Memory type:\t\t%x\n", buf[1]);
  362. rt_kprintf(" Memory capacity:\t%x\n", buf[2]);
  363. }
  364. FINSH_FUNCTION_EXPORT(list_sflash, list the SPI Flash.)
  365. #endif
  366. #endif /* defined(EFM32_USING_SFLASH) */
  367. /******************************************************************//**
  368. * @}
  369. *********************************************************************/