| 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
ssp_18xx_43xx.c
Go to the documentation of this file.
1 /*
2 * @brief LPC18xx/43xx SSP 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 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 ****************************************************************************/
38 #define SSP_Write2BFifo(pSSP, \
39 xf_setup) if (xf_setup->tx_data) {IP_SSP_SendFrame(pSSP, \
40 (*(uint16_t *) ((uint32_t) xf_setup->tx_data \
41 + xf_setup->tx_cnt))); } \
42 else {IP_SSP_SendFrame(pSSP, 0xFFFF); } \
43 xf_setup->tx_cnt += 2;
44
46 #define SSP_Write1BFifo(pSSP, \
47 xf_setup) if (xf_setup->tx_data) {IP_SSP_SendFrame(pSSP, \
48 (*(uint8_t *) ((uint32_t) xf_setup->tx_data \
49 + xf_setup->tx_cnt))); } \
50 else {IP_SSP_SendFrame(pSSP, 0xFF); } \
51 xf_setup->tx_cnt++;
52
54 #define SSP_Read2BFifo(pSSP, xf_setup, \
55 rDat) while (IP_SSP_GetStatus(pSSP, \
56 SSP_STAT_RNE) == SET && xf_setup->rx_cnt < xf_setup->length) { \
57 rDat = IP_SSP_ReceiveFrame(pSSP); \
58 if (xf_setup->rx_data) { \
59 *(uint16_t *) ((uint32_t) xf_setup->rx_data + xf_setup->rx_cnt) = rDat; \
60 } \
61 xf_setup->rx_cnt += 2; \
62 }
63
65 #define SSP_Read1BFifo(pSSP, xf_setup, \
66 rDat) while (IP_SSP_GetStatus(pSSP, \
67 SSP_STAT_RNE) == SET && xf_setup->rx_cnt < xf_setup->length) { \
68 rDat = IP_SSP_ReceiveFrame(pSSP); \
69 if (xf_setup->rx_data) { \
70 *(uint8_t *) ((uint32_t) xf_setup->rx_data + xf_setup->rx_cnt) = rDat; \
71 } \
72 xf_setup->rx_cnt++; \
73 }
74
75 /*****************************************************************************
76 * Public types/enumerations/variables
77 ****************************************************************************/
78
79 /*****************************************************************************
80 * Private functions
81 ****************************************************************************/
82
83 /*****************************************************************************
84 * Public functions
85 ****************************************************************************/
86
87 /* SSP Polling Read/Write in blocking mode */
88 uint32_t Chip_SSP_RWFrames_Blocking(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
89 {
90 uint16_t rDat;
91
92 /* Clear all remaining frames in RX FIFO */
93 while (IP_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
94 IP_SSP_ReceiveFrame(pSSP);
95 }
96
97 /* Clear status */
98 IP_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
99
100 if (IP_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
101 while (xf_setup->rx_cnt < xf_setup->length || xf_setup->tx_cnt < xf_setup->length) {
102 /* write data to buffer */
103 if (( IP_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && ( xf_setup->tx_cnt < xf_setup->length) ) {
104 SSP_Write2BFifo(pSSP, xf_setup)
105 }
106
107 /* Check overrun error */
108 if (IP_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
109 return ERROR;
110 }
111
112 /* Check for any data available in RX FIFO */
113 SSP_Read2BFifo(pSSP, xf_setup, rDat)
114 }
115
116 if (xf_setup->tx_data) {
117 return xf_setup->tx_cnt;
118 }
119 else if (xf_setup->rx_data) {
120 return xf_setup->rx_cnt;
121 }
122 return 0;
123 }
124 else {
125 while (xf_setup->rx_cnt < xf_setup->length || xf_setup->tx_cnt < xf_setup->length) {
126 /* write data to buffer */
127 if (( IP_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && ( xf_setup->tx_cnt < xf_setup->length) ) {
128 SSP_Write1BFifo(pSSP, xf_setup)
129 }
130
131 /* Check overrun error */
132 if (IP_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
133 return ERROR;
134 }
135
136 /* Check for any data available in RX FIFO */
137 SSP_Read1BFifo(pSSP, xf_setup, rDat)
138 }
139
140 if (xf_setup->tx_data) {
141 return xf_setup->tx_cnt;
142 }
143 else if (xf_setup->rx_data) {
144 return xf_setup->rx_cnt;
145 }
146 return 0;
147 }
148 }
149
150 /* SSP Polling Write in blocking mode */
151 uint32_t Chip_SSP_WriteFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len)
152 {
153 uint32_t tx_cnt = 0, rx_cnt = 0;
154
155 /* Clear all remaining frames in RX FIFO */
156 while (IP_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
157 IP_SSP_ReceiveFrame(pSSP);
158 }
159
160 /* Clear status */
161 IP_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
162
163 if (IP_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
164 uint16_t *wdata16;
165
166 wdata16 = (uint16_t *) buffer;
167
168 while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
169 /* write data to buffer */
170 if ((IP_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
171 IP_SSP_SendFrame(pSSP, *wdata16);
172 wdata16++;
173 tx_cnt += 2;
174 }
175
176 /* Check overrun error */
177 if (IP_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
178 return ERROR;
179 }
180
181 /* Check for any data available in RX FIFO */
182 while (IP_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET) {
183 IP_SSP_ReceiveFrame(pSSP); /* read dummy data */
184 rx_cnt += 2;
185 }
186 }
187
188 return tx_cnt;
189 }
190 else {
191 uint8_t *wdata8;
192
193 wdata8 = buffer;
194
195 while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
196 /* write data to buffer */
197 if ((IP_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
198 IP_SSP_SendFrame(pSSP, *wdata8);
199 wdata8++;
200 tx_cnt++;
201 }
202
203 /* Check overrun error */
204 if (IP_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
205 return ERROR;
206 }
207
208 /* Check for any data available in RX FIFO */
209 while (IP_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
210 IP_SSP_ReceiveFrame(pSSP); /* read dummy data */
211 rx_cnt++;
212 }
213 }
214
215 return tx_cnt;
216 }
217 }
218
219 /* SSP Polling Read in blocking mode */
220 uint32_t Chip_SSP_ReadFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len)
221 {
222 uint32_t rx_cnt = 0, tx_cnt = 0;
223
224 /* Clear all remaining frames in RX FIFO */
225 while (IP_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
226 IP_SSP_ReceiveFrame(pSSP);
227 }
228
229 /* Clear status */
230 IP_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
231
232 if (IP_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
233 uint16_t *rdata16;
234
235 rdata16 = (uint16_t *) buffer;
236
237 while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
238 /* write data to buffer */
239 if ((IP_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
240 IP_SSP_SendFrame(pSSP, 0xFFFF); /* just send dummy data */
241 tx_cnt += 2;
242 }
243
244 /* Check overrun error */
245 if (IP_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
246 return ERROR;
247 }
248
249 /* Check for any data available in RX FIFO */
250 while (IP_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
251 *rdata16 = IP_SSP_ReceiveFrame(pSSP);
252 rdata16++;
253 rx_cnt += 2;
254 }
255 }
256
257 return rx_cnt;
258 }
259 else {
260 uint8_t *rdata8;
261
262 rdata8 = buffer;
263
264 while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
265 /* write data to buffer */
266 if ((IP_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
267 IP_SSP_SendFrame(pSSP, 0xFF); /* just send dummy data */
268 tx_cnt++;
269 }
270
271 /* Check overrun error */
272 if (IP_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
273 return ERROR;
274 }
275
276 /* Check for any data available in RX FIFO */
277 while (IP_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
278 *rdata8 = IP_SSP_ReceiveFrame(pSSP);
279 rdata8++;
280 rx_cnt++;
281 }
282 }
283
284 return rx_cnt;
285 }
286 }
287
288 /* Clean all data in RX FIFO of SSP */
289 void Chip_SSP_Int_FlushData(LPC_SSP_T *pSSP)
290 {
291 if (IP_SSP_GetStatus(pSSP, SSP_STAT_BSY)) {
292 while (IP_SSP_GetStatus(pSSP, SSP_STAT_BSY)) {}
293 }
294
295 /* Clear all remaining frames in RX FIFO */
296 while (IP_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
297 IP_SSP_ReceiveFrame(pSSP);
298 }
299
300 /* Clear status */
301 IP_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
302 }
303
304 /* SSP Interrupt Read/Write with 8-bit frame width */
305 Status Chip_SSP_Int_RWFrames8Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
306 {
307 uint16_t rDat;
308
309 /* Check overrun error in RIS register */
310 if (IP_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
311 return ERROR;
312 }
313
314 if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)) {
315 /* check if RX FIFO contains data */
316 SSP_Read1BFifo(pSSP, xf_setup, rDat)
317
318 while ((IP_SSP_GetStatus(pSSP, SSP_STAT_TNF)) && (xf_setup->tx_cnt != xf_setup->length)) {
319 /* Write data to buffer */
320 SSP_Write1BFifo(pSSP, xf_setup)
321
322 /* Check overrun error in RIS register */
323 if (IP_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
324 return ERROR;
325 }
326
327 /* Check for any data available in RX FIFO */
328 SSP_Read1BFifo(pSSP, xf_setup, rDat)
329 }
330 return SUCCESS;
331 }
332
333 return ERROR;
334 }
335
336 /* SSP Interrupt Read/Write with 16-bit frame width */
337 Status Chip_SSP_Int_RWFrames16Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
338 {
339 uint16_t rDat;
340
341 /* Check overrun error in RIS register */
342 if (IP_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
343 return ERROR;
344 }
345
346 if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)) {
347 /* check if RX FIFO contains data */
348 SSP_Read2BFifo(pSSP, xf_setup, rDat)
349
350 while ((IP_SSP_GetStatus(pSSP, SSP_STAT_TNF)) && (xf_setup->tx_cnt != xf_setup->length)) {
351 /* Write data to buffer */
352 SSP_Write2BFifo(pSSP, xf_setup)
353
354 /* Check overrun error in RIS register */
355 if (IP_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
356 return ERROR;
357 }
358
359 /* Check for any data available in RX FIFO */
360 SSP_Read2BFifo(pSSP, xf_setup, rDat)
361 }
362 return SUCCESS;
363 }
364
365 return ERROR;
366 }
367
368 /* Set the SSP operating modes, master or slave */
369 void Chip_SSP_SetMaster(LPC_SSP_T *pSSP, bool master)
370 {
371 if (master) {
372 IP_SSP_Set_Mode(pSSP, SSP_MODE_MASTER);
373 }
374 else {
375 IP_SSP_Set_Mode(pSSP, SSP_MODE_SLAVE);
376 }
377 }
378
379 /* Set the clock frequency for SSP interface */
380 void Chip_SSP_SetBitRate(LPC_SSP_T *pSSP, uint32_t bitRate)
381 {
382 uint32_t ssp_clk, cr0_div, cmp_clk, prescale;
383
384 if (pSSP == LPC_SSP0) {
385 ssp_clk = Chip_Clock_GetRate(CLK_MX_SSP0);
386 }
387 else {
388 ssp_clk = Chip_Clock_GetRate(CLK_MX_SSP1);
389 }
390
391 cr0_div = 0;
392 cmp_clk = 0xFFFFFFFF;
393 prescale = 2;
394
395 while (cmp_clk > bitRate) {
396 cmp_clk = ssp_clk / ((cr0_div + 1) * prescale);
397 if (cmp_clk > bitRate) {
398 cr0_div++;
399 if (cr0_div > 0xFF) {
400 cr0_div = 0;
401 prescale += 2;
402 }
403 }
404 }
405
406 IP_SSP_Set_ClockRate(pSSP, cr0_div, prescale);
407 }
408
409 /* Initialize the SSP */
410 void Chip_SSP_Init(LPC_SSP_T *pSSP)
411 {
412 if (pSSP == LPC_SSP0) {
413 Chip_Clock_Enable(CLK_MX_SSP0);
414 }
415 else {
416 Chip_Clock_Enable(CLK_MX_SSP1);
417 }
418
419 IP_SSP_Set_Mode(pSSP, SSP_MODE_MASTER);
420 IP_SSP_SetFormat(pSSP, SSP_BITS_8, SSP_FRAMEFORMAT_SPI, SSP_CLOCK_CPHA0_CPOL0);
421 Chip_SSP_SetBitRate(pSSP, 100000);
422 }
423
424 /* Shutdown the SSP */
425 void Chip_SSP_DeInit(LPC_SSP_T *pSSP)
426 {
427 IP_SSP_DeInit(pSSP);
428
429 if (pSSP == LPC_SSP0) {
430 Chip_Clock_Disable(CLK_MX_SSP0);
431 }
432 else {
433 Chip_Clock_Disable(CLK_MX_SSP1);
434 }
435 }