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