dev_sflash.c 11 KB

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