LPCOpen Platform for LPC18XX/43XX microcontrollers: C:/w/lpcopen_docs/software/lpc_core/lpc_chip/chip_18xx_43xx/ssp_18xx_43xx.c Source File

| LPCOpen Platform for LPC18XX/43XX microcontrollers 18XX43XX LPCOpen Platform for the NXP LPC18XX/43XX family of Microcontrollers

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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 ****************************************************************************/
37
38 /*****************************************************************************
39 * Public types/enumerations/variables
40 ****************************************************************************/
41
42 /*****************************************************************************
43 * Private functions
44 ****************************************************************************/
45
46 STATIC void SSP_Write2BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
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
60 STATIC void SSP_Write1BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
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
73 STATIC void SSP_Read2BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
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
89 STATIC void SSP_Read1BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
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 index for the register interface */
105 STATIC CHIP_CCU_CLK_T Chip_SSP_GetClockIndex(LPC_SSP_T *pSSP)
106 {
107 CHIP_CCU_CLK_T clkSSP;
108
109 if (pSSP == LPC_SSP1) {
110 clkSSP = CLK_MX_SSP1;
111 }
112 else {
113 clkSSP = CLK_MX_SSP0;
114 }
115
116 return clkSSP;
117 }
118
119 /* Returns clock index for the peripheral block */
120 STATIC CHIP_CCU_CLK_T Chip_SSP_GetPeriphClockIndex(LPC_SSP_T *pSSP)
121 {
122 CHIP_CCU_CLK_T clkSSP;
123
124 if (pSSP == LPC_SSP1) {
125 clkSSP = CLK_APB2_SSP1;
126 }
127 else {
128 clkSSP = CLK_APB0_SSP0;
129 }
130
131 return clkSSP;
132 }
133 /*****************************************************************************
134 * Public functions
135 ****************************************************************************/
136
137 /*Set up output clocks per bit for SSP bus*/
138 void Chip_SSP_SetClockRate(LPC_SSP_T *pSSP, uint32_t clk_rate, uint32_t prescale)
139 {
140 uint32_t temp;
141 temp = pSSP->CR0 & (~(SSP_CR0_SCR(0xFF)));
142 pSSP->CR0 = temp | (SSP_CR0_SCR(clk_rate));
143 pSSP->CPSR = prescale;
144 }
145
146 /* SSP Polling Read/Write in blocking mode */
147 uint32_t Chip_SSP_RWFrames_Blocking(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
148 {
149 /* Clear all remaining frames in RX FIFO */
150 while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
151 Chip_SSP_ReceiveFrame(pSSP);
152 }
153
154 /* Clear status */
155 Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
156
157 if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
158 while (xf_setup->rx_cnt < xf_setup->length || xf_setup->tx_cnt < xf_setup->length) {
159 /* write data to buffer */
160 if (( Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && ( xf_setup->tx_cnt < xf_setup->length) ) {
161 SSP_Write2BFifo(pSSP, xf_setup);
162 }
163
164 /* Check overrun error */
165 if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
166 return ERROR;
167 }
168
169 /* Check for any data available in RX FIFO */
170 SSP_Read2BFifo(pSSP, xf_setup);
171 }
172 }
173 else {
174 while (xf_setup->rx_cnt < xf_setup->length || xf_setup->tx_cnt < xf_setup->length) {
175 /* write data to buffer */
176 if (( Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && ( xf_setup->tx_cnt < xf_setup->length) ) {
177 SSP_Write1BFifo(pSSP, xf_setup);
178 }
179
180 /* Check overrun error */
181 if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
182 return ERROR;
183 }
184
185 /* Check for any data available in RX FIFO */
186 SSP_Read1BFifo(pSSP, xf_setup);
187 }
188 }
189 if (xf_setup->tx_data) {
190 return xf_setup->tx_cnt;
191 }
192 else if (xf_setup->rx_data) {
193 return xf_setup->rx_cnt;
194 }
195
196 return 0;
197 }
198
199 /* SSP Polling Write in blocking mode */
200 uint32_t Chip_SSP_WriteFrames_Blocking(LPC_SSP_T *pSSP, const uint8_t *buffer, uint32_t buffer_len)
201 {
202 uint32_t tx_cnt = 0, rx_cnt = 0;
203
204 /* Clear all remaining frames in RX FIFO */
205 while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
206 Chip_SSP_ReceiveFrame(pSSP);
207 }
208
209 /* Clear status */
210 Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
211
212 if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
213 uint16_t *wdata16;
214
215 wdata16 = (uint16_t *) buffer;
216
217 while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
218 /* write data to buffer */
219 if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
220 Chip_SSP_SendFrame(pSSP, *wdata16);
221 wdata16++;
222 tx_cnt += 2;
223 }
224
225 /* Check overrun error */
226 if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
227 return ERROR;
228 }
229
230 /* Check for any data available in RX FIFO */
231 while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET) {
232 Chip_SSP_ReceiveFrame(pSSP); /* read dummy data */
233 rx_cnt += 2;
234 }
235 }
236 }
237 else {
238 const uint8_t *wdata8;
239
240 wdata8 = buffer;
241
242 while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
243 /* write data to buffer */
244 if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
245 Chip_SSP_SendFrame(pSSP, *wdata8);
246 wdata8++;
247 tx_cnt++;
248 }
249
250 /* Check overrun error */
251 if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
252 return ERROR;
253 }
254
255 /* Check for any data available in RX FIFO */
256 while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
257 Chip_SSP_ReceiveFrame(pSSP); /* read dummy data */
258 rx_cnt++;
259 }
260 }
261 }
262
263 return tx_cnt;
264
265 }
266
267 /* SSP Polling Read in blocking mode */
268 uint32_t Chip_SSP_ReadFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len)
269 {
270 uint32_t rx_cnt = 0, tx_cnt = 0;
271
272 /* Clear all remaining frames in RX FIFO */
273 while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
274 Chip_SSP_ReceiveFrame(pSSP);
275 }
276
277 /* Clear status */
278 Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
279
280 if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
281 uint16_t *rdata16;
282
283 rdata16 = (uint16_t *) buffer;
284
285 while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
286 /* write data to buffer */
287 if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
288 Chip_SSP_SendFrame(pSSP, 0xFFFF); /* just send dummy data */
289 tx_cnt += 2;
290 }
291
292 /* Check overrun error */
293 if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
294 return ERROR;
295 }
296
297 /* Check for any data available in RX FIFO */
298 while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
299 *rdata16 = Chip_SSP_ReceiveFrame(pSSP);
300 rdata16++;
301 rx_cnt += 2;
302 }
303 }
304 }
305 else {
306 uint8_t *rdata8;
307
308 rdata8 = buffer;
309
310 while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
311 /* write data to buffer */
312 if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
313 Chip_SSP_SendFrame(pSSP, 0xFF); /* just send dummy data */
314 tx_cnt++;
315 }
316
317 /* Check overrun error */
318 if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
319 return ERROR;
320 }
321
322 /* Check for any data available in RX FIFO */
323 while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
324 *rdata8 = Chip_SSP_ReceiveFrame(pSSP);
325 rdata8++;
326 rx_cnt++;
327 }
328 }
329 }
330
331 return rx_cnt;
332
333 }
334
335 /* Clean all data in RX FIFO of SSP */
336 void Chip_SSP_Int_FlushData(LPC_SSP_T *pSSP)
337 {
338 if (Chip_SSP_GetStatus(pSSP, SSP_STAT_BSY)) {
339 while (Chip_SSP_GetStatus(pSSP, SSP_STAT_BSY)) {}
340 }
341
342 /* Clear all remaining frames in RX FIFO */
343 while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
344 Chip_SSP_ReceiveFrame(pSSP);
345 }
346
347 /* Clear status */
348 Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
349 }
350
351 /* SSP Interrupt Read/Write with 8-bit frame width */
352 Status Chip_SSP_Int_RWFrames8Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
353 {
354 /* Check overrun error in RIS register */
355 if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
356 return ERROR;
357 }
358
359 if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)) {
360 /* check if RX FIFO contains data */
361 SSP_Read1BFifo(pSSP, xf_setup);
362
363 while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF)) && (xf_setup->tx_cnt != xf_setup->length)) {
364 /* Write data to buffer */
365 SSP_Write1BFifo(pSSP, xf_setup);
366
367 /* Check overrun error in RIS register */
368 if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
369 return ERROR;
370 }
371
372 /* Check for any data available in RX FIFO */
373 SSP_Read1BFifo(pSSP, xf_setup);
374 }
375
376 return SUCCESS;
377 }
378
379 return ERROR;
380 }
381
382 /* SSP Interrupt Read/Write with 16-bit frame width */
383 Status Chip_SSP_Int_RWFrames16Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
384 {
385 /* Check overrun error in RIS register */
386 if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
387 return ERROR;
388 }
389
390 if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)) {
391 /* check if RX FIFO contains data */
392 SSP_Read2BFifo(pSSP, xf_setup);
393
394 while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF)) && (xf_setup->tx_cnt != xf_setup->length)) {
395 /* Write data to buffer */
396 SSP_Write2BFifo(pSSP, xf_setup);
397
398 /* Check overrun error in RIS register */
399 if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
400 return ERROR;
401 }
402
403 /* Check for any data available in RX FIFO */
404 SSP_Read2BFifo(pSSP, xf_setup);
405 }
406
407 return SUCCESS;
408 }
409
410 return ERROR;
411 }
412
413 /* Set the SSP operating modes, master or slave */
414 void Chip_SSP_SetMaster(LPC_SSP_T *pSSP, bool master)
415 {
416 if (master) {
417 Chip_SSP_Set_Mode(pSSP, SSP_MODE_MASTER);
418 }
419 else {
420 Chip_SSP_Set_Mode(pSSP, SSP_MODE_SLAVE);
421 }
422 }
423
424 /* Set the clock frequency for SSP interface */
425 void Chip_SSP_SetBitRate(LPC_SSP_T *pSSP, uint32_t bitRate)
426 {
427 uint32_t ssp_clk, cr0_div, cmp_clk, prescale;
428
429 ssp_clk = Chip_Clock_GetRate(Chip_SSP_GetPeriphClockIndex(pSSP));
430
431 cr0_div = 0;
432 cmp_clk = 0xFFFFFFFF;
433 prescale = 2;
434
435 while (cmp_clk > bitRate) {
436 cmp_clk = ssp_clk / ((cr0_div + 1) * prescale);
437 if (cmp_clk > bitRate) {
438 cr0_div++;
439 if (cr0_div > 0xFF) {
440 cr0_div = 0;
441 prescale += 2;
442 }
443 }
444 }
445
446 Chip_SSP_SetClockRate(pSSP, cr0_div, prescale);
447 }
448
449 /* Initialize the SSP */
450 void Chip_SSP_Init(LPC_SSP_T *pSSP)
451 {
452 Chip_Clock_Enable(Chip_SSP_GetClockIndex(pSSP));
453 Chip_Clock_Enable(Chip_SSP_GetPeriphClockIndex(pSSP));
454
455 Chip_SSP_Set_Mode(pSSP, SSP_MODE_MASTER);
456 Chip_SSP_SetFormat(pSSP, SSP_BITS_8, SSP_FRAMEFORMAT_SPI, SSP_CLOCK_CPHA0_CPOL0);
457 Chip_SSP_SetBitRate(pSSP, 100000);
458 }
459
460 /* De-initializes the SSP peripheral */
461 void Chip_SSP_DeInit(LPC_SSP_T *pSSP)
462 {
463 Chip_SSP_Disable(pSSP);
464
465 Chip_Clock_Disable(Chip_SSP_GetPeriphClockIndex(pSSP));
466 Chip_Clock_Disable(Chip_SSP_GetClockIndex(pSSP));
467
468 }
469