dev_sflash.c 9.8 KB

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