iLLD_TC27xC  1.0
IfxQspi.c
Go to the documentation of this file.
1 /**
2  * \file IfxQspi.c
3  * \brief QSPI basic functionality
4  *
5  * \version iLLD_0_1_0_10
6  * \copyright Copyright (c) 2013 Infineon Technologies AG. All rights reserved.
7  *
8  *
9  * IMPORTANT NOTICE
10  *
11  *
12  * Infineon Technologies AG (Infineon) is supplying this file for use
13  * exclusively with Infineon's microcontroller products. This file can be freely
14  * distributed within development tools that are supporting such microcontroller
15  * products.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
18  * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
20  * INFINEON SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
21  * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
22  *
23  */
24 
25 /******************************************************************************/
26 /*----------------------------------Includes----------------------------------*/
27 /******************************************************************************/
28 
29 #include "IfxQspi.h"
30 
31 /******************************************************************************/
32 /*-------------------------Function Implementations---------------------------*/
33 /******************************************************************************/
34 
35 float IfxQspi_calcRealBaudrate(Ifx_QSPI *qspi, IfxQspi_ChannelId channelId)
36 {
37  int cs = channelId % 8;
38  float fQspi = IfxScuCcu_getMaxFrequency();
39  Ifx_QSPI_ECON econ[8];
40  econ[cs].U = qspi->ECON[cs].U;
41  fQspi = fQspi / (qspi->GLOBALCON.B.TQ + 1);
42  fQspi = fQspi / (econ[cs].B.Q + 1);
43  fQspi = fQspi / ((econ[cs].B.A + 1) + econ[cs].B.B + econ[cs].B.C);
44  return fQspi;
45 }
46 
47 
48 uint32 IfxQspi_calculateBasicConfigurationValue(Ifx_QSPI *qspi, const IfxQspi_ChannelId channelId, const SpiIf_ChMode *chMode, const float baudrate)
49 {
50  Ifx_QSPI_BACON bacon;
51  bacon.U = 0;
52 
53  uint32 pre = IfxQspi_calculatePrescaler(qspi, baudrate);
54 
55  bacon.B.LAST = 0; /* 1-bits Last Word in a Frame, will be set via recalcBasicConfiguration before transfer */
56  bacon.B.IPRE = pre; /* 3-bits Prescaler for the Idle Delay */
57  bacon.B.IDLE = chMode->csInactiveDelay; /* 3-bits Idle Delay Length */
58  bacon.B.LPRE = pre; /* 3-bits Prescaler for the Leading Delay */
59  bacon.B.LEAD = chMode->csLeadDelay; /* 3-bits Leading Delay Length */
60  bacon.B.TPRE = pre; /* 3-bits Prescaler for the Trailing Delay */
61  bacon.B.TRAIL = chMode->csTrailDelay; /* 2-bits Trailing Delay Length */
62  bacon.B.PARTYP = (chMode->parityMode == Ifx_ParityMode_even) ? 0 : 1;
63  bacon.B.UINT = 0; /* 1-bits User Interrupt at the PT1 Event in the Subsequent Frames */
64  bacon.B.MSB = (chMode->dataHeading == SpiIf_DataHeading_lsbFirst) ? 0 : 1;
65  bacon.B.BYTE = 0; /* only support bitwise selection in B.DL */
66  bacon.B.DL = chMode->dataWidth - 1;
67  bacon.B.CS = channelId;
68 
69  return bacon.U;
70 }
71 
72 
73 uint32 IfxQspi_calculateExtendedConfigurationValue(Ifx_QSPI *qspi, const uint8 cs, const SpiIf_ChConfig *chConfig)
74 {
75  Ifx_QSPI_ECON econ;
76  econ.U = 0;
77 
78  float32 tQspi = 1.0f / IfxQspi_getTimeQuantaFrequency(qspi);
79  float32 tBaud = 1.0f / chConfig->baudrate;
80  int abcMin = (2);
81  int abcMax = (4 + 0 + 4);
82  int q, bestQ = 0, abc, bestAbc = abcMax;
83  float32 error, bestError;
84  boolean done = FALSE;
85 
86  bestError = 1e6;
87 
88  for (q = 1; q <= 64; q++)
89  {
90  for (abc = abcMax; abc >= abcMin; abc -= 2)
91  {
92  float32 tBaudTmp = tQspi * (q * abc);
93  error = __absf(tBaudTmp - tBaud);
94 
95  if (__leqf(error, bestError) && ((q * abc) >= 4))
96  {
97  bestError = error;
98  bestAbc = abc;
99  bestQ = q;
100 
101  if (bestAbc > 5)
102  {
103  done = (!__neqf(error, 0.0)) ? TRUE : FALSE;
104 
105  if (done != FALSE)
106  {
107  break;
108  }
109  }
110  }
111  }
112 
113  if (done != FALSE)
114  {
115  break;
116  }
117  }
118 
119  econ.B.Q = bestQ - 1;
120  econ.B.A = (bestAbc / 2) - 1;
121  econ.B.C = __min(bestAbc / 2, 3);
122  econ.B.B = bestAbc - (econ.B.C + (econ.B.A + 1));
123  econ.B.CPH = (chConfig->mode.shiftClock == SpiIf_ShiftClock_shiftTransmitDataOnLeadingEdge) ? 1 : 0;
124  econ.B.CPOL = (chConfig->mode.clockPolarity == SpiIf_ClockPolarity_idleLow) ? 0 : 1;
125  econ.B.PAREN = chConfig->mode.parityCheck;
126 
127  return econ.U;
128 }
129 
130 
131 uint32 IfxQspi_calculatePrescaler(Ifx_QSPI *qspi, float baudrate)
132 {
133  float error, bestError;
134  float halfBaud = baudrate / 2;
135  float fQspiIn = IfxQspi_getModuleFrequency(qspi);
136  bestError = 10e6;
137  uint32 i, bestPre = 0;
138 
139  for (i = 0; i < 8; i++)
140  {
141  float tempHalfBaud = fQspiIn / (1U << (4 * i));
142  error = __absf(tempHalfBaud - halfBaud);
143 
144  if (__leqf(error, bestError))
145  {
146  bestError = error;
147  bestPre = i;
148  }
149  }
150 
151  return bestPre;
152 }
153 
154 
155 uint32 IfxQspi_calculateTimeQuantumLength(Ifx_QSPI *qspi, float maxBaudrate)
156 {
157  float divider = IfxScuCcu_getMaxFrequency() / (4.0 * maxBaudrate);
158  uint32 tq = __max((uint32)__roundf(divider) - 1, 0);
159  return tq;
160 }
161 
162 
163 void IfxQspi_read16(Ifx_QSPI *qspi, uint16 *data, Ifx_SizeT count)
164 {
165  volatile Ifx_QSPI_RXEXIT *rxFifo = &qspi->RXEXIT;
166 
167  while (count > 0)
168  {
169  *(data++) = (uint16)rxFifo->U;
170  count--;
171  }
172 }
173 
174 
175 void IfxQspi_read32(Ifx_QSPI *qspi, uint32 *data, Ifx_SizeT count)
176 {
177  volatile Ifx_QSPI_RXEXIT *rxFifo = &qspi->RXEXIT;
178 
179  while (count > 0)
180  {
181  *(data++) = rxFifo->U;
182  count--;
183  }
184 }
185 
186 
187 void IfxQspi_read8(Ifx_QSPI *qspi, uint8 *data, Ifx_SizeT count)
188 {
189  volatile Ifx_QSPI_RXEXIT *rxFifo = &qspi->RXEXIT;
190 
191  while (count > 0)
192  {
193  *(data++) = (uint8)rxFifo->U;
194  count--;
195  }
196 }
197 
198 
199 uint32 IfxQspi_recalcBasicConfiguration(uint32 oldBACON, Ifx_SizeT numOfData, boolean shortData, boolean lastData)
200 {
201  Ifx_QSPI_BACON bacon;
202  bacon.U = oldBACON;
203 
204  if (shortData == FALSE)
205  {
206  bacon.B.DL = numOfData;
207  }
208 
209  bacon.B.LAST = lastData;
210  return bacon.U;
211 }
212 
213 
214 void IfxQspi_setSlaveSelectOutputControl(Ifx_QSPI *qspi, IfxQspi_ChannelId channelId, boolean outputEnable, boolean activeLevel)
215 {
216  uint16 mask = 1 << channelId;
217 
218  Ifx_QSPI_SSOC ssoc;
219  ssoc.U = qspi->SSOC.U;
220 
221  if (outputEnable)
222  {
223  ssoc.B.OEN |= mask;
224  }
225  else
226  {
227  ssoc.B.OEN &= ~mask;
228  }
229 
230  if (activeLevel)
231  {
232  ssoc.B.AOL |= mask;
233  }
234  else
235  {
236  ssoc.B.AOL &= ~mask;
237  }
238 
239  qspi->SSOC.U = ssoc.U;
240 }
241 
242 
243 void IfxQspi_write16(Ifx_QSPI *qspi, IfxQspi_ChannelId channelId, uint16 *data, Ifx_SizeT count)
244 {
245  int cs = channelId % 8;
246  volatile Ifx_QSPI_DATAENTRY *dataEntry = &qspi->DATAENTRY[cs];
247 
248  while (count > 0)
249  {
250  dataEntry->U = *(data++);
251  count--;
252  }
253 }
254 
255 
256 void IfxQspi_write32(Ifx_QSPI *qspi, IfxQspi_ChannelId channelId, uint32 *data, Ifx_SizeT count)
257 {
258  int cs = channelId % 8;
259  volatile Ifx_QSPI_DATAENTRY *dataEntry = &qspi->DATAENTRY[cs];
260 
261  while (count > 0)
262  {
263  dataEntry->U = *(data++);
264  count--;
265  }
266 }
267 
268 
269 void IfxQspi_write8(Ifx_QSPI *qspi, IfxQspi_ChannelId channelId, uint8 *data, Ifx_SizeT count)
270 {
271  int cs = channelId % 8;
272  volatile Ifx_QSPI_DATAENTRY *dataEntry = &qspi->DATAENTRY[cs];
273 
274  while (count > 0)
275  {
276  dataEntry->U = *(data++);
277  count--;
278  }
279 }