dev_sflash.c 9.8 KB

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