1 /*
2 * @brief LPC15xx SPI driver
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2014
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 licensor 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
32 #include "chip.h"
33
34 /*****************************************************************************
35 * Private types/enumerations/variables
36 ****************************************************************************/
37
38 /*****************************************************************************
39 * Public types/enumerations/variables
40 ****************************************************************************/
41
42 /*****************************************************************************
43 * Private functions
44 ****************************************************************************/
45
SPI_Send_Data_RxIgnore(LPC_SPI_T * pSPI,SPI_DATA_SETUP_T * pXfSetup)46 STATIC void SPI_Send_Data_RxIgnore(LPC_SPI_T *pSPI,
47 SPI_DATA_SETUP_T *pXfSetup)
48 {
49 if (pXfSetup->TxCnt == (pXfSetup->Length - 1)) {
50 Chip_SPI_SendLastFrame_RxIgnore(pSPI, pXfSetup->pTx[pXfSetup->TxCnt], pXfSetup->DataSize, pXfSetup->ssel);
51 }
52 else {
53 Chip_SPI_SendMidFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt]);
54 }
55
56 pXfSetup->TxCnt++;
57 }
58
SPI_Send_Data(LPC_SPI_T * pSPI,SPI_DATA_SETUP_T * pXfSetup)59 STATIC void SPI_Send_Data(LPC_SPI_T *pSPI,
60 SPI_DATA_SETUP_T *pXfSetup)
61 {
62 if (pXfSetup->TxCnt == (pXfSetup->Length - 1)) {
63 Chip_SPI_SendLastFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt], pXfSetup->DataSize, pXfSetup->ssel);
64 }
65 else {
66 Chip_SPI_SendMidFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt]);
67 }
68
69 pXfSetup->TxCnt++;
70 }
71
SPI_Send_Dummy(LPC_SPI_T * pSPI,SPI_DATA_SETUP_T * pXfSetup)72 STATIC void SPI_Send_Dummy(LPC_SPI_T *pSPI,
73 SPI_DATA_SETUP_T *pXfSetup)
74 {
75 if (pXfSetup->RxCnt == (pXfSetup->Length - 1)) {
76 Chip_SPI_SendLastFrame(pSPI, 0x55, pXfSetup->DataSize, pXfSetup->ssel);
77 }
78 else {
79 Chip_SPI_SendMidFrame(pSPI, 0x55);
80 }
81 }
82
SPI_Receive_Data(LPC_SPI_T * pSPI,SPI_DATA_SETUP_T * pXfSetup)83 STATIC void SPI_Receive_Data(LPC_SPI_T *pSPI,
84 SPI_DATA_SETUP_T *pXfSetup)
85 {
86 pXfSetup->pRx[pXfSetup->RxCnt] = Chip_SPI_ReceiveFrame(pSPI);
87 pXfSetup->RxCnt++;
88 }
89
90 /*****************************************************************************
91 * Public functions
92 ****************************************************************************/
93
94 /* Calculate the Clock Rate Divider for SPI Peripheral */
Chip_SPI_CalClkRateDivider(LPC_SPI_T * pSPI,uint32_t bitRate)95 uint32_t Chip_SPI_CalClkRateDivider(LPC_SPI_T *pSPI, uint32_t bitRate)
96 {
97 uint32_t SPIClk;
98 uint32_t DivVal;
99
100 /* Get SPI clock rate */
101 SPIClk = Chip_Clock_GetSystemClockRate(); /*The peripheral clock for both SPIs is the system clock*/
102
103 DivVal = SPIClk / bitRate;
104
105 return DivVal - 1;
106 }
107
108 /* Set SPI Config register */
Chip_SPI_SetConfig(LPC_SPI_T * pSPI,SPI_CFG_T * pConfig)109 void Chip_SPI_SetConfig(LPC_SPI_T *pSPI, SPI_CFG_T *pConfig)
110 {
111 uint32_t EnStat = pSPI->CFG & SPI_CFG_SPI_EN;
112
113 /* Disable before update CFG register */
114 if (EnStat) {
115 Chip_SPI_Disable(pSPI);
116 }
117
118 /* SPI Configure */
119 pSPI->CFG = ((uint32_t) pConfig->ClockMode) | ((uint32_t) pConfig->DataOrder) | ((uint32_t) pConfig->Mode) |
120 ((uint32_t) pConfig->SSELPol);
121
122 /* Rate Divider setting */
123 pSPI->DIV = SPI_DIV_VAL(pConfig->ClkDiv);
124
125 /* Clear status flag*/
126 Chip_SPI_ClearStatus(
127 pSPI,
128 SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR | SPI_STAT_CLR_SSA | SPI_STAT_CLR_SSD |
129 SPI_STAT_FORCE_EOT);
130
131 /* Return the previous state */
132 if (EnStat) {
133 Chip_SPI_Enable(pSPI);
134 }
135 }
136
Chip_SPI_Init(LPC_SPI_T * pSPI)137 void Chip_SPI_Init(LPC_SPI_T *pSPI)
138 {
139 if (pSPI == LPC_SPI1) {
140 Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SPI1);
141 Chip_SYSCTL_PeriphReset(RESET_SPI1);
142 }
143 else {
144 Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SPI0);
145 Chip_SYSCTL_PeriphReset(RESET_SPI0);
146 }
147 }
148
149 /* De-initializes the SPI peripheral */
Chip_SPI_DeInit(LPC_SPI_T * pSPI)150 void Chip_SPI_DeInit(LPC_SPI_T *pSPI)
151 {
152 Chip_SPI_Disable(pSPI);
153
154 Chip_Clock_DisablePeriphClock((pSPI == LPC_SPI1) ? SYSCTL_CLOCK_SPI1 : SYSCTL_CLOCK_SPI0);
155 }
156
157 /* Configure SPI Delay parameters */
Chip_SPI_DelayConfig(LPC_SPI_T * pSPI,SPI_DELAY_CONFIG_T * pConfig)158 void Chip_SPI_DelayConfig(LPC_SPI_T *pSPI, SPI_DELAY_CONFIG_T *pConfig)
159 {
160 pSPI->DLY = SPI_DLY_PRE_DELAY(pConfig->PreDelay);
161 pSPI->DLY |= SPI_DLY_POST_DELAY(pConfig->PostDelay);
162 pSPI->DLY |= SPI_DLY_FRAME_DELAY(pConfig->FrameDelay);
163 if (pConfig->TransferDelay) {
164 pSPI->DLY |= SPI_DLY_TRANSFER_DELAY(pConfig->TransferDelay - 1);
165 }
166 }
167
168 /* Disable/Enable Interrupt */
Chip_SPI_Int_Cmd(LPC_SPI_T * pSPI,uint32_t IntMask,FunctionalState NewState)169 void Chip_SPI_Int_Cmd(LPC_SPI_T *pSPI, uint32_t IntMask, FunctionalState NewState)
170 {
171 if (NewState == ENABLE) {
172 pSPI->INTENSET |= (IntMask & SPI_INTENSET_BITMASK);
173 }
174 else {
175 pSPI->INTENCLR = (IntMask & SPI_INTENCLR_BITMASK);
176 }
177 }
178
179 /*Send and Receive SPI Data */
Chip_SPI_RWFrames_Blocking(LPC_SPI_T * pSPI,SPI_DATA_SETUP_T * pXfSetup)180 uint32_t Chip_SPI_RWFrames_Blocking(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
181 {
182 uint32_t Status;
183 /* Clear status */
184 Chip_SPI_ClearStatus(
185 pSPI,
186 SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR | SPI_STAT_CLR_SSA | SPI_STAT_CLR_SSD |
187 SPI_STAT_FORCE_EOT);
188 Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, pXfSetup->ssel | SPI_TXCTL_EOF);
189 pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
190 while ((pXfSetup->TxCnt < pXfSetup->Length) ||
191 (pXfSetup->RxCnt < pXfSetup->Length)) {
192 Status = Chip_SPI_GetStatus(pSPI);
193
194 /* In case of TxReady */
195 if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
196 SPI_Send_Data(pSPI, pXfSetup);
197 }
198
199 /*In case of Rx ready */
200 if ((Status & SPI_STAT_RXRDY) && (pXfSetup->RxCnt < pXfSetup->Length)) {
201 SPI_Receive_Data(pSPI, pXfSetup);
202 }
203 }
204 /* Check error */
205 if (Chip_SPI_GetStatus(pSPI) & (SPI_STAT_RXOV | SPI_STAT_TXUR)) {
206 return 0;
207 }
208 return pXfSetup->TxCnt;
209 }
210
Chip_SPI_WriteFrames_Blocking(LPC_SPI_T * pSPI,SPI_DATA_SETUP_T * pXfSetup)211 uint32_t Chip_SPI_WriteFrames_Blocking(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
212 {
213 /* Clear status */
214 Chip_SPI_ClearStatus(
215 pSPI,
216 SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR | SPI_STAT_CLR_SSA | SPI_STAT_CLR_SSD |
217 SPI_STAT_FORCE_EOT);
218 Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, pXfSetup->ssel | SPI_TXCTL_EOF | SPI_TXCTL_RXIGNORE);
219 pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
220 while (pXfSetup->TxCnt < pXfSetup->Length) {
221 /* Wait for TxReady */
222 while (!(Chip_SPI_GetStatus(pSPI) & SPI_STAT_TXRDY)) {}
223
224 SPI_Send_Data_RxIgnore(pSPI, pXfSetup);
225
226 }
227
228 /* Make sure the last frame sent completely*/
229 while (!(Chip_SPI_GetStatus(pSPI) & SPI_STAT_SSD)) {}
230 Chip_SPI_ClearStatus(pSPI, SPI_STAT_CLR_SSD);
231
232 /* Check overrun error */
233 if (Chip_SPI_GetStatus(pSPI) & SPI_STAT_TXUR) {
234 return 0;
235 }
236 return pXfSetup->TxCnt;
237 }
238
Chip_SPI_ReadFrames_Blocking(LPC_SPI_T * pSPI,SPI_DATA_SETUP_T * pXfSetup)239 uint32_t Chip_SPI_ReadFrames_Blocking(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
240 {
241 /* Clear status */
242 Chip_SPI_ClearStatus(
243 pSPI,
244 SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR | SPI_STAT_CLR_SSA | SPI_STAT_CLR_SSD |
245 SPI_STAT_FORCE_EOT);
246 Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, pXfSetup->ssel | SPI_TXCTL_EOF);
247 pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
248 while (pXfSetup->RxCnt < pXfSetup->Length) {
249 /* Wait for TxReady */
250 while (!(Chip_SPI_GetStatus(pSPI) & SPI_STAT_TXRDY)) {}
251
252 SPI_Send_Dummy(pSPI, pXfSetup);
253
254 /* Wait for receive data */
255 while (!(Chip_SPI_GetStatus(pSPI) & SPI_STAT_RXRDY)) {}
256
257 SPI_Receive_Data(pSPI, pXfSetup);
258
259 }
260 /* Check overrun error */
261 if (Chip_SPI_GetStatus(pSPI) & (SPI_STAT_RXOV | SPI_STAT_TXUR)) {
262 return 0;
263 }
264 return pXfSetup->RxCnt;
265 }
266
267 /* SPI Interrupt Read/Write with 8-bit frame width */
Chip_SPI_Int_RWFrames(LPC_SPI_T * pSPI,SPI_DATA_SETUP_T * pXfSetup)268 Status Chip_SPI_Int_RWFrames(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
269 {
270 uint32_t Status;
271
272 Status = Chip_SPI_GetStatus(pSPI);
273 /* Check error in STAT register */
274 if (Status & (SPI_STAT_RXOV | SPI_STAT_TXUR)) {
275 /* Clear errors */
276 Chip_SPI_ClearStatus(pSPI, SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR);
277 return ERROR;
278 }
279
280 if (pXfSetup->TxCnt == 0) {
281 if (pXfSetup->pRx == NULL) {
282 Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, pXfSetup->ssel | SPI_TXCTL_EOF | SPI_TXCTL_RXIGNORE);
283 }
284 else {
285 Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, pXfSetup->ssel | SPI_TXCTL_EOF);
286 }
287 }
288
289 if (pXfSetup->pRx == NULL) {
290 if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
291 SPI_Send_Data_RxIgnore(pSPI, pXfSetup);
292 }
293 }
294 else {
295 /* check if Tx ready */
296 if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
297 SPI_Send_Data(pSPI, pXfSetup);
298 }
299
300 /* check if RX FIFO contains data */
301 if ((Status & SPI_STAT_RXRDY) && (pXfSetup->RxCnt < pXfSetup->Length)) {
302 SPI_Receive_Data(pSPI, pXfSetup);
303 }
304 }
305
306 return SUCCESS;
307 }
308