iLLD_TC27xD  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_1_0_0_11_0
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  float32 tTmp, tBaudTmp;
85  boolean done = FALSE;
86 
87  bestError = 1e6;
88 
89  for (abc = abcMax; abc >= abcMin; abc -= 2)
90  {
91  tTmp = tQspi * abc;
92  q = ((tBaud / tTmp) + 0.5);
93 
94  if (q > 64)
95  {
96  q = 64;
97  }
98 
99  if (q < 2)
100  {
101  q = 2;
102  }
103 
104  tBaudTmp = tTmp * q;
105  error = __absf(tBaudTmp - tBaud);
106 
107  if (__leqf(error, bestError))
108  {
109  bestError = error;
110  bestAbc = abc;
111  bestQ = q;
112 
113  if (bestAbc > 5)
114  {
115  done = (!__neqf(error, 0.0)) ? TRUE : FALSE;
116 
117  if (done != FALSE)
118  {
119  break;
120  }
121  }
122  }
123  }
124 
125  econ.B.Q = bestQ - 1;
126  econ.B.A = (bestAbc / 2) - 1;
127  econ.B.C = __min(bestAbc / 2, 3);
128  econ.B.B = bestAbc - (econ.B.C + (econ.B.A + 1));
129  econ.B.CPH = (chConfig->mode.shiftClock == SpiIf_ShiftClock_shiftTransmitDataOnLeadingEdge) ? 1 : 0;
130  econ.B.CPOL = (chConfig->mode.clockPolarity == SpiIf_ClockPolarity_idleLow) ? 0 : 1;
131  econ.B.PAREN = chConfig->mode.parityCheck;
132 
133  return econ.U;
134 }
135 
136 
137 uint32 IfxQspi_calculatePrescaler(Ifx_QSPI *qspi, float baudrate)
138 {
139  float error, bestError;
140  float halfBaud = baudrate / 2;
141  float fQspiIn = IfxQspi_getModuleFrequency(qspi);
142  bestError = 10e6;
143  uint32 i, bestPre = 0;
144 
145  for (i = 0; i < 8; i++)
146  {
147  float tempHalfBaud = fQspiIn / (1U << (4 * i));
148  error = __absf(tempHalfBaud - halfBaud);
149 
150  if (__leqf(error, bestError))
151  {
152  bestError = error;
153  bestPre = i;
154  }
155  }
156 
157  return bestPre;
158 }
159 
160 
161 uint32 IfxQspi_calculateTimeQuantumLength(Ifx_QSPI *qspi, float maxBaudrate)
162 {
163  float divider = IfxScuCcu_getMaxFrequency() / (4.0 * maxBaudrate);
164  uint32 tq = __max((uint32)__roundf(divider) - 1, 0);
165  return tq;
166 }
167 
168 
169 void IfxQspi_read16(Ifx_QSPI *qspi, uint16 *data, Ifx_SizeT count)
170 {
171  volatile Ifx_QSPI_RXEXIT *rxFifo = &qspi->RXEXIT;
172 
173  while (count > 0)
174  {
175  *(data++) = (uint16)rxFifo->U;
176  count--;
177  }
178 }
179 
180 
181 void IfxQspi_read32(Ifx_QSPI *qspi, uint32 *data, Ifx_SizeT count)
182 {
183  volatile Ifx_QSPI_RXEXIT *rxFifo = &qspi->RXEXIT;
184 
185  while (count > 0)
186  {
187  *(data++) = rxFifo->U;
188  count--;
189  }
190 }
191 
192 
193 void IfxQspi_read8(Ifx_QSPI *qspi, uint8 *data, Ifx_SizeT count)
194 {
195  volatile Ifx_QSPI_RXEXIT *rxFifo = &qspi->RXEXIT;
196 
197  while (count > 0)
198  {
199  *(data++) = (uint8)rxFifo->U;
200  count--;
201  }
202 }
203 
204 
205 uint32 IfxQspi_recalcBasicConfiguration(uint32 oldBACON, Ifx_SizeT numOfData, boolean shortData, boolean lastData)
206 {
207  Ifx_QSPI_BACON bacon;
208  bacon.U = oldBACON;
209 
210  if (shortData == FALSE)
211  {
212  bacon.B.DL = numOfData;
213  bacon.B.BYTE = 1;
214  }
215 
216  bacon.B.LAST = lastData;
217  return bacon.U;
218 }
219 
220 
221 void IfxQspi_resetModule(Ifx_QSPI *qspi)
222 {
225  qspi->KRST0.B.RST = 1; /* Only if both Kernel reset bits are set a reset is executed */
226  qspi->KRST1.B.RST = 1;
227  IfxScuWdt_setCpuEndinit(passwd);
228 
229  while (0 == qspi->KRST0.B.RSTSTAT) /* Wait until reset is executed */
230 
231  {}
232 
234  qspi->KRSTCLR.B.CLR = 1; /* Clear Kernel reset status bit */
235  IfxScuWdt_setCpuEndinit(passwd);
236 }
237 
238 
239 void IfxQspi_setSlaveSelectOutputControl(Ifx_QSPI *qspi, IfxQspi_ChannelId channelId, boolean outputEnable, boolean activeLevel)
240 {
241  uint16 mask = 1 << channelId;
242 
243  Ifx_QSPI_SSOC ssoc;
244  ssoc.U = qspi->SSOC.U;
245 
246  if (outputEnable)
247  {
248  ssoc.B.OEN |= mask;
249  }
250  else
251  {
252  ssoc.B.OEN &= ~mask;
253  }
254 
255  if (activeLevel)
256  {
257  ssoc.B.AOL |= mask;
258  }
259  else
260  {
261  ssoc.B.AOL &= ~mask;
262  }
263 
264  qspi->SSOC.U = ssoc.U;
265 }
266 
267 
268 void IfxQspi_write16(Ifx_QSPI *qspi, IfxQspi_ChannelId channelId, uint16 *data, Ifx_SizeT count)
269 {
270  int cs = channelId % 8;
271  volatile Ifx_QSPI_DATAENTRY *dataEntry = &qspi->DATAENTRY[cs];
272 
273  while (count > 0)
274  {
275  dataEntry->U = *(data++);
276  count--;
277  }
278 }
279 
280 
281 void IfxQspi_write32(Ifx_QSPI *qspi, IfxQspi_ChannelId channelId, uint32 *data, Ifx_SizeT count)
282 {
283  int cs = channelId % 8;
284  volatile Ifx_QSPI_DATAENTRY *dataEntry = &qspi->DATAENTRY[cs];
285 
286  while (count > 0)
287  {
288  dataEntry->U = *(data++);
289  count--;
290  }
291 }
292 
293 
294 void IfxQspi_write8(Ifx_QSPI *qspi, IfxQspi_ChannelId channelId, uint8 *data, Ifx_SizeT count)
295 {
296  int cs = channelId % 8;
297  volatile Ifx_QSPI_DATAENTRY *dataEntry = &qspi->DATAENTRY[cs];
298 
299  while (count > 0)
300  {
301  dataEntry->U = *(data++);
302  count--;
303  }
304 }