LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
298 }
299 
300 /* SSP Interrupt Read/Write with 8-bit frame width */
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 */
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) {
369  }
370  else {
372  }
373 }
374 
375 /* Determine clock for uart BASED ON SELECTED uart */
377 
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 */
397 {
398 #if !defined(CHIP_LPC175X_6X)
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 */
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 */
440 {
441  /* Enable SSP clocking. SSP base clock(s) must already be enabled */
443 
446  Chip_SSP_SetBitRate(pSSP, 100000);
447 }
448 
449 /* De-initializes the SSP peripheral */
451 {
452  IP_SSP_DeInit(pSSP);
453 
454  /* Disable SSP clocking */
456 }