LPCOpen Platform for LPC112X microcontrollers  112X
LPCOpen Platform for the NXP LPC112X family of Microcontrollers
ssp_112x.c
Go to the documentation of this file.
1 /*
2  * @brief LPC11xx SSP Registers and control functions
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 
47 {
48  if (xf_setup->tx_data) {
49  Chip_SSP_SendFrame(pSSP, (*(uint16_t *) ((uint32_t) xf_setup->tx_data +
50  xf_setup->tx_cnt)));
51  }
52  else {
53  Chip_SSP_SendFrame(pSSP, 0xFFFF);
54  }
55 
56  xf_setup->tx_cnt += 2;
57 }
58 
61 {
62  if (xf_setup->tx_data) {
63  Chip_SSP_SendFrame(pSSP, (*(uint8_t *) ((uint32_t) xf_setup->tx_data + xf_setup->tx_cnt)));
64  }
65  else {
66  Chip_SSP_SendFrame(pSSP, 0xFF);
67  }
68 
69  xf_setup->tx_cnt++;
70 }
71 
74 {
75  uint16_t rDat;
76 
77  while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET) &&
78  (xf_setup->rx_cnt < xf_setup->length)) {
79  rDat = Chip_SSP_ReceiveFrame(pSSP);
80  if (xf_setup->rx_data) {
81  *(uint16_t *) ((uint32_t) xf_setup->rx_data + xf_setup->rx_cnt) = rDat;
82  }
83 
84  xf_setup->rx_cnt += 2;
85  }
86 }
87 
90 {
91  uint16_t rDat;
92 
93  while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET) &&
94  (xf_setup->rx_cnt < xf_setup->length)) {
95  rDat = Chip_SSP_ReceiveFrame(pSSP);
96  if (xf_setup->rx_data) {
97  *(uint8_t *) ((uint32_t) xf_setup->rx_data + xf_setup->rx_cnt) = rDat;
98  }
99 
100  xf_setup->rx_cnt++;
101  }
102 }
103 
104 /* Returns clock for the peripheral block */
106 {
107  CHIP_SYSCON_CLOCK_T clkSSP;
108 
109  if (pSSP == LPC_SSP0) {
110  clkSSP = SYSCON_CLOCK_SSP0;
111  }
112  else {
113  clkSSP = SYSCON_CLOCK_SSP1;
114  }
115 
116  return clkSSP;
117 }
118 
119 /* Returns reset ID for the peripheral block */
121 {
123 
124  if (pSSP == LPC_SSP0) {
125  resetSSP = RESET_SSP0;
126  }
127  else {
128  resetSSP = RESET_SSP1;
129  }
130 
131  return resetSSP;
132 }
133 
134 /* Returns reset ID for the peripheral block */
135 STATIC void Chip_SSP_SetSSPClkDivider(LPC_SSP_T *pSSP, uint32_t div)
136 {
137  if (pSSP == LPC_SSP0) {
139  }
140  else {
142  }
143 }
144 
145 /* Returns SSP peripheral clock for the peripheral block */
147 {
148  uint32_t sspCLK = Chip_Clock_GetMainClockRate();
149 
150  if (pSSP == LPC_SSP0) {
151  sspCLK /= Chip_Clock_GetSSP0ClockDiv();
152  }
153  else {
154  sspCLK /= Chip_Clock_GetSSP1ClockDiv();
155  }
156 
157  return sspCLK;
158 }
159 
160 /*****************************************************************************
161  * Public functions
162  ****************************************************************************/
163 
164 /*Set up output clocks per bit for SSP bus*/
165 void Chip_SSP_SetClockRate(LPC_SSP_T *pSSP, uint32_t clk_rate, uint32_t prescale)
166 {
167  uint32_t temp;
168  temp = pSSP->CR0 & (~(SSP_CR0_SCR(0xFF)));
169  pSSP->CR0 = temp | (SSP_CR0_SCR(clk_rate));
170  pSSP->CPSR = prescale;
171 }
172 
173 /* SSP Polling Read/Write in blocking mode */
175 {
176  /* Clear all remaining frames in RX FIFO */
177  while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
178  Chip_SSP_ReceiveFrame(pSSP);
179  }
180 
181  /* Clear status */
183 
184  if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
185  while (xf_setup->rx_cnt < xf_setup->length || xf_setup->tx_cnt < xf_setup->length) {
186  /* write data to buffer */
187  if (( Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && ( xf_setup->tx_cnt < xf_setup->length) ) {
188  SSP_Write2BFifo(pSSP, xf_setup);
189  }
190 
191  /* Check overrun error */
192  if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
193  return ERROR;
194  }
195 
196  /* Check for any data available in RX FIFO */
197  SSP_Read2BFifo(pSSP, xf_setup);
198  }
199  }
200  else {
201  while (xf_setup->rx_cnt < xf_setup->length || xf_setup->tx_cnt < xf_setup->length) {
202  /* write data to buffer */
203  if (( Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && ( xf_setup->tx_cnt < xf_setup->length) ) {
204  SSP_Write1BFifo(pSSP, xf_setup);
205  }
206 
207  /* Check overrun error */
208  if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
209  return ERROR;
210  }
211 
212  /* Check for any data available in RX FIFO */
213  SSP_Read1BFifo(pSSP, xf_setup);
214  }
215  }
216  if (xf_setup->tx_data) {
217  return xf_setup->tx_cnt;
218  }
219  else if (xf_setup->rx_data) {
220  return xf_setup->rx_cnt;
221  }
222 
223  return 0;
224 }
225 
226 /* SSP Polling Write in blocking mode */
227 uint32_t Chip_SSP_WriteFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len)
228 {
229  uint32_t tx_cnt = 0, rx_cnt = 0;
230 
231  /* Clear all remaining frames in RX FIFO */
232  while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
233  Chip_SSP_ReceiveFrame(pSSP);
234  }
235 
236  /* Clear status */
238 
239  if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
240  uint16_t *wdata16;
241 
242  wdata16 = (uint16_t *) buffer;
243 
244  while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
245  /* write data to buffer */
246  if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
247  Chip_SSP_SendFrame(pSSP, *wdata16);
248  wdata16++;
249  tx_cnt += 2;
250  }
251 
252  /* Check overrun error */
253  if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
254  return ERROR;
255  }
256 
257  /* Check for any data available in RX FIFO */
258  while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET) {
259  Chip_SSP_ReceiveFrame(pSSP); /* read dummy data */
260  rx_cnt += 2;
261  }
262  }
263  }
264  else {
265  uint8_t *wdata8;
266 
267  wdata8 = buffer;
268 
269  while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
270  /* write data to buffer */
271  if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
272  Chip_SSP_SendFrame(pSSP, *wdata8);
273  wdata8++;
274  tx_cnt++;
275  }
276 
277  /* Check overrun error */
278  if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
279  return ERROR;
280  }
281 
282  /* Check for any data available in RX FIFO */
283  while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
284  Chip_SSP_ReceiveFrame(pSSP); /* read dummy data */
285  rx_cnt++;
286  }
287  }
288  }
289 
290  return tx_cnt;
291 
292 }
293 
294 /* SSP Polling Read in blocking mode */
295 uint32_t Chip_SSP_ReadFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len)
296 {
297  uint32_t rx_cnt = 0, tx_cnt = 0;
298 
299  /* Clear all remaining frames in RX FIFO */
300  while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
301  Chip_SSP_ReceiveFrame(pSSP);
302  }
303 
304  /* Clear status */
306 
307  if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
308  uint16_t *rdata16;
309 
310  rdata16 = (uint16_t *) buffer;
311 
312  while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
313  /* write data to buffer */
314  if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
315  Chip_SSP_SendFrame(pSSP, 0xFFFF); /* just send dummy data */
316  tx_cnt += 2;
317  }
318 
319  /* Check overrun error */
320  if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
321  return ERROR;
322  }
323 
324  /* Check for any data available in RX FIFO */
325  while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
326  *rdata16 = Chip_SSP_ReceiveFrame(pSSP);
327  rdata16++;
328  rx_cnt += 2;
329  }
330  }
331  }
332  else {
333  uint8_t *rdata8;
334 
335  rdata8 = buffer;
336 
337  while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
338  /* write data to buffer */
339  if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
340  Chip_SSP_SendFrame(pSSP, 0xFF); /* just send dummy data */
341  tx_cnt++;
342  }
343 
344  /* Check overrun error */
345  if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
346  return ERROR;
347  }
348 
349  /* Check for any data available in RX FIFO */
350  while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
351  *rdata8 = Chip_SSP_ReceiveFrame(pSSP);
352  rdata8++;
353  rx_cnt++;
354  }
355  }
356  }
357 
358  return rx_cnt;
359 
360 }
361 
362 /* Clean all data in RX FIFO of SSP */
364 {
365  if (Chip_SSP_GetStatus(pSSP, SSP_STAT_BSY)) {
366  while (Chip_SSP_GetStatus(pSSP, SSP_STAT_BSY)) {}
367  }
368 
369  /* Clear all remaining frames in RX FIFO */
370  while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
371  Chip_SSP_ReceiveFrame(pSSP);
372  }
373 
374  /* Clear status */
376 }
377 
378 /* SSP Interrupt Read/Write with 8-bit frame width */
380 {
381  /* Check overrun error in RIS register */
382  if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
383  return ERROR;
384  }
385 
386  if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)) {
387  /* check if RX FIFO contains data */
388  SSP_Read1BFifo(pSSP, xf_setup);
389 
390  while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF)) && (xf_setup->tx_cnt != xf_setup->length)) {
391  /* Write data to buffer */
392  SSP_Write1BFifo(pSSP, xf_setup);
393 
394  /* Check overrun error in RIS register */
395  if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
396  return ERROR;
397  }
398 
399  /* Check for any data available in RX FIFO */
400  SSP_Read1BFifo(pSSP, xf_setup);
401  }
402 
403  return SUCCESS;
404  }
405 
406  return ERROR;
407 }
408 
409 /* SSP Interrupt Read/Write with 16-bit frame width */
411 {
412  /* Check overrun error in RIS register */
413  if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
414  return ERROR;
415  }
416 
417  if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)) {
418  /* check if RX FIFO contains data */
419  SSP_Read2BFifo(pSSP, xf_setup);
420 
421  while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF)) && (xf_setup->tx_cnt != xf_setup->length)) {
422  /* Write data to buffer */
423  SSP_Write2BFifo(pSSP, xf_setup);
424 
425  /* Check overrun error in RIS register */
426  if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
427  return ERROR;
428  }
429 
430  /* Check for any data available in RX FIFO */
431  SSP_Read2BFifo(pSSP, xf_setup);
432  }
433 
434  return SUCCESS;
435  }
436 
437  return ERROR;
438 }
439 
440 /* Set the SSP operating modes, master or slave */
441 void Chip_SSP_SetMaster(LPC_SSP_T *pSSP, bool master)
442 {
443  if (master) {
445  }
446  else {
448  }
449 }
450 
451 /* Set the clock frequency for SSP interface */
452 void Chip_SSP_SetBitRate(LPC_SSP_T *pSSP, uint32_t bitRate)
453 {
454  uint32_t ssp_clk, cr0_div, cmp_clk, prescale;
455 
456  ssp_clk = Chip_SSP_GetPCLKkRate(pSSP);
457 
458  cr0_div = 0;
459  cmp_clk = 0xFFFFFFFF;
460  prescale = 2;
461 
462  while (cmp_clk > bitRate) {
463  cmp_clk = ssp_clk / ((cr0_div + 1) * prescale);
464  if (cmp_clk > bitRate) {
465  cr0_div++;
466  if (cr0_div > 0xFF) {
467  cr0_div = 0;
468  prescale += 2;
469  }
470  }
471  }
472 
473  Chip_SSP_SetClockRate(pSSP, cr0_div, prescale);
474 }
475 
476 /* Initialize the SSP */
478 {
480  Chip_SSP_SetSSPClkDivider(pSSP, 1);
482 
485  Chip_SSP_SetBitRate(pSSP, 100000);
486 }
487 
488 /* De-initializes the SSP peripheral */
490 {
491  Chip_SSP_Disable(pSSP);
492 
494  Chip_SSP_SetSSPClkDivider(pSSP, 0);
495 }