LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
spi_8xx.c
Go to the documentation of this file.
1 /*
2  * @brief LPC8xx SPI 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 licenser 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  CHIP_SPI_DATA_SETUP_T *pXfSetup)
48 {
49  if (pXfSetup->TxCnt == (pXfSetup->Length - 1)) {
50  Chip_SPI_SendLastFrame_RxIgnore(pSPI, pXfSetup->pTx[pXfSetup->TxCnt], pXfSetup->DataSize);
51  }
52  else {
53  Chip_SPI_SendMidFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt]);
54  }
55 
56  pXfSetup->TxCnt++;
57 }
58 
59 static void SPI_Send_Data(LPC_SPI_T *pSPI,
60  CHIP_SPI_DATA_SETUP_T *pXfSetup)
61 {
62  if (pXfSetup->TxCnt == (pXfSetup->Length - 1)) {
63  Chip_SPI_SendLastFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt], pXfSetup->DataSize);
64  }
65  else {
66  Chip_SPI_SendMidFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt]);
67  }
68 
69  pXfSetup->TxCnt++;
70 }
71 
72 static void SPI_Send_Dummy(LPC_SPI_T *pSPI,
73  CHIP_SPI_DATA_SETUP_T *pXfSetup)
74 {
75  if (pXfSetup->RxCnt == (pXfSetup->Length - 1)) {
76  Chip_SPI_SendLastFrame(pSPI, 0x55, pXfSetup->DataSize);
77  }
78  else {
79  Chip_SPI_SendMidFrame(pSPI, 0x55);
80  }
81 }
82 
83 static void SPI_Receive_Data(LPC_SPI_T *pSPI,
84  CHIP_SPI_DATA_SETUP_T *pXfSetup)
85 {
86  pXfSetup->pRx[pXfSetup->RxCnt] = IP_SPI_ReceiveFrame(pSPI);
87  pXfSetup->RxCnt++;
88 }
89 
90 /*****************************************************************************
91  * Public functions
92  ****************************************************************************/
93 
94 /* Calculate the Clock Rate Divider for SPI Peripheral */
96 {
97  uint32_t SPIClk;
98  uint32_t DivVal = 1;
99 
100  /* Get SPI clock rate */
101  SPIClk = Chip_Clock_GetSystemClockRate(); /*The peripheral clock for both SPIs is the system clock*/
102 
103  DivVal = SPIClk / bitRate;
104 
105  return DivVal;
106 }
107 
108 /* Initialize the SPI */
109 void Chip_SPI_Init(LPC_SPI_T *pSPI, SPI_CONFIG_T *pConfig)
110 {
111  if (pSPI == LPC_SPI1) {
112  /* Enable SPI clocking. SPI base clock(s) must already be enabled */
114 
115  /* Reset SPI Peripheral */
117  }
118  else {
121  }
122 
123  /* Configuration */
124  IP_SPI_Init(pSPI, pConfig);
125 }
126 
127 /* De-initializes the SPI peripheral */
129 {
130  IP_SPI_DeInit(pSPI);
131 
132  /* Disable SPI clocking */
133  if (pSPI == LPC_SPI1) {
135  }
136  else {
138  }
139 }
140 
141 /* Disable/Enable Interrupt */
142 void Chip_SPI_Int_Cmd(LPC_SPI_T *pSPI, uint32_t IntMask, FunctionalState NewState)
143 {
144  if (NewState == ENABLE) {
145  IP_SPI_IntEnable(pSPI, IntMask);
146  }
147  else {
148  IP_SPI_IntDisable(pSPI, IntMask);
149  }
150 }
151 
152 /*Send and Receive SPI Data */
154 {
156  /* Clear status */
159  pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
160  while ((pXfSetup->TxCnt < pXfSetup->Length) ||
161  (pXfSetup->RxCnt < pXfSetup->Length)) {
162  Status = IP_SPI_GetStatus(pSPI);
163 
164  /* In case of TxReady */
165  if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
166  SPI_Send_Data(pSPI, pXfSetup);
167  }
168 
169  /*In case of Rx ready */
170  if ((Status & SPI_STAT_RXRDY) && (pXfSetup->RxCnt < pXfSetup->Length)) {
171  SPI_Receive_Data(pSPI, pXfSetup);
172  }
173  }
174  /* Check error */
176  return 0;
177  }
178  return pXfSetup->TxCnt;
179 }
180 
182 {
183  /* Clear status */
186  pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
187  while (pXfSetup->TxCnt < pXfSetup->Length) {
188  /* Wait for TxReady */
189  while (!(IP_SPI_GetStatus(pSPI) & SPI_STAT_TXRDY)) {}
190 
191  SPI_Send_Data_RxIgnore(pSPI, pXfSetup);
192 
193  }
194 
195  /* Make sure the last frame sent completely*/
196  while (!(IP_SPI_GetStatus(pSPI) & SPI_STAT_SSD)) {}
198 
199  /* Check overrun error */
200  if (IP_SPI_GetStatus(pSPI) & SPI_STAT_CLR_TXUR) {
201  return 0;
202  }
203  return pXfSetup->TxCnt;
204 }
205 
207 {
208  /* Clear status */
211  pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
212  while (pXfSetup->RxCnt < pXfSetup->Length) {
213  /* Wait for TxReady */
214  while (!(IP_SPI_GetStatus(pSPI) & SPI_STAT_TXRDY)) {}
215 
216  SPI_Send_Dummy(pSPI, pXfSetup);
217 
218  /* Wait for receive data */
219  while (!(IP_SPI_GetStatus(pSPI) & SPI_STAT_RXRDY)) {}
220 
221  SPI_Receive_Data(pSPI, pXfSetup);
222 
223  }
224  /* Check overrun error */
226  return 0;
227  }
228  return pXfSetup->RxCnt;
229 }
230 
231 /* SPI Interrupt Read/Write with 8-bit frame width */
233 {
235 
236  Status = IP_SPI_GetStatus(pSPI);
237  /* Check error in INTSTAT register */
238  if (Status & (SPI_STAT_RXOV | SPI_STAT_TXUR)) {
239  return ERROR;
240  }
241 
242  if (pXfSetup->TxCnt == 0) {
244  }
245 
246  if (pXfSetup->pRx == NULL) {
247  if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
248  SPI_Send_Data_RxIgnore(pSPI, pXfSetup);
249  }
250  }
251  else {
252  /* check if Tx ready */
253  if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
254  SPI_Send_Data(pSPI, pXfSetup);
255  }
256 
257  /* check if RX FIFO contains data */
258  if ((Status & SPI_STAT_RXRDY) && (pXfSetup->RxCnt < pXfSetup->Length)) {
259  SPI_Receive_Data(pSPI, pXfSetup);
260  }
261  }
262 
263  return SUCCESS;
264 }