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