spi_8xx.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. /*
  2. * @brief LPC8xx SPI driver
  3. *
  4. * @note
  5. * Copyright(C) NXP Semiconductors, 2012
  6. * All rights reserved.
  7. *
  8. * @par
  9. * Software that is described herein is for illustrative purposes only
  10. * which provides customers with programming information regarding the
  11. * LPC products. This software is supplied "AS IS" without any warranties of
  12. * any kind, and NXP Semiconductors and its licenser disclaim any and
  13. * all warranties, express or implied, including all implied warranties of
  14. * merchantability, fitness for a particular purpose and non-infringement of
  15. * intellectual property rights. NXP Semiconductors assumes no responsibility
  16. * or liability for the use of the software, conveys no license or rights under any
  17. * patent, copyright, mask work right, or any other intellectual property rights in
  18. * or to any products. NXP Semiconductors reserves the right to make changes
  19. * in the software without notification. NXP Semiconductors also makes no
  20. * representation or warranty that such application will be suitable for the
  21. * specified use without further testing or modification.
  22. *
  23. * @par
  24. * Permission to use, copy, modify, and distribute this software and its
  25. * documentation is hereby granted, under NXP Semiconductors' and its
  26. * licensor's relevant copyrights in the software, without fee, provided that it
  27. * is used in conjunction with NXP Semiconductors microcontrollers. This
  28. * copyright, permission, and disclaimer notice must appear in all copies of
  29. * this code.
  30. */
  31. #include "chip.h"
  32. /*****************************************************************************
  33. * Private types/enumerations/variables
  34. ****************************************************************************/
  35. static volatile bool xmitOn;
  36. static volatile bool deasserted;
  37. /*****************************************************************************
  38. * Public types/enumerations/variables
  39. ****************************************************************************/
  40. /*****************************************************************************
  41. * Private functions
  42. ****************************************************************************/
  43. STATIC void SPI_Send_Data_RxIgnore(LPC_SPI_T *pSPI,
  44. SPI_DATA_SETUP_T *pXfSetup)
  45. {
  46. if (pXfSetup->TxCnt == (pXfSetup->Length - 1)) {
  47. Chip_SPI_SendLastFrame_RxIgnore(pSPI, pXfSetup->pTx[pXfSetup->TxCnt], pXfSetup->DataSize);
  48. }
  49. else {
  50. Chip_SPI_SendMidFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt]);
  51. }
  52. pXfSetup->TxCnt++;
  53. }
  54. STATIC void SPI_Send_Data(LPC_SPI_T *pSPI,
  55. SPI_DATA_SETUP_T *pXfSetup)
  56. {
  57. if (pXfSetup->TxCnt == (pXfSetup->Length - 1)) {
  58. Chip_SPI_SendLastFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt], pXfSetup->DataSize);
  59. }
  60. else {
  61. Chip_SPI_SendMidFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt]);
  62. }
  63. pXfSetup->TxCnt++;
  64. }
  65. STATIC void SPI_Send_Dummy(LPC_SPI_T *pSPI,
  66. SPI_DATA_SETUP_T *pXfSetup)
  67. {
  68. if (pXfSetup->RxCnt == (pXfSetup->Length - 1)) {
  69. Chip_SPI_SendLastFrame(pSPI, 0x55, pXfSetup->DataSize);
  70. }
  71. else {
  72. Chip_SPI_SendMidFrame(pSPI, 0x55);
  73. }
  74. }
  75. STATIC void SPI_Receive_Data(LPC_SPI_T *pSPI,
  76. SPI_DATA_SETUP_T *pXfSetup)
  77. {
  78. pXfSetup->pRx[pXfSetup->RxCnt] = Chip_SPI_ReceiveFrame(pSPI);
  79. pXfSetup->RxCnt++;
  80. }
  81. /* Determine SSEL associated with the current data value */
  82. STATIC uint8_t Chip_SPIS_FindSSEL(LPC_SPI_T *pSPI, uint32_t data)
  83. {
  84. int i;
  85. uint8_t ssel = 0;
  86. for (i = 0; i <= 3; i++) {
  87. if ((data & SPI_RXDAT_RXSSELNUM_INACTIVE(i)) == 0) {
  88. /* Signal is active on low */
  89. ssel = (uint8_t) i;
  90. }
  91. }
  92. return ssel;
  93. }
  94. /*****************************************************************************
  95. * Public functions
  96. ****************************************************************************/
  97. /* Calculate the Clock Rate Divider for SPI Peripheral */
  98. uint32_t Chip_SPI_CalClkRateDivider(LPC_SPI_T *pSPI, uint32_t bitRate)
  99. {
  100. uint32_t SPIClk;
  101. uint32_t DivVal = 1;
  102. /* Get SPI clock rate */
  103. SPIClk = Chip_Clock_GetSystemClockRate(); /*The peripheral clock for both SPIs is the system clock*/
  104. DivVal = SPIClk / bitRate;
  105. return DivVal;
  106. }
  107. /* Configure SPI Delay parameters */
  108. void Chip_SPI_DelayConfig(LPC_SPI_T *pSPI, SPI_DELAY_CONFIG_T *pConfig)
  109. {
  110. uint32_t delayValue = SPI_DLY_PRE_DELAY(pConfig->PreDelay) |
  111. SPI_DLY_POST_DELAY(pConfig->PostDelay) |
  112. SPI_DLY_FRAME_DELAY(pConfig->FrameDelay);
  113. if (pConfig->TransferDelay) {
  114. delayValue |= SPI_DLY_TRANSFER_DELAY(pConfig->TransferDelay - 1);
  115. }
  116. pSPI->DLY = delayValue;
  117. }
  118. /* Disable/Enable Interrupt */
  119. void Chip_SPI_Int_Cmd(LPC_SPI_T *pSPI, uint32_t IntMask, FunctionalState NewState)
  120. {
  121. if (NewState == ENABLE) {
  122. pSPI->INTENSET = IntMask;
  123. }
  124. else {
  125. pSPI->INTENCLR = IntMask;
  126. }
  127. }
  128. /*Send and Receive SPI Data */
  129. uint32_t Chip_SPI_RWFrames_Blocking(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
  130. {
  131. uint32_t Status;
  132. /* Clear status */
  133. Chip_SPI_ClearStatus(pSPI, SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR | SPI_STAT_CLR_SSA | SPI_STAT_CLR_SSD);
  134. Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, SPI_TXCTL_ASSERT_SSEL | SPI_TXCTL_EOF);
  135. pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
  136. while ((pXfSetup->TxCnt < pXfSetup->Length) ||
  137. (pXfSetup->RxCnt < pXfSetup->Length)) {
  138. Status = Chip_SPI_GetStatus(pSPI);
  139. /* In case of TxReady */
  140. if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
  141. SPI_Send_Data(pSPI, pXfSetup);
  142. }
  143. /*In case of Rx ready */
  144. if ((Status & SPI_STAT_RXRDY) && (pXfSetup->RxCnt < pXfSetup->Length)) {
  145. SPI_Receive_Data(pSPI, pXfSetup);
  146. }
  147. }
  148. /* Check error */
  149. if (Chip_SPI_GetStatus(pSPI) & (SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR)) {
  150. return 0;
  151. }
  152. return pXfSetup->TxCnt;
  153. }
  154. uint32_t Chip_SPI_WriteFrames_Blocking(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
  155. {
  156. /* Clear status */
  157. Chip_SPI_ClearStatus(pSPI, SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR | SPI_STAT_CLR_SSA | SPI_STAT_CLR_SSD);
  158. Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, SPI_TXCTL_ASSERT_SSEL | SPI_TXCTL_EOF | SPI_TXCTL_RXIGNORE);
  159. pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
  160. while (pXfSetup->TxCnt < pXfSetup->Length) {
  161. /* Wait for TxReady */
  162. while (!(Chip_SPI_GetStatus(pSPI) & SPI_STAT_TXRDY)) {}
  163. SPI_Send_Data_RxIgnore(pSPI, pXfSetup);
  164. }
  165. /* Make sure the last frame sent completely*/
  166. while (!(Chip_SPI_GetStatus(pSPI) & SPI_STAT_SSD)) {}
  167. Chip_SPI_ClearStatus(pSPI, SPI_STAT_CLR_SSD);
  168. /* Check overrun error */
  169. if (Chip_SPI_GetStatus(pSPI) & SPI_STAT_CLR_TXUR) {
  170. return 0;
  171. }
  172. return pXfSetup->TxCnt;
  173. }
  174. uint32_t Chip_SPI_ReadFrames_Blocking(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
  175. {
  176. /* Clear status */
  177. Chip_SPI_ClearStatus(pSPI, SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR | SPI_STAT_CLR_SSA | SPI_STAT_CLR_SSD);
  178. Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, SPI_TXCTL_ASSERT_SSEL | SPI_TXCTL_EOF);
  179. pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
  180. while (pXfSetup->RxCnt < pXfSetup->Length) {
  181. /* Wait for TxReady */
  182. while (!(Chip_SPI_GetStatus(pSPI) & SPI_STAT_TXRDY)) {}
  183. SPI_Send_Dummy(pSPI, pXfSetup);
  184. /* Wait for receive data */
  185. while (!(Chip_SPI_GetStatus(pSPI) & SPI_STAT_RXRDY)) {}
  186. SPI_Receive_Data(pSPI, pXfSetup);
  187. }
  188. /* Check overrun error */
  189. if (Chip_SPI_GetStatus(pSPI) & (SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR)) {
  190. return 0;
  191. }
  192. return pXfSetup->RxCnt;
  193. }
  194. /* SPI Interrupt Read/Write with 8-bit frame width */
  195. Status Chip_SPI_Int_RWFrames(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
  196. {
  197. uint32_t Status;
  198. Status = Chip_SPI_GetStatus(pSPI);
  199. /* Check error in INTSTAT register */
  200. if (Status & (SPI_STAT_RXOV | SPI_STAT_TXUR)) {
  201. return ERROR;
  202. }
  203. if (pXfSetup->TxCnt == 0) {
  204. Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, SPI_TXCTL_ASSERT_SSEL | SPI_TXCTL_EOF);
  205. }
  206. if (pXfSetup->pRx == NULL) {
  207. if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
  208. SPI_Send_Data_RxIgnore(pSPI, pXfSetup);
  209. }
  210. }
  211. else {
  212. /* check if Tx ready */
  213. if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
  214. SPI_Send_Data(pSPI, pXfSetup);
  215. }
  216. /* check if RX FIFO contains data */
  217. if ((Status & SPI_STAT_RXRDY) && (pXfSetup->RxCnt < pXfSetup->Length)) {
  218. SPI_Receive_Data(pSPI, pXfSetup);
  219. }
  220. }
  221. return SUCCESS;
  222. }
  223. /* Get SPI master bit rate */
  224. uint32_t Chip_SPIM_GetClockRate(LPC_SPI_T *pSPI)
  225. {
  226. return Chip_Clock_GetSystemClockRate() / ((pSPI->DIV & ~SPI_DIV_RESERVED) + 1);
  227. }
  228. /* Set SPI master bit rate */
  229. uint32_t Chip_SPIM_SetClockRate(LPC_SPI_T *pSPI, uint32_t rate)
  230. {
  231. uint32_t baseClock, div;
  232. /* Get peripheral base clock rate */
  233. baseClock = Chip_Clock_GetSystemClockRate();
  234. /* Compute divider */
  235. div = baseClock / rate;
  236. /* Limit values */
  237. if (div == 0) {
  238. div = 1;
  239. }
  240. else if (div > 0x10000) {
  241. div = 0x10000;
  242. }
  243. pSPI->DIV = div - 1;
  244. return Chip_SPIM_GetClockRate(pSPI);
  245. }
  246. /* Configure SPI Delay parameters */
  247. void Chip_SPIM_DelayConfig(LPC_SPI_T *pSPI, SPIM_DELAY_CONFIG_T *pConfig)
  248. {
  249. pSPI->DLY = (SPI_DLY_PRE_DELAY(pConfig->PreDelay) |
  250. SPI_DLY_POST_DELAY(pConfig->PostDelay) |
  251. SPI_DLY_FRAME_DELAY(pConfig->FrameDelay) |
  252. SPI_DLY_TRANSFER_DELAY(pConfig->TransferDelay - 1));
  253. }
  254. /* Assert a SPI select */
  255. void Chip_SPIM_AssertSSEL(LPC_SPI_T *pSPI, uint8_t sselNum)
  256. {
  257. uint32_t reg;
  258. reg = pSPI->TXCTRL & SPI_TXDATCTL_CTRLMASK;
  259. /* Assert a SSEL line by driving it low */
  260. reg &= ~SPI_TXDATCTL_DEASSERTNUM_SSEL(sselNum);
  261. pSPI->TXCTRL = reg;
  262. }
  263. /* Deassert a SPI select */
  264. void Chip_SPIM_DeAssertSSEL(LPC_SPI_T *pSPI, uint8_t sselNum)
  265. {
  266. uint32_t reg;
  267. reg = pSPI->TXCTRL & SPI_TXDATCTL_CTRLMASK;
  268. pSPI->TXCTRL = reg | SPI_TXDATCTL_DEASSERTNUM_SSEL(sselNum);
  269. }
  270. /* SPI master transfer state change handler */
  271. void Chip_SPIM_XferHandler(LPC_SPI_T *pSPI, SPIM_XFER_T *xfer)
  272. {
  273. uint32_t data;
  274. uint8_t flen;
  275. /* Get length of a receive value */
  276. flen = ((pSPI->TXCTRL & ~SPI_TXCTRL_RESERVED) >> 24) & 0xF;
  277. /* Master asserts slave */
  278. if ((Chip_SPI_GetStatus(pSPI) & SPI_STAT_SSA) != 0) {
  279. Chip_SPI_ClearStatus(pSPI, SPI_STAT_SSA);
  280. /* SSEL assertion callback */
  281. xfer->pCB->masterXferCSAssert(xfer);
  282. }
  283. /* Slave de-assertion */
  284. if ((Chip_SPI_GetStatus(pSPI) & SPI_STAT_SSD) != 0) {
  285. Chip_SPI_ClearStatus(pSPI, SPI_STAT_SSD);
  286. /* If transmitter disabled and deassert happens, the transfer is done */
  287. if (xmitOn == false) {
  288. xfer->pCB->mMasterXferDone(xfer);
  289. }
  290. }
  291. /* Transmit data? */
  292. while (((Chip_SPI_GetStatus(pSPI) & SPI_STAT_TXRDY) != 0) && (xmitOn == true)) {
  293. if ((xfer->txCount == 1) && (xfer->terminate)) {
  294. /* Transfer is done, this will be last data */
  295. Chip_SPIM_ForceEndOfTransfer(pSPI);
  296. xmitOn = false;
  297. }
  298. else if (xfer->txCount == 0) {
  299. /* Request a new buffer first */
  300. xfer->pCB->masterXferSend(xfer);
  301. }
  302. if (xfer->txCount > 0) {
  303. /* Send 0 if ignoring transmit */
  304. if (xfer->pTXData8 == NULL) {
  305. data = 0;
  306. }
  307. else {
  308. /* Copy buffer to data */
  309. if (flen > 8) {
  310. data = (uint32_t) *xfer->pTXData16;
  311. xfer->pTXData16++;
  312. }
  313. else {
  314. data = (uint32_t) *xfer->pTXData8;
  315. xfer->pTXData8++;
  316. }
  317. xfer->dataTXferred++;
  318. }
  319. Chip_SPI_WriteTXData(pSPI, data);
  320. xfer->txCount--;
  321. }
  322. }
  323. /* Data received? */
  324. while ((Chip_SPI_GetStatus(pSPI) & SPI_STAT_RXRDY) != 0) {
  325. /* Get raw data and status */
  326. data = Chip_SPI_ReadRawRXFifo(pSPI);
  327. /* Only copy data when not ignoring receive */
  328. if (xfer->pRXData8 != NULL) {
  329. /* Enough size in current buffers? */
  330. if (xfer->rxCount == 0) {
  331. /* Request a new buffer first */
  332. xfer->pCB->masterXferRecv(xfer);
  333. }
  334. /* Copy data to buffer */
  335. if (xfer->rxCount > 0) {
  336. if (flen > 8) {
  337. *xfer->pRXData16 = (uint16_t) (data & 0xFFFF);
  338. xfer->pRXData16++;
  339. }
  340. else {
  341. *xfer->pRXData8 = (uint8_t) (data & 0xFF);
  342. xfer->pRXData8++;
  343. }
  344. xfer->dataRXferred++;
  345. xfer->rxCount--;
  346. }
  347. }
  348. }
  349. }
  350. /* Start non-blocking SPI master transfer */
  351. void Chip_SPIM_Xfer(LPC_SPI_T *pSPI, SPIM_XFER_T *xfer)
  352. {
  353. /* Setup SPI master select, data length, EOT/EOF timing, and RX data ignore */
  354. pSPI->TXCTRL = xfer->options | SPI_TXDATCTL_DEASSERT_ALL;
  355. Chip_SPIM_AssertSSEL(pSPI, xfer->sselNum);
  356. /* Clear initial transfer states */
  357. xfer->dataRXferred = xfer->dataTXferred = 0;
  358. /* Call main handler to start transfer */
  359. xmitOn = true;
  360. Chip_SPIM_XferHandler(pSPI, xfer);
  361. }
  362. /* Perform blocking SPI master transfer */
  363. void Chip_SPIM_XferBlocking(LPC_SPI_T *pSPI, SPIM_XFER_T *xfer)
  364. {
  365. /* Start trasnfer */
  366. Chip_SPIM_Xfer(pSPI, xfer);
  367. /* Wait for termination */
  368. while (xmitOn == true) {
  369. Chip_SPIM_XferHandler(pSPI, xfer);
  370. }
  371. }
  372. /* SPI slave transfer state change handler */
  373. uint32_t Chip_SPIS_XferHandler(LPC_SPI_T *pSPI, SPIS_XFER_T *xfer)
  374. {
  375. uint32_t staterr, data;
  376. uint8_t flen;
  377. /* Get length of a receive value */
  378. flen = ((pSPI->TXCTRL & ~SPI_TXCTRL_RESERVED) >> 24) & 0xF;
  379. /* Get errors for later, we'll continue even if errors occur, but we notify
  380. caller on return */
  381. staterr = Chip_SPI_GetStatus(pSPI) & (SPI_STAT_RXOV | SPI_STAT_TXUR);
  382. if (staterr != 0) {
  383. Chip_SPI_ClearStatus(pSPI, staterr);
  384. }
  385. /* Slave assertion */
  386. if ((Chip_SPI_GetStatus(pSPI) & SPI_STAT_SSA) != 0) {
  387. Chip_SPI_ClearStatus(pSPI, SPI_STAT_SSA);
  388. /* Determine SPI select. Read the data FIFO to get the slave number. Data
  389. should not be in the receive FIFO yet, only the statuses */
  390. xfer->sselNum = Chip_SPIS_FindSSEL(pSPI, Chip_SPI_ReadRawRXFifo(pSPI));
  391. /* SSEL assertion callback */
  392. xfer->pCB->slaveXferCSAssert(xfer);
  393. }
  394. /* Slave de-assertion */
  395. if ((Chip_SPI_GetStatus(pSPI) & SPI_STAT_SSD) != 0) {
  396. Chip_SPI_ClearStatus(pSPI, SPI_STAT_SSD);
  397. deasserted = true;
  398. xfer->pCB->slaveXferCSDeAssert(xfer);
  399. }
  400. /* Transmit data? */
  401. while ((Chip_SPI_GetStatus(pSPI) & SPI_STAT_TXRDY) != 0) {
  402. if (xfer->txCount == 0) {
  403. /* Request a new buffer first */
  404. xfer->pCB->slaveXferSend(xfer);
  405. }
  406. /* Send 0 on empty buffer or count */
  407. if ((xfer->txCount == 0) || (xfer->pTXData8 == NULL)) {
  408. data = 0;
  409. }
  410. else {
  411. /* Copy buffer to data */
  412. if (flen > 8) {
  413. data = (uint32_t) *xfer->pTXData16;
  414. xfer->pTXData16++;
  415. }
  416. else {
  417. data = (uint32_t) *xfer->pTXData8;
  418. xfer->pTXData8++;
  419. }
  420. xfer->dataTXferred++;
  421. xfer->txCount--;
  422. }
  423. Chip_SPI_WriteTXData(pSPI, data);
  424. }
  425. /* Data received? */
  426. while ((Chip_SPI_GetStatus(pSPI) & SPI_STAT_RXRDY) != 0) {
  427. /* Get raw data and status */
  428. data = Chip_SPI_ReadRawRXFifo(pSPI);
  429. /* Only copy data when not ignoring receive */
  430. if (xfer->pRXData8 != NULL) {
  431. /* Enough size in current buffers? */
  432. if (xfer->rxCount == 0) {
  433. /* Request a new buffer first */
  434. xfer->pCB->slaveXferRecv(xfer);
  435. }
  436. /* Copy data to buffer */
  437. if (flen > 8) {
  438. *xfer->pRXData16 = (uint16_t) (data & 0xFFFF);
  439. xfer->pRXData16++;
  440. }
  441. else {
  442. *xfer->pRXData8 = (uint8_t) (data & 0xFF);
  443. xfer->pRXData8++;
  444. }
  445. xfer->dataRXferred++;
  446. xfer->rxCount--;
  447. }
  448. }
  449. return staterr;
  450. }
  451. /* SPI slave transfer blocking function */
  452. uint32_t Chip_SPIS_XferBlocking(LPC_SPI_T *pSPI, SPIS_XFER_T *xfer)
  453. {
  454. uint32_t status = 0;
  455. /* Wait forever until deassertion event */
  456. deasserted = false;
  457. while ((!deasserted) && (status == 0)) {
  458. status = Chip_SPIS_XferHandler(pSPI, xfer);
  459. }
  460. return status;
  461. }