nu_spim.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308
  1. /**************************************************************************//**
  2. * @file spim.c
  3. * @version V1.00
  4. * @brief M480 series SPIM driver
  5. *
  6. * SPDX-License-Identifier: Apache-2.0
  7. * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
  8. *****************************************************************************/
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include "NuMicro.h"
  12. /** @addtogroup Standard_Driver Standard Driver
  13. @{
  14. */
  15. /** @addtogroup SPIM_Driver SPIM Driver
  16. @{
  17. */
  18. /** @addtogroup SPIM_EXPORTED_FUNCTIONS SPIM Exported Functions
  19. @{
  20. */
  21. /** @cond HIDDEN_SYMBOLS */
  22. #define ENABLE_DEBUG 0
  23. #if ENABLE_DEBUG
  24. #define SPIM_DBGMSG printf
  25. #else
  26. #define SPIM_DBGMSG(...) do { } while (0) /* disable debug */
  27. #endif
  28. static volatile uint8_t g_Supported_List[] =
  29. {
  30. MFGID_WINBOND,
  31. MFGID_MXIC,
  32. MFGID_EON,
  33. MFGID_ISSI,
  34. MFGID_SPANSION
  35. };
  36. static void N_delay(int n);
  37. static void SwitchNBitOutput(uint32_t u32NBit);
  38. static void SwitchNBitInput(uint32_t u32NBit);
  39. static void spim_write(uint8_t pu8TxBuf[], uint32_t u32NTx);
  40. static void spim_read(uint8_t pu8RxBuf[], uint32_t u32NRx);
  41. static void SPIM_WriteStatusRegister(uint8_t dataBuf[], uint32_t u32NTx, uint32_t u32NBit);
  42. static void SPIM_ReadStatusRegister(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit);
  43. static void SPIM_ReadStatusRegister2(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit);
  44. static void SPIM_WriteStatusRegister2(uint8_t dataBuf[], uint32_t u32NTx, uint32_t u32NBit);
  45. static void SPIM_ReadStatusRegister3(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit);
  46. static void SPIM_ReadSecurityRegister(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit);
  47. static int spim_is_write_done(uint32_t u32NBit);
  48. static int spim_wait_write_done(uint32_t u32NBit);
  49. static void spim_set_write_enable(int isEn, uint32_t u32NBit);
  50. static void spim_enable_spansion_quad_mode(int isEn);
  51. static void spim_eon_set_qpi_mode(int isEn);
  52. static void SPIM_SPANSION_4Bytes_Enable(int isEn, uint32_t u32NBit);
  53. static void SPIM_WriteInPageDataByIo(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NTx, uint8_t pu8TxBuf[], uint8_t wrCmd,
  54. uint32_t u32NBitCmd, uint32_t u32NBitAddr, uint32_t u32NBitDat, int isSync);
  55. static void SPIM_WriteInPageDataByPageWrite(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NTx,
  56. uint8_t pu8TxBuf[], uint32_t wrCmd, int isSync);
  57. static void N_delay(int n)
  58. {
  59. while (n-- > 0)
  60. {
  61. __NOP();
  62. }
  63. }
  64. static void SwitchNBitOutput(uint32_t u32NBit)
  65. {
  66. switch (u32NBit)
  67. {
  68. case 1UL:
  69. SPIM_ENABLE_SING_OUTPUT_MODE(); /* 1-bit, Output. */
  70. break;
  71. case 2UL:
  72. SPIM_ENABLE_DUAL_OUTPUT_MODE(); /* 2-bit, Output. */
  73. break;
  74. case 4UL:
  75. SPIM_ENABLE_QUAD_OUTPUT_MODE(); /* 4-bit, Output. */
  76. break;
  77. default:
  78. break;
  79. }
  80. }
  81. static void SwitchNBitInput(uint32_t u32NBit)
  82. {
  83. switch (u32NBit)
  84. {
  85. case 1UL:
  86. SPIM_ENABLE_SING_INPUT_MODE(); /* 1-bit, Input. */
  87. break;
  88. case 2UL:
  89. SPIM_ENABLE_DUAL_INPUT_MODE(); /* 2-bit, Input. */
  90. break;
  91. case 4UL:
  92. SPIM_ENABLE_QUAD_INPUT_MODE(); /* 4-bit, Input. */
  93. break;
  94. default:
  95. break;
  96. }
  97. }
  98. /**
  99. * @brief Write data to SPI slave.
  100. * @param pu8TxBuf Transmit buffer.
  101. * @param u32NTx Number of bytes to transmit.
  102. * @return None.
  103. */
  104. static void spim_write(uint8_t pu8TxBuf[], uint32_t u32NTx)
  105. {
  106. uint32_t buf_idx = 0UL;
  107. while (u32NTx)
  108. {
  109. uint32_t dataNum = 0UL, dataNum2;
  110. if (u32NTx >= 16UL)
  111. {
  112. dataNum = 4UL;
  113. }
  114. else if (u32NTx >= 12UL)
  115. {
  116. dataNum = 3UL;
  117. }
  118. else if (u32NTx >= 8UL)
  119. {
  120. dataNum = 2UL;
  121. }
  122. else if (u32NTx >= 4UL)
  123. {
  124. dataNum = 1UL;
  125. }
  126. dataNum2 = dataNum;
  127. while (dataNum2)
  128. {
  129. uint32_t tmp;
  130. memcpy(&tmp, &pu8TxBuf[buf_idx], 4U);
  131. buf_idx += 4UL;
  132. u32NTx -= 4UL;
  133. dataNum2 --;
  134. /* *((__O uint32_t *) &SPIM->TX0 + dataNum2) = tmp; */
  135. SPIM->TX[dataNum2] = tmp;
  136. }
  137. if (dataNum)
  138. {
  139. SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_IO); /* Switch to Normal mode. */
  140. SPIM_SET_DATA_WIDTH(32UL);
  141. SPIM_SET_DATA_NUM(dataNum);
  142. SPIM_SET_GO();
  143. SPIM_WAIT_FREE();
  144. }
  145. if (u32NTx && (u32NTx < 4UL))
  146. {
  147. uint32_t rnm, tmp;
  148. rnm = u32NTx;
  149. memcpy(&tmp, &pu8TxBuf[buf_idx], u32NTx);
  150. buf_idx += u32NTx;
  151. u32NTx = 0UL;
  152. SPIM->TX[0] = tmp;
  153. SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_IO); /* Switch to Normal mode. */
  154. SPIM_SET_DATA_WIDTH(rnm * 8UL);
  155. SPIM_SET_DATA_NUM(1UL);
  156. SPIM_SET_GO();
  157. SPIM_WAIT_FREE();
  158. }
  159. }
  160. }
  161. /**
  162. * @brief Read data from SPI slave.
  163. * @param pu8TxBuf Receive buffer.
  164. * @param u32NRx Size of receive buffer in bytes.
  165. * @return None.
  166. */
  167. static void spim_read(uint8_t pu8RxBuf[], uint32_t u32NRx)
  168. {
  169. uint32_t buf_idx = 0UL;
  170. while (u32NRx)
  171. {
  172. uint32_t dataNum = 0UL; /* number of words */
  173. if (u32NRx >= 16UL)
  174. {
  175. dataNum = 4UL;
  176. }
  177. else if (u32NRx >= 12UL)
  178. {
  179. dataNum = 3UL;
  180. }
  181. else if (u32NRx >= 8UL)
  182. {
  183. dataNum = 2UL;
  184. }
  185. else if (u32NRx >= 4UL)
  186. {
  187. dataNum = 1UL;
  188. }
  189. if (dataNum)
  190. {
  191. SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_IO); /* Switch to Normal mode. */
  192. SPIM_SET_DATA_WIDTH(32UL);
  193. SPIM_SET_DATA_NUM(dataNum);
  194. SPIM_SET_GO();
  195. SPIM_WAIT_FREE();
  196. }
  197. while (dataNum)
  198. {
  199. uint32_t tmp;
  200. tmp = SPIM->RX[dataNum-1UL];
  201. memcpy(&pu8RxBuf[buf_idx], &tmp, 4U);
  202. buf_idx += 4UL;
  203. dataNum --;
  204. u32NRx -= 4UL;
  205. }
  206. if (u32NRx && (u32NRx < 4UL))
  207. {
  208. uint32_t tmp;
  209. SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_IO); /* Switch to Normal mode. */
  210. SPIM_SET_DATA_WIDTH(u32NRx * 8UL);
  211. SPIM_SET_DATA_NUM(1UL);
  212. SPIM_SET_GO();
  213. SPIM_WAIT_FREE();
  214. tmp = SPIM->RX[0];
  215. memcpy(&pu8RxBuf[buf_idx], &tmp, u32NRx);
  216. buf_idx += u32NRx;
  217. u32NRx = 0UL;
  218. }
  219. }
  220. }
  221. /**
  222. * @brief Issue Read Status Register #1 command.
  223. * @param dataBuf Receive buffer.
  224. * @param u32NRx Size of receive buffer.
  225. * @param u32NBit N-bit transmit/receive.
  226. * @return None.
  227. */
  228. static void SPIM_ReadStatusRegister(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit)
  229. {
  230. uint8_t cmdBuf[] = {OPCODE_RDSR}; /* 1-byte Read Status Register #1 command. */
  231. SPIM_SET_SS_EN(1); /* CS activated. */
  232. SwitchNBitOutput(u32NBit);
  233. spim_write(cmdBuf, sizeof (cmdBuf));
  234. SwitchNBitInput(u32NBit);
  235. spim_read(dataBuf, u32NRx);
  236. SPIM_SET_SS_EN(0); /* CS deactivated. */
  237. }
  238. /**
  239. * @brief Issue Write Status Register #1 command.
  240. * @param dataBuf Transmit buffer.
  241. * @param u32NTx Size of transmit buffer.
  242. * @param u32NBit N-bit transmit/receive.
  243. * @return None.
  244. */
  245. static void SPIM_WriteStatusRegister(uint8_t dataBuf[], uint32_t u32NTx, uint32_t u32NBit)
  246. {
  247. uint8_t cmdBuf[] = {OPCODE_WRSR, 0x00U}; /* 1-byte Write Status Register #1 command + 1-byte data. */
  248. cmdBuf[1] = dataBuf[0];
  249. SPIM_SET_SS_EN(1); /* CS activated. */
  250. SwitchNBitOutput(u32NBit);
  251. spim_write(cmdBuf, sizeof (cmdBuf));
  252. SPIM_SET_SS_EN(0); /* CS deactivated. */
  253. }
  254. /**
  255. * @brief Issue Read Status Register #2 command.
  256. * @param dataBuf Receive buffer.
  257. * @param u32NRx Size of receive buffer.
  258. * @param u32NBit N-bit transmit/receive.
  259. * @return None.
  260. */
  261. static void SPIM_ReadStatusRegister2(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit)
  262. {
  263. uint8_t cmdBuf[] = {OPCODE_RDSR2}; /* 1-byte Read Status Register #1 command. */
  264. SPIM_SET_SS_EN(1); /* CS activated. */
  265. SwitchNBitOutput(u32NBit);
  266. spim_write(cmdBuf, sizeof (cmdBuf));
  267. SwitchNBitInput(u32NBit);
  268. spim_read(dataBuf, u32NRx);
  269. SPIM_SET_SS_EN(0); /* CS deactivated. */
  270. }
  271. /**
  272. * @brief Issue Winbond Write Status Register command. This command write both Status Register-1
  273. * and Status Register-2.
  274. * @param dataBuf Transmit buffer.
  275. * @param u32NTx Size of transmit buffer.
  276. * @param u32NBit N-bit transmit/receive.
  277. * @return None.
  278. */
  279. static void SPIM_WriteStatusRegister2(uint8_t dataBuf[], uint32_t u32NTx, uint32_t u32NBit)
  280. {
  281. uint8_t cmdBuf[3] = {OPCODE_WRSR, 0U, 0U};
  282. cmdBuf[1] = dataBuf[0];
  283. cmdBuf[2] = dataBuf[1];
  284. SPIM_SET_SS_EN(1); /* CS activated. */
  285. SwitchNBitOutput(u32NBit);
  286. spim_write(cmdBuf, sizeof (cmdBuf));
  287. SPIM_SET_SS_EN(0); /* CS deactivated. */
  288. }
  289. #if 0 /* not used */
  290. /**
  291. * @brief Issue Write Status Register #3 command.
  292. * @param dataBuf Transmit buffer.
  293. * @param u32NTx Size of transmit buffer.
  294. * @param u32NBit N-bit transmit/receive.
  295. * @return None.
  296. */
  297. static void SPIM_WriteStatusRegister3(uint8_t dataBuf[], uint32_t u32NTx, uint32_t u32NBit)
  298. {
  299. uint8_t cmdBuf[] = {OPCODE_WRSR3, 0x00U}; /* 1-byte Write Status Register #2 command + 1-byte data. */
  300. cmdBuf[1] = dataBuf[0];
  301. SPIM_SET_SS_EN(1); /* CS activated. */
  302. SwitchNBitOutput(u32NBit);
  303. spim_write(cmdBuf, sizeof (cmdBuf));
  304. SPIM_SET_SS_EN(0); /* CS deactivated. */
  305. }
  306. #endif
  307. /**
  308. * @brief Issue Read Status Register #3 command.
  309. * @param dataBuf Receive buffer.
  310. * @param u32NRx Size of receive buffer.
  311. * @param u32NBit N-bit transmit/receive.
  312. * @return None.
  313. */
  314. static void SPIM_ReadStatusRegister3(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit)
  315. {
  316. uint8_t cmdBuf[] = {OPCODE_RDSR3}; /* 1-byte Read Status Register #1 command. */
  317. SPIM_SET_SS_EN(1); /* CS activated. */
  318. SwitchNBitOutput(u32NBit);
  319. spim_write(cmdBuf, sizeof (cmdBuf));
  320. SwitchNBitInput(u32NBit);
  321. spim_read(dataBuf, u32NRx);
  322. SPIM_SET_SS_EN(0); /* CS deactivated. */
  323. }
  324. #if 0 /* not used */
  325. /**
  326. * @brief Issue Write Security Register command.
  327. * @param dataBuf Transmit buffer.
  328. * @param u32NTx Size of transmit buffer.
  329. * @param u32NBit N-bit transmit/receive.
  330. * @return None.
  331. */
  332. static void SPIM_WriteSecurityRegister(uint8_t dataBuf[], uint32_t u32NTx, uint32_t u32NBit)
  333. {
  334. uint8_t cmdBuf[] = {OPCODE_WRSCUR, 0x00U}; /* 1-byte Write Status Register #2 command + 1-byte data. */
  335. cmdBuf[1] = dataBuf[0];
  336. SPIM_SET_SS_EN(1); /* CS activated. */
  337. SwitchNBitOutput(u32NBit);
  338. spim_write(cmdBuf, sizeof (cmdBuf));
  339. SPIM_SET_SS_EN(0); /* CS deactivated. */
  340. }
  341. #endif
  342. /**
  343. * @brief Issue Read Security Register command.
  344. * @param dataBuf Receive buffer.
  345. * @param u32NRx Size of receive buffer.
  346. * @param u32NBit N-bit transmit/receive.
  347. * @return None.
  348. */
  349. static void SPIM_ReadSecurityRegister(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit)
  350. {
  351. uint8_t cmdBuf[] = {OPCODE_RDSCUR}; /* 1-byte Read Status Register #1 command. */
  352. SPIM_SET_SS_EN(1); /* CS activated. */
  353. SwitchNBitOutput(u32NBit);
  354. spim_write(cmdBuf, sizeof (cmdBuf));
  355. SwitchNBitInput(u32NBit);
  356. spim_read(dataBuf, u32NRx);
  357. SPIM_SET_SS_EN(0); /* CS deactivated. */
  358. }
  359. /**
  360. * @brief Check if Erase/Write is done.
  361. * @return 0: Not done. 1: Done.
  362. */
  363. static int spim_is_write_done(uint32_t u32NBit)
  364. {
  365. uint8_t status[1];
  366. SPIM_ReadStatusRegister(status, sizeof (status), u32NBit);
  367. return ! (status[0] & SR_WIP);
  368. }
  369. /**
  370. * @brief Wait until Erase/Write done.
  371. * @param u32NBit N-bit transmit/receive.
  372. * @return 0 SPIM write done.
  373. */
  374. static int spim_wait_write_done(uint32_t u32NBit)
  375. {
  376. uint32_t count;
  377. int ret = -1;
  378. for (count = 0UL; count < SystemCoreClock/1000UL; count++)
  379. {
  380. if (spim_is_write_done(u32NBit))
  381. {
  382. ret = 0;
  383. break;
  384. }
  385. }
  386. if (ret != 0)
  387. {
  388. SPIM_DBGMSG("spim_wait_write_done time-out!!\n");
  389. }
  390. return ret;
  391. }
  392. /**
  393. * @brief Issue Write Enable/disable command.
  394. * @param isEn Enable/disable.
  395. * @param u32NBit N-bit transmit/receive.
  396. * @return None.
  397. */
  398. static void spim_set_write_enable(int isEn, uint32_t u32NBit)
  399. {
  400. uint8_t cmdBuf[] = {0U}; /* 1-byte Write Enable command. */
  401. cmdBuf[0] = isEn ? OPCODE_WREN : OPCODE_WRDI;
  402. SPIM_SET_SS_EN(1); /* CS activated. */
  403. SwitchNBitOutput(u32NBit);
  404. spim_write(cmdBuf, sizeof (cmdBuf));
  405. SPIM_SET_SS_EN(0); /* CS deactivated. */
  406. }
  407. /** @endcond HIDDEN_SYMBOLS */
  408. /**
  409. * @brief Get SPIM serial clock.
  410. * @return SPI serial clock.
  411. * @details This function calculates the serial clock of SPI in Hz.
  412. */
  413. uint32_t SPIM_GetSClkFreq(void)
  414. {
  415. uint32_t clkDiv = SPIM_GET_CLOCK_DIVIDER();
  416. return clkDiv ? SystemCoreClock / (clkDiv * 2U) : SystemCoreClock;
  417. }
  418. /**
  419. * @brief Initialize SPIM flash.
  420. * @param clrWP Clear Write Protect or not.
  421. * @return 0 Success.
  422. * @return -1 Unrecognized manufacture ID or failed on reading manufacture ID.
  423. */
  424. int SPIM_InitFlash(int clrWP)
  425. {
  426. uint8_t idBuf[3];
  427. uint8_t cmdBuf[1];
  428. uint32_t i;
  429. int32_t ret = -1;
  430. SPIM_SET_SS_ACTLVL(0);
  431. /*
  432. * Because not sure in SPI or QPI mode, do QPI reset and then SPI reset.
  433. */
  434. /* QPI Reset Enable */
  435. cmdBuf[0] = OPCODE_RSTEN;
  436. SPIM_SET_SS_EN(1); /* CS activated. */
  437. SPIM_ENABLE_QUAD_OUTPUT_MODE(); /* 1-bit, Output. */
  438. spim_write(cmdBuf, sizeof (cmdBuf));
  439. SPIM_SET_SS_EN(0); /* CS deactivated. */
  440. /* QPI Reset */
  441. cmdBuf[0] = OPCODE_RST;
  442. SPIM_SET_SS_EN(1); /* CS activated. */
  443. SPIM_ENABLE_QUAD_OUTPUT_MODE(); /* 1-bit, Output. */
  444. spim_write(cmdBuf, sizeof (cmdBuf));
  445. SPIM_SET_SS_EN(0); /* CS deactivated. */
  446. /* SPI ResetEnable */
  447. cmdBuf[0] = OPCODE_RSTEN;
  448. SPIM_SET_SS_EN(1); /* CS activated. */
  449. SPIM_ENABLE_SING_OUTPUT_MODE(); /* 1-bit, Output. */
  450. spim_write(cmdBuf, sizeof (cmdBuf));
  451. SPIM_SET_SS_EN(0); /* CS deactivated. */
  452. /* SPI Reset */
  453. cmdBuf[0] = OPCODE_RST;
  454. SPIM_SET_SS_EN(1); /* CS activated. */
  455. SPIM_ENABLE_SING_OUTPUT_MODE(); /* 1-bit, Output. */
  456. spim_write(cmdBuf, sizeof (cmdBuf));
  457. SPIM_SET_SS_EN(0); /* CS deactivated. */
  458. if (clrWP)
  459. {
  460. uint8_t dataBuf[] = {0x00U};
  461. spim_set_write_enable(1, 1UL); /* Clear Block Protect. */
  462. SPIM_WriteStatusRegister(dataBuf, sizeof (dataBuf), 1U);
  463. spim_wait_write_done(1UL);
  464. }
  465. SPIM_ReadJedecId(idBuf, sizeof (idBuf), 1UL);
  466. /* printf("ID: 0x%x, 0x%x, px%x\n", idBuf[0], idBuf[1], idBuf[2]); */
  467. for (i = 0UL; i < sizeof(g_Supported_List)/sizeof(g_Supported_List[0]); i++)
  468. {
  469. if (idBuf[0] == g_Supported_List[i])
  470. {
  471. ret = 0;
  472. }
  473. }
  474. if (ret != 0)
  475. {
  476. SPIM_DBGMSG("Flash initialize failed!! 0x%x\n", idBuf[0]);
  477. }
  478. return ret;
  479. }
  480. /**
  481. * @brief Issue JEDEC ID command.
  482. * @param idBuf ID buffer.
  483. * @param u32NRx Size of ID buffer.
  484. * @param u32NBit N-bit transmit/receive.
  485. * @return None.
  486. */
  487. void SPIM_ReadJedecId(uint8_t idBuf[], uint32_t u32NRx, uint32_t u32NBit)
  488. {
  489. uint8_t cmdBuf[] = { OPCODE_RDID }; /* 1-byte JEDEC ID command. */
  490. SPIM_SET_SS_EN(1); /* CS activated. */
  491. SwitchNBitOutput(u32NBit);
  492. spim_write(cmdBuf, sizeof (cmdBuf));
  493. SwitchNBitInput(u32NBit);
  494. spim_read(idBuf, u32NRx);
  495. SPIM_SET_SS_EN(0); /* CS deactivated. */
  496. }
  497. /** @cond HIDDEN_SYMBOLS */
  498. static void spim_enable_spansion_quad_mode(int isEn)
  499. {
  500. uint8_t cmdBuf[3];
  501. uint8_t dataBuf[1], status1;
  502. cmdBuf[0] = 0x5U; /* Read Status Register-1 */
  503. SPIM_SET_SS_EN(1);
  504. SwitchNBitOutput(1UL);
  505. spim_write(cmdBuf, sizeof (cmdBuf));
  506. SwitchNBitInput(1UL);
  507. spim_read(dataBuf, sizeof (dataBuf));
  508. SPIM_SET_SS_EN(0);
  509. /* SPIM_DBGMSG("SR1 = 0x%x\n", dataBuf[0]); */
  510. status1 = dataBuf[0];
  511. cmdBuf[0] = 0x35U; /* Read Configuration Register-1 */
  512. SPIM_SET_SS_EN(1);
  513. SwitchNBitOutput(1UL);
  514. spim_write(cmdBuf, sizeof (cmdBuf));
  515. SwitchNBitInput(1UL);
  516. spim_read(dataBuf, sizeof (dataBuf));
  517. SPIM_SET_SS_EN(0);
  518. /* SPIM_DBGMSG("CR1 = 0x%x\n", dataBuf[0]); */
  519. spim_set_write_enable(1, 1UL);
  520. cmdBuf[0] = 0x1U; /* Write register */
  521. cmdBuf[1] = status1;
  522. if (isEn)
  523. {
  524. cmdBuf[2] = dataBuf[0] | 0x2U; /* set QUAD */
  525. }
  526. else
  527. {
  528. cmdBuf[2] = dataBuf[0] & ~0x2U; /* clear QUAD */
  529. }
  530. SPIM_SET_SS_EN(1);
  531. SwitchNBitOutput(1UL);
  532. spim_write(cmdBuf, 3UL);
  533. SPIM_SET_SS_EN(0);
  534. spim_set_write_enable(0, 1UL);
  535. cmdBuf[0] = 0x35U; /* Read Configuration Register-1 */
  536. SPIM_SET_SS_EN(1);
  537. SwitchNBitOutput(1UL);
  538. spim_write(cmdBuf, sizeof (cmdBuf));
  539. SwitchNBitInput(1UL);
  540. spim_read(dataBuf, sizeof (dataBuf));
  541. SPIM_SET_SS_EN(0);
  542. /* SPIM_DBGMSG("CR1 = 0x%x\n", dataBuf[0]); */
  543. N_delay(10000);
  544. }
  545. /** @endcond HIDDEN_SYMBOLS */
  546. /**
  547. * @brief Set Quad Enable/disable.
  548. * @param isEn Enable/disable.
  549. * @param u32NBit N-bit transmit/receive.
  550. * @return None.
  551. */
  552. void SPIM_SetQuadEnable(int isEn, uint32_t u32NBit)
  553. {
  554. uint8_t idBuf[3];
  555. uint8_t dataBuf[2];
  556. SPIM_ReadJedecId(idBuf, sizeof (idBuf), u32NBit);
  557. SPIM_DBGMSG("SPIM_SetQuadEnable - Flash ID is 0x%x\n", idBuf[0]);
  558. switch (idBuf[0])
  559. {
  560. case MFGID_WINBOND: /* Winbond SPI flash */
  561. SPIM_ReadStatusRegister(&dataBuf[0], 1UL, u32NBit);
  562. SPIM_ReadStatusRegister2(&dataBuf[1], 1UL, u32NBit);
  563. SPIM_DBGMSG("Status Register: 0x%x - 0x%x\n", dataBuf[0], dataBuf[1]);
  564. if (isEn)
  565. {
  566. dataBuf[1] |= SR2_QE;
  567. }
  568. else
  569. {
  570. dataBuf[1] &= ~SR2_QE;
  571. }
  572. spim_set_write_enable(1, u32NBit); /* Write Enable. */
  573. SPIM_WriteStatusRegister2(dataBuf, sizeof (dataBuf), u32NBit);
  574. spim_wait_write_done(u32NBit);
  575. SPIM_ReadStatusRegister(&dataBuf[0], 1UL, u32NBit);
  576. SPIM_ReadStatusRegister2(&dataBuf[1], 1UL, u32NBit);
  577. SPIM_DBGMSG("Status Register: 0x%x - 0x%x\n", dataBuf[0], dataBuf[1]);
  578. break;
  579. case MFGID_MXIC: /* MXIC SPI flash. */
  580. case MFGID_EON:
  581. case MFGID_ISSI: /* ISSI SPI flash. */
  582. spim_set_write_enable(1, u32NBit); /* Write Enable. */
  583. dataBuf[0] = isEn ? SR_QE : 0U;
  584. SPIM_WriteStatusRegister(dataBuf, sizeof (dataBuf), u32NBit);
  585. spim_wait_write_done(u32NBit);
  586. break;
  587. case MFGID_SPANSION:
  588. spim_enable_spansion_quad_mode(isEn);
  589. break;
  590. default:
  591. break;
  592. }
  593. }
  594. /**
  595. * @brief Enter/exit QPI mode.
  596. * @param isEn Enable/disable.
  597. * @return None.
  598. */
  599. static void spim_eon_set_qpi_mode(int isEn)
  600. {
  601. uint8_t cmdBuf[1]; /* 1-byte command. */
  602. uint8_t status[1];
  603. SPIM_ReadStatusRegister(status, sizeof (status), 1UL);
  604. SPIM_DBGMSG("Status: 0x%x\n", status[0]);
  605. if (isEn) /* Assume in SPI mode. */
  606. {
  607. cmdBuf[0] = OPCODE_ENQPI;
  608. SPIM_SET_SS_EN(1); /* CS activated. */
  609. SwitchNBitOutput(1UL);
  610. spim_write(cmdBuf, sizeof (cmdBuf));
  611. SPIM_SET_SS_EN(0); /* CS deactivated. */
  612. }
  613. else /* Assume in QPI mode. */
  614. {
  615. cmdBuf[0] = OPCODE_EXQPI;
  616. SPIM_SET_SS_EN(1); /* CS activated. */
  617. SwitchNBitOutput(4UL);
  618. spim_write(cmdBuf, sizeof (cmdBuf));
  619. SPIM_SET_SS_EN(0); /* CS deactivated. */
  620. }
  621. SPIM_ReadStatusRegister(status, sizeof (status), 1UL);
  622. SPIM_DBGMSG("Status: 0x%x\n", status[0]);
  623. }
  624. static void SPIM_SPANSION_4Bytes_Enable(int isEn, uint32_t u32NBit)
  625. {
  626. uint8_t cmdBuf[2];
  627. uint8_t dataBuf[1];
  628. cmdBuf[0] = OPCODE_BRRD;
  629. SPIM_SET_SS_EN(1); /* CS activated. */
  630. SwitchNBitOutput(u32NBit);
  631. spim_write(cmdBuf, 1UL);
  632. SwitchNBitInput(1UL);
  633. spim_read(dataBuf, 1UL);
  634. SPIM_SET_SS_EN(0); /* CS deactivated. */
  635. SPIM_DBGMSG("Bank Address register= 0x%x\n", dataBuf[0]);
  636. cmdBuf[0] = OPCODE_BRWR;
  637. if (isEn)
  638. {
  639. cmdBuf[1] = dataBuf[0] | 0x80U; /* set EXTADD */
  640. }
  641. else
  642. {
  643. cmdBuf[1] = dataBuf[0] & ~0x80U; /* clear EXTADD */
  644. }
  645. SPIM_SET_SS_EN(1); /* CS activated. */
  646. SwitchNBitOutput(1UL);
  647. spim_write(cmdBuf, 2UL);
  648. SPIM_SET_SS_EN(0); /* CS deactivated. */
  649. }
  650. /** @cond HIDDEN_SYMBOLS */
  651. /**
  652. * @brief Query 4-byte address mode enabled or not.
  653. * @param u32NBit N-bit transmit/receive.
  654. * @return 0: 4-byte address mode disabled. 1: 4-byte address mode enabled.
  655. */
  656. int SPIM_Is4ByteModeEnable(uint32_t u32NBit)
  657. {
  658. int isEn = 0;
  659. int isSupt = 0;
  660. uint8_t idBuf[3];
  661. uint8_t dataBuf[1];
  662. SPIM_ReadJedecId(idBuf, sizeof (idBuf), u32NBit);
  663. /* Based on Flash size, check if 4-byte address mode is supported. */
  664. switch (idBuf[0])
  665. {
  666. case MFGID_WINBOND:
  667. case MFGID_MXIC:
  668. case MFGID_EON:
  669. isSupt = (idBuf[2] < 0x19U) ? 0L : 1L;
  670. break;
  671. case MFGID_ISSI:
  672. isSupt = (idBuf[2] < 0x49U) ? 0L : 1L;
  673. break;
  674. default:
  675. break;
  676. }
  677. if (isSupt != 0)
  678. {
  679. if (idBuf[0] == MFGID_WINBOND)
  680. {
  681. /* Winbond SPI flash. */
  682. SPIM_ReadStatusRegister3(dataBuf, sizeof (dataBuf), u32NBit);
  683. isEn = !! (dataBuf[0] & SR3_ADR);
  684. }
  685. else if ((idBuf[0] == MFGID_MXIC) || (idBuf[0] ==MFGID_EON))
  686. {
  687. /* MXIC/EON SPI flash. */
  688. SPIM_ReadSecurityRegister(dataBuf, sizeof (dataBuf), u32NBit);
  689. isEn = !! (dataBuf[0] & SCUR_4BYTE);
  690. }
  691. }
  692. return isEn;
  693. }
  694. /** @endcond HIDDEN_SYMBOLS */
  695. /**
  696. * @brief Enter/Exit 4-byte address mode.
  697. * @param isEn Enable/disable.
  698. * @param u32NBit N-bit transmit/receive.
  699. * @return 0 success
  700. * -1 failed
  701. */
  702. int SPIM_Enable_4Bytes_Mode(int isEn, uint32_t u32NBit)
  703. {
  704. int isSupt = 0L, ret = -1;
  705. uint8_t idBuf[3];
  706. uint8_t cmdBuf[1]; /* 1-byte Enter/Exit 4-Byte Mode command. */
  707. SPIM_ReadJedecId(idBuf, sizeof (idBuf), u32NBit);
  708. /* Based on Flash size, check if 4-byte address mode is supported. */
  709. switch (idBuf[0])
  710. {
  711. case MFGID_WINBOND:
  712. case MFGID_MXIC:
  713. case MFGID_EON:
  714. isSupt = (idBuf[2] < 0x19U) ? 0L : 1L;
  715. break;
  716. case MFGID_ISSI:
  717. isSupt = (idBuf[2] < 0x49U) ? 0L : 1L;
  718. break;
  719. case MFGID_SPANSION:
  720. SPIM_SPANSION_4Bytes_Enable(isEn, u32NBit);
  721. isSupt = 1L;
  722. ret = 0L;
  723. break;
  724. default:
  725. break;
  726. }
  727. if ((isSupt) && (idBuf[0] != MFGID_SPANSION))
  728. {
  729. cmdBuf[0] = isEn ? OPCODE_EN4B : OPCODE_EX4B;
  730. SPIM_SET_SS_EN(1); /* CS activated. */
  731. SwitchNBitOutput(u32NBit);
  732. spim_write(cmdBuf, sizeof (cmdBuf));
  733. SPIM_SET_SS_EN(0); /* CS deactivated. */
  734. /*
  735. * FIXME: Per test, 4BYTE Indicator bit doesn't set after EN4B, which
  736. * doesn't match spec(MX25L25635E), so skip the check below.
  737. */
  738. if (idBuf[0] != MFGID_MXIC)
  739. {
  740. if (isEn)
  741. {
  742. while (! SPIM_Is4ByteModeEnable(u32NBit)) { }
  743. }
  744. else
  745. {
  746. while (SPIM_Is4ByteModeEnable(u32NBit)) { }
  747. }
  748. }
  749. ret = 0;
  750. }
  751. return ret;
  752. }
  753. void SPIM_WinbondUnlock(uint32_t u32NBit)
  754. {
  755. uint8_t idBuf[3];
  756. uint8_t dataBuf[4];
  757. SPIM_ReadJedecId(idBuf, sizeof (idBuf), u32NBit);
  758. if ((idBuf[0] != MFGID_WINBOND) || (idBuf[1] != 0x40) || (idBuf[2] != 0x16))
  759. {
  760. SPIM_DBGMSG("SPIM_WinbondUnlock - Not W25Q32, do nothing.\n");
  761. return;
  762. }
  763. SPIM_ReadStatusRegister(&dataBuf[0], 1UL, u32NBit);
  764. SPIM_ReadStatusRegister2(&dataBuf[1], 1UL, u32NBit);
  765. SPIM_DBGMSG("Status Register: 0x%x - 0x%x\n", dataBuf[0], dataBuf[1]);
  766. dataBuf[1] &= ~0x40; /* clear Status Register-1 SEC bit */
  767. spim_set_write_enable(1, u32NBit); /* Write Enable. */
  768. SPIM_WriteStatusRegister2(dataBuf, sizeof (dataBuf), u32NBit);
  769. spim_wait_write_done(u32NBit);
  770. SPIM_ReadStatusRegister(&dataBuf[0], 1UL, u32NBit);
  771. SPIM_ReadStatusRegister2(&dataBuf[1], 1UL, u32NBit);
  772. SPIM_DBGMSG("Status Register (after unlock): 0x%x - 0x%x\n", dataBuf[0], dataBuf[1]);
  773. }
  774. /**
  775. * @brief Erase whole chip.
  776. * @param u32NBit N-bit transmit/receive.
  777. * @param isSync Block or not.
  778. * @return None.
  779. */
  780. void SPIM_ChipErase(uint32_t u32NBit, int isSync)
  781. {
  782. uint8_t cmdBuf[] = { OPCODE_CHIP_ERASE }; /* 1-byte Chip Erase command. */
  783. spim_set_write_enable(1, u32NBit); /* Write Enable. */
  784. SPIM_SET_SS_EN(1); /* CS activated. */
  785. SwitchNBitOutput(u32NBit);
  786. spim_write(cmdBuf, sizeof (cmdBuf));
  787. SPIM_SET_SS_EN(0); /* CS deactivated. */
  788. if (isSync)
  789. {
  790. spim_wait_write_done(u32NBit);
  791. }
  792. }
  793. /**
  794. * @brief Erase one block.
  795. * @param u32Addr Block to erase which contains the u32Addr.
  796. * @param is4ByteAddr 4-byte u32Address or not.
  797. * @param u8ErsCmd Erase command.
  798. * @param u32NBit N-bit transmit/receive.
  799. * @param isSync Block or not.
  800. * @return None.
  801. */
  802. void SPIM_EraseBlock(uint32_t u32Addr, int is4ByteAddr, uint8_t u8ErsCmd, uint32_t u32NBit, int isSync)
  803. {
  804. uint8_t cmdBuf[16];
  805. uint32_t buf_idx = 0UL;
  806. spim_set_write_enable(1, u32NBit); /* Write Enable. */
  807. cmdBuf[buf_idx++] = u8ErsCmd;
  808. if (is4ByteAddr)
  809. {
  810. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 24);
  811. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 16);
  812. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 8);
  813. cmdBuf[buf_idx++] = (uint8_t) (u32Addr & 0xFFUL);
  814. }
  815. else
  816. {
  817. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 16);
  818. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 8);
  819. cmdBuf[buf_idx++] = (uint8_t) (u32Addr & 0xFFUL);
  820. }
  821. SPIM_SET_SS_EN(1); /* CS activated. */
  822. SwitchNBitOutput(u32NBit);
  823. spim_write(cmdBuf, buf_idx);
  824. SPIM_SET_SS_EN(0); /* CS deactivated. */
  825. if (isSync)
  826. {
  827. spim_wait_write_done(u32NBit);
  828. }
  829. }
  830. /** @cond HIDDEN_SYMBOLS */
  831. /**
  832. * @brief Write data in the same page by I/O mode.
  833. * @param u32Addr Start u32Address to write.
  834. * @param is4ByteAddr 4-byte u32Address or not.
  835. * @param u32NTx Number of bytes to write.
  836. * @param pu8TxBuf Transmit buffer.
  837. * @param wrCmd Write command.
  838. * @param u32NBitCmd N-bit transmit command.
  839. * @param u32NBitAddr N-bit transmit u32Address.
  840. * @param u32NBitDat N-bit transmit/receive data.
  841. * @param isSync Block or not.
  842. * @return None.
  843. */
  844. static void SPIM_WriteInPageDataByIo(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NTx, uint8_t pu8TxBuf[], uint8_t wrCmd,
  845. uint32_t u32NBitCmd, uint32_t u32NBitAddr, uint32_t u32NBitDat, int isSync)
  846. {
  847. uint8_t cmdBuf[16];
  848. uint32_t buf_idx;
  849. spim_set_write_enable(1, u32NBitCmd); /* Write Enable. */
  850. SPIM_SET_SS_EN(1); /* CS activated. */
  851. SwitchNBitOutput(u32NBitCmd);
  852. cmdBuf[0] = wrCmd;
  853. spim_write(cmdBuf, 1UL); /* Write out command. */
  854. buf_idx = 0UL;
  855. if (is4ByteAddr)
  856. {
  857. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 24);
  858. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 16);
  859. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 8);
  860. cmdBuf[buf_idx++] = (uint8_t) u32Addr;
  861. }
  862. else
  863. {
  864. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 16);
  865. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 8);
  866. cmdBuf[buf_idx++] = (uint8_t) u32Addr;
  867. }
  868. SwitchNBitOutput(u32NBitAddr);
  869. spim_write(cmdBuf, buf_idx); /* Write out u32Address. */
  870. SwitchNBitOutput(u32NBitDat);
  871. spim_write(pu8TxBuf, u32NTx); /* Write out data. */
  872. SPIM_SET_SS_EN(0); /* CS deactivated. */
  873. if (isSync)
  874. {
  875. spim_wait_write_done(u32NBitCmd);
  876. }
  877. }
  878. /**
  879. * @brief Write data in the same page by Page Write mode.
  880. * @param u32Addr Start u32Address to write.
  881. * @param is4ByteAddr 4-byte u32Address or not.
  882. * @param u32NTx Number of bytes to write.
  883. * @param pu8TxBuf Transmit buffer.
  884. * @param wrCmd Write command.
  885. * @param isSync Block or not.
  886. * @return None.
  887. */
  888. static void SPIM_WriteInPageDataByPageWrite(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NTx,
  889. uint8_t pu8TxBuf[], uint32_t wrCmd, int isSync)
  890. {
  891. if ((wrCmd == CMD_QUAD_PAGE_PROGRAM_WINBOND) ||
  892. (wrCmd == CMD_QUAD_PAGE_PROGRAM_MXIC))
  893. {
  894. SPIM_SetQuadEnable(1, 1UL); /* Set Quad Enable. */
  895. }
  896. else if (wrCmd == CMD_QUAD_PAGE_PROGRAM_EON)
  897. {
  898. SPIM_SetQuadEnable(1, 1UL); /* Set Quad Enable. */
  899. spim_eon_set_qpi_mode(1); /* Enter QPI mode. */
  900. }
  901. SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_PAGEWRITE);/* Switch to Page Write mode. */
  902. SPIM_SET_SPIM_MODE(wrCmd); /* SPIM mode. */
  903. SPIM_SET_4BYTE_ADDR_EN(is4ByteAddr); /* Enable/disable 4-Byte Address. */
  904. SPIM->SRAMADDR = (uint32_t) pu8TxBuf; /* SRAM u32Address. */
  905. SPIM->DMACNT = u32NTx; /* Transfer length. */
  906. SPIM->FADDR = u32Addr; /* Flash u32Address.*/
  907. SPIM_SET_GO(); /* Go. */
  908. if (isSync)
  909. {
  910. SPIM_WAIT_FREE();
  911. }
  912. if (wrCmd == CMD_QUAD_PAGE_PROGRAM_EON)
  913. {
  914. spim_eon_set_qpi_mode(0); /* Exit QPI mode. */
  915. }
  916. }
  917. /** @endcond HIDDEN_SYMBOLS */
  918. /**
  919. * @brief Write data to SPI Flash by sending commands manually (I/O mode).
  920. * @param u32Addr: Start u32Address to write.
  921. * @param is4ByteAddr: 4-byte u32Address or not.
  922. * @param u32NTx: Number of bytes to write.
  923. * @param pu8TxBuf: Transmit buffer.
  924. * @param wrCmd: Write command.
  925. * @param u32NBitCmd: N-bit transmit command.
  926. * @param u32NBitAddr: N-bit transmit u32Address.
  927. * @param u32NBitDat: N-bit transmit/receive data.
  928. * @return None.
  929. */
  930. void SPIM_IO_Write(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NTx, uint8_t pu8TxBuf[], uint8_t wrCmd,
  931. uint32_t u32NBitCmd, uint32_t u32NBitAddr, uint32_t u32NBitDat)
  932. {
  933. uint32_t pageOffset, toWr;
  934. uint32_t buf_idx = 0UL;
  935. pageOffset = u32Addr % 256UL;
  936. if ((pageOffset + u32NTx) <= 256UL) /* Do all the bytes fit onto one page ? */
  937. {
  938. SPIM_WriteInPageDataByIo(u32Addr, is4ByteAddr, u32NTx, &pu8TxBuf[buf_idx],
  939. wrCmd, u32NBitCmd, u32NBitAddr, u32NBitDat, 1);
  940. }
  941. else
  942. {
  943. toWr = 256UL - pageOffset; /* Size of data remaining on the first page. */
  944. SPIM_WriteInPageDataByIo(u32Addr, is4ByteAddr, toWr, &pu8TxBuf[buf_idx],
  945. wrCmd, u32NBitCmd, u32NBitAddr, u32NBitDat, 1);
  946. u32Addr += toWr; /* Advance indicator. */
  947. u32NTx -= toWr;
  948. buf_idx += toWr;
  949. while (u32NTx)
  950. {
  951. toWr = 256UL;
  952. if (toWr > u32NTx)
  953. {
  954. toWr = u32NTx;
  955. }
  956. SPIM_WriteInPageDataByIo(u32Addr, is4ByteAddr, toWr, &pu8TxBuf[buf_idx],
  957. wrCmd, u32NBitCmd, u32NBitAddr, u32NBitDat, 1);
  958. u32Addr += toWr; /* Advance indicator. */
  959. u32NTx -= toWr;
  960. buf_idx += toWr;
  961. }
  962. }
  963. }
  964. /**
  965. * @brief Read data from SPI Flash by sending commands manually (I/O mode).
  966. * @param u32Addr Start u32Address to read.
  967. * @param is4ByteAddr 4-byte u32Address or not.
  968. * @param u32NRx Number of bytes to read.
  969. * @param pu8RxBuf Receive buffer.
  970. * @param rdCmd Read command.
  971. * @param u32NBitCmd N-bit transmit command.
  972. * @param u32NBitAddr N-bit transmit u32Address.
  973. * @param u32NBitDat N-bit transmit/receive data.
  974. * @param u32NDummy Number of dummy bytes following address.
  975. * @return None.
  976. */
  977. void SPIM_IO_Read(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NRx, uint8_t pu8RxBuf[], uint8_t rdCmd,
  978. uint32_t u32NBitCmd, uint32_t u32NBitAddr, uint32_t u32NBitDat, int u32NDummy)
  979. {
  980. uint8_t cmdBuf[16];
  981. uint32_t buf_idx;
  982. SPIM_SET_SS_EN(1); /* CS activated. */
  983. cmdBuf[0] = rdCmd;
  984. SwitchNBitOutput(u32NBitCmd);
  985. spim_write(cmdBuf, 1UL); /* Write out command. */
  986. buf_idx = 0UL;
  987. if (is4ByteAddr)
  988. {
  989. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 24);
  990. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 16);
  991. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 8);
  992. cmdBuf[buf_idx++] = (uint8_t) u32Addr;
  993. }
  994. else
  995. {
  996. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 16);
  997. cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 8);
  998. cmdBuf[buf_idx++] = (uint8_t) u32Addr;
  999. }
  1000. SwitchNBitOutput(u32NBitAddr);
  1001. spim_write(cmdBuf, buf_idx); /* Write out u32Address. */
  1002. buf_idx = 0UL;
  1003. while (u32NDummy --)
  1004. {
  1005. cmdBuf[buf_idx++] = 0x00U;
  1006. }
  1007. /* Same bit mode as above. */
  1008. spim_write(cmdBuf, buf_idx); /* Write out dummy bytes. */
  1009. SwitchNBitInput(u32NBitDat);
  1010. spim_read(pu8RxBuf, u32NRx); /* Read back data. */
  1011. SPIM_SET_SS_EN(0); /* CS deactivated. */
  1012. }
  1013. /**
  1014. * @brief Write data to SPI Flash by Page Write mode.
  1015. * @param u32Addr Start address to write.
  1016. * @param is4ByteAddr 4-byte address or not.
  1017. * @param u32NTx Number of bytes to write.
  1018. * @param pu8TxBuf Transmit buffer.
  1019. * @param wrCmd Write command.
  1020. * @return None.
  1021. */
  1022. void SPIM_DMA_Write(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NTx, uint8_t pu8TxBuf[], uint32_t wrCmd)
  1023. {
  1024. uint32_t pageOffset, toWr;
  1025. uint32_t buf_idx = 0UL;
  1026. pageOffset = u32Addr % 256UL;
  1027. if ((pageOffset + u32NTx) <= 256UL)
  1028. {
  1029. /* Do all the bytes fit onto one page ? */
  1030. SPIM_WriteInPageDataByPageWrite(u32Addr, is4ByteAddr, u32NTx, pu8TxBuf, wrCmd, 1);
  1031. }
  1032. else
  1033. {
  1034. toWr = 256UL - pageOffset; /* Size of data remaining on the first page. */
  1035. SPIM_WriteInPageDataByPageWrite(u32Addr, is4ByteAddr, toWr, &pu8TxBuf[buf_idx], wrCmd, 1);
  1036. u32Addr += toWr; /* Advance indicator. */
  1037. u32NTx -= toWr;
  1038. buf_idx += toWr;
  1039. while (u32NTx)
  1040. {
  1041. toWr = 256UL;
  1042. if (toWr > u32NTx)
  1043. {
  1044. toWr = u32NTx;
  1045. }
  1046. SPIM_WriteInPageDataByPageWrite(u32Addr, is4ByteAddr, toWr, &pu8TxBuf[buf_idx], wrCmd, 1);
  1047. u32Addr += toWr; /* Advance indicator. */
  1048. u32NTx -= toWr;
  1049. buf_idx += toWr;
  1050. }
  1051. }
  1052. }
  1053. /**
  1054. * @brief Read data from SPI Flash by Page Read mode.
  1055. * @param u32Addr Start address to read.
  1056. * @param is4ByteAddr 4-byte u32Address or not.
  1057. * @param u32NRx Number of bytes to read.
  1058. * @param pu8RxBuf Receive buffer.
  1059. * @param u32RdCmd Read command.
  1060. * @param isSync Block or not.
  1061. * @return None.
  1062. */
  1063. void SPIM_DMA_Read(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NRx, uint8_t pu8RxBuf[],
  1064. uint32_t u32RdCmd, int isSync)
  1065. {
  1066. SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_PAGEREAD); /* Switch to Page Read mode. */
  1067. SPIM_SET_SPIM_MODE(u32RdCmd); /* SPIM mode. */
  1068. SPIM_SET_4BYTE_ADDR_EN(is4ByteAddr); /* Enable/disable 4-Byte Address. */
  1069. SPIM->SRAMADDR = (uint32_t) pu8RxBuf; /* SRAM u32Address. */
  1070. SPIM->DMACNT = u32NRx; /* Transfer length. */
  1071. SPIM->FADDR = u32Addr; /* Flash u32Address.*/
  1072. SPIM_SET_GO(); /* Go. */
  1073. if (isSync)
  1074. {
  1075. SPIM_WAIT_FREE(); /* Wait for DMA done. */
  1076. }
  1077. }
  1078. /**
  1079. * @brief Enter Direct Map mode.
  1080. * @param is4ByteAddr 4-byte u32Address or not.
  1081. * @param u32RdCmd Read command.
  1082. * @param u32IdleIntvl Idle interval.
  1083. * @return None.
  1084. */
  1085. void SPIM_EnterDirectMapMode(int is4ByteAddr, uint32_t u32RdCmd, uint32_t u32IdleIntvl)
  1086. {
  1087. SPIM_SET_4BYTE_ADDR_EN(is4ByteAddr); /* Enable/disable 4-byte u32Address. */
  1088. SPIM_SET_SPIM_MODE(u32RdCmd); /* SPIM mode. */
  1089. SPIM_SET_IDL_INTVL(u32IdleIntvl); /* Idle interval. */
  1090. SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_DIRECTMAP); /* Switch to Direct Map mode. */
  1091. }
  1092. /**
  1093. * @brief Exit Direct Map mode.
  1094. * @return None.
  1095. */
  1096. void SPIM_ExitDirectMapMode(void)
  1097. {
  1098. SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_IO); /* Switch back to Normal mode. */
  1099. }
  1100. /*@}*/ /* end of group SPIM_EXPORTED_FUNCTIONS */
  1101. /*@}*/ /* end of group SPIM_Driver */
  1102. /*@}*/ /* end of group Standard_Driver */
  1103. /*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/