| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
spi_8xx.c
Go to the documentation of this file.
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
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
46 static void SPI_Send_Data_RxIgnore(LPC_SPI_T *pSPI,
47 CHIP_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);
51 }
52 else {
53 Chip_SPI_SendMidFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt]);
54 }
55
56 pXfSetup->TxCnt++;
57 }
58
59 static void SPI_Send_Data(LPC_SPI_T *pSPI,
60 CHIP_SPI_DATA_SETUP_T *pXfSetup)
61 {
62 if (pXfSetup->TxCnt == (pXfSetup->Length - 1)) {
63 Chip_SPI_SendLastFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt], pXfSetup->DataSize);
64 }
65 else {
66 Chip_SPI_SendMidFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt]);
67 }
68
69 pXfSetup->TxCnt++;
70 }
71
72 static void SPI_Send_Dummy(LPC_SPI_T *pSPI,
73 CHIP_SPI_DATA_SETUP_T *pXfSetup)
74 {
75 if (pXfSetup->RxCnt == (pXfSetup->Length - 1)) {
76 Chip_SPI_SendLastFrame(pSPI, 0x55, pXfSetup->DataSize);
77 }
78 else {
79 Chip_SPI_SendMidFrame(pSPI, 0x55);
80 }
81 }
82
83 static void SPI_Receive_Data(LPC_SPI_T *pSPI,
84 CHIP_SPI_DATA_SETUP_T *pXfSetup)
85 {
86 pXfSetup->pRx[pXfSetup->RxCnt] = IP_SPI_ReceiveFrame(pSPI);
87 pXfSetup->RxCnt++;
88 }
89
90 /*****************************************************************************
91 * Public functions
92 ****************************************************************************/
93
94 /* Calculate the Clock Rate Divider for SPI Peripheral */
95 uint32_t Chip_SPI_CalClkRateDivider(LPC_SPI_T *pSPI, uint32_t bitRate)
96 {
97 uint32_t SPIClk;
98 uint32_t DivVal = 1;
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;
106 }
107
108 /* Initialize the SPI */
109 void Chip_SPI_Init(LPC_SPI_T *pSPI, SPI_CONFIG_T *pConfig)
110 {
111 if (pSPI == LPC_SPI1) {
112 /* Enable SPI clocking. SPI base clock(s) must already be enabled */
113 Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SPI1);
114
115 /* Reset SPI Peripheral */
116 Chip_SYSCTL_PeriphReset(RESET_SPI1);
117 }
118 else {
119 Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SPI0);
120 Chip_SYSCTL_PeriphReset(RESET_SPI0);
121 }
122
123 /* Configuration */
124 IP_SPI_Init(pSPI, pConfig);
125 }
126
127 /* De-initializes the SPI peripheral */
128 void Chip_SPI_DeInit(LPC_SPI_T *pSPI)
129 {
130 IP_SPI_DeInit(pSPI);
131
132 /* Disable SPI clocking */
133 if (pSPI == LPC_SPI1) {
134 Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SPI1);
135 }
136 else {
137 Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SPI0);
138 }
139 }
140
141 /* Disable/Enable Interrupt */
142 void Chip_SPI_Int_Cmd(LPC_SPI_T *pSPI, uint32_t IntMask, FunctionalState NewState)
143 {
144 if (NewState == ENABLE) {
145 IP_SPI_IntEnable(pSPI, IntMask);
146 }
147 else {
148 IP_SPI_IntDisable(pSPI, IntMask);
149 }
150 }
151
152 /*Send and Receive SPI Data */
153 uint32_t Chip_SPI_RWFrames_Blocking(LPC_SPI_T *pSPI, CHIP_SPI_DATA_SETUP_T *pXfSetup)
154 {
155 uint32_t Status;
156 /* Clear status */
157 IP_SPI_ClearStatus(pSPI, SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR | SPI_STAT_CLR_SSA | SPI_STAT_CLR_SSD);
158 IP_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, SPI_TXCTL_ASSERT_SSEL | SPI_TXCTL_EOF);
159 pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
160 while ((pXfSetup->TxCnt < pXfSetup->Length) ||
161 (pXfSetup->RxCnt < pXfSetup->Length)) {
162 Status = IP_SPI_GetStatus(pSPI);
163
164 /* In case of TxReady */
165 if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
166 SPI_Send_Data(pSPI, pXfSetup);
167 }
168
169 /*In case of Rx ready */
170 if ((Status & SPI_STAT_RXRDY) && (pXfSetup->RxCnt < pXfSetup->Length)) {
171 SPI_Receive_Data(pSPI, pXfSetup);
172 }
173 }
174 /* Check error */
175 if (IP_SPI_GetStatus(pSPI) & (SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR)) {
176 return 0;
177 }
178 return pXfSetup->TxCnt;
179 }
180
181 uint32_t Chip_SPI_WriteFrames_Blocking(LPC_SPI_T *pSPI, CHIP_SPI_DATA_SETUP_T *pXfSetup)
182 {
183 /* Clear status */
184 IP_SPI_ClearStatus(pSPI, SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR | SPI_STAT_CLR_SSA | SPI_STAT_CLR_SSD);
185 IP_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, SPI_TXCTL_ASSERT_SSEL | SPI_TXCTL_EOF | SPI_TXCTL_RXIGNORE);
186 pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
187 while (pXfSetup->TxCnt < pXfSetup->Length) {
188 /* Wait for TxReady */
189 while (!(IP_SPI_GetStatus(pSPI) & SPI_STAT_TXRDY)) {}
190
191 SPI_Send_Data_RxIgnore(pSPI, pXfSetup);
192
193 }
194
195 /* Make sure the last frame sent completely*/
196 while (!(IP_SPI_GetStatus(pSPI) & SPI_STAT_SSD)) {}
197 IP_SPI_ClearStatus(pSPI, SPI_STAT_CLR_SSD);
198
199 /* Check overrun error */
200 if (IP_SPI_GetStatus(pSPI) & SPI_STAT_CLR_TXUR) {
201 return 0;
202 }
203 return pXfSetup->TxCnt;
204 }
205
206 uint32_t Chip_SPI_ReadFrames_Blocking(LPC_SPI_T *pSPI, CHIP_SPI_DATA_SETUP_T *pXfSetup)
207 {
208 /* Clear status */
209 IP_SPI_ClearStatus(pSPI, SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR | SPI_STAT_CLR_SSA | SPI_STAT_CLR_SSD);
210 IP_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, SPI_TXCTL_ASSERT_SSEL | SPI_TXCTL_EOF);
211 pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
212 while (pXfSetup->RxCnt < pXfSetup->Length) {
213 /* Wait for TxReady */
214 while (!(IP_SPI_GetStatus(pSPI) & SPI_STAT_TXRDY)) {}
215
216 SPI_Send_Dummy(pSPI, pXfSetup);
217
218 /* Wait for receive data */
219 while (!(IP_SPI_GetStatus(pSPI) & SPI_STAT_RXRDY)) {}
220
221 SPI_Receive_Data(pSPI, pXfSetup);
222
223 }
224 /* Check overrun error */
225 if (IP_SPI_GetStatus(pSPI) & (SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR)) {
226 return 0;
227 }
228 return pXfSetup->RxCnt;
229 }
230
231 /* SPI Interrupt Read/Write with 8-bit frame width */
232 Status Chip_SPI_Int_RWFrames(LPC_SPI_T *pSPI, CHIP_SPI_DATA_SETUP_T *pXfSetup)
233 {
234 uint32_t Status;
235
236 Status = IP_SPI_GetStatus(pSPI);
237 /* Check error in INTSTAT register */
238 if (Status & (SPI_STAT_RXOV | SPI_STAT_TXUR)) {
239 return ERROR;
240 }
241
242 if (pXfSetup->TxCnt == 0) {
243 IP_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, SPI_TXCTL_ASSERT_SSEL | SPI_TXCTL_EOF);
244 }
245
246 if (pXfSetup->pRx == NULL) {
247 if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
248 SPI_Send_Data_RxIgnore(pSPI, pXfSetup);
249 }
250 }
251 else {
252 /* check if Tx ready */
253 if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
254 SPI_Send_Data(pSPI, pXfSetup);
255 }
256
257 /* check if RX FIFO contains data */
258 if ((Status & SPI_STAT_RXRDY) && (pXfSetup->RxCnt < pXfSetup->Length)) {
259 SPI_Receive_Data(pSPI, pXfSetup);
260 }
261 }
262
263 return SUCCESS;
264 }