iLLD_TC27xD  1.0
IfxAsclin_Spi.c
Go to the documentation of this file.
1 /**
2  * \file IfxAsclin_Spi.c
3  * \brief ASCLIN SPI details
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 "IfxAsclin_Spi.h"
30 
31 /******************************************************************************/
32 /*-----------------------Private Function Prototypes--------------------------*/
33 /******************************************************************************/
34 
35 /**
36  * \param asclin module handle
37  * \return status of the on going job
38  */
39 static IfxAsclin_Spi_Status IfxAsclin_Spi_lock(IfxAsclin_Spi *asclin);
40 
41 /**
42  * \param asclin module handle
43  * \return None
44  */
45 static void IfxAsclin_Spi_unlock(IfxAsclin_Spi *asclin);
46 
47 /******************************************************************************/
48 /*-------------------------Function Implementations---------------------------*/
49 /******************************************************************************/
50 
52 {
53  Ifx_ASCLIN *asclinSFR = asclin->asclin; /* getting the pointer to ASCLIN registers from module handler */
55  IfxScuWdt_clearCpuEndinit(psw); /* clearing the endinit protection*/
56  IfxAsclin_setDisableModuleRequest(asclinSFR); /* disabling the module */
57  IfxScuWdt_setCpuEndinit(psw); /* setting the endinit protection back on */
58 }
59 
60 
61 IfxAsclin_Spi_Status IfxAsclin_Spi_exchange(IfxAsclin_Spi *asclin, void *src, void *dest, uint32 count)
62 {
63  IfxAsclin_Spi_Status status = IfxAsclin_Spi_lock(asclin); /* lock the driver until the communication is done */
64 
65  if (status == IfxAsclin_Spi_Status_ok)
66  {
67  asclin->transferInProgress = 1; /* setting transfer in progress status */
68  asclin->txJob.data = src; /* data to be transmitted */
69  asclin->txJob.pending = count; /* count of Tx data */
70  asclin->rxJob.data = dest; /* empty buffer to receive data */
71  asclin->rxJob.pending = count; /* count of Rx data */
72 
73  IfxAsclin_Spi_write(asclin); /* write data into Tx fifo */
74  }
75 
76  return status;
77 }
78 
79 
81 {
83 
84  if ((asclin->transferInProgress != 0) || (asclin->sending != 0))
85  {
87  }
88 
89  return status;
90 }
91 
92 
94 {
95  Ifx_ASCLIN *asclinSFR = config->asclin; /* pointer to ASCLIN registers */
97 
98  asclin->asclin = asclinSFR; /* adding register pointer to module handler*/
99  IfxAsclin_enableModule(asclinSFR); /* enabling the module */
100 
101  /* mode initialisation */
102  IfxAsclin_setClockSource(asclinSFR, IfxAsclin_ClockSource_noClock); /* disabling the clock */
103  IfxAsclin_setFrameMode(asclinSFR, IfxAsclin_FrameMode_initialise); /* setting the module in Initialise mode */
104  IfxAsclin_setClockSource(asclinSFR, config->clockSource); /* setting the clock source */
105 
106  /* spi mode initialisation */
107  IfxAsclin_setClockSource(asclinSFR, IfxAsclin_ClockSource_noClock); /* disabling the clock */
108  IfxAsclin_setFrameMode(asclinSFR, config->frameMode); /* setting the module in Spi mode */
109  IfxAsclin_setPrescaler(asclinSFR, config->baudrate.prescaler); /* setting the prescaler*/
110  IfxAsclin_setClockSource(asclinSFR, config->clockSource); /* setting the clock source */
111 
112  IfxAsclin_SamplePointPosition samplePointPosition = (config->baudrate.oversampling + 1) / 2; /* sample point position at half of oversampling factor */
113 
114  /* baudrate generation */
115  status = (IfxAsclin_Status)IfxAsclin_setBitTiming(asclinSFR, config->baudrate.baudrate,
116  config->baudrate.oversampling,
117  samplePointPosition,
118  config->bitSampling.medianFilter); /* setting the baudrate bit fields to generate the required baudrate */
119 
120  IfxAsclin_setClockSource(asclinSFR, IfxAsclin_ClockSource_noClock); /* disabling the clock again */
121 
122  /* input output control initialisation */
123  IfxAsclin_setRxInput(asclinSFR, config->inputOutput.alti); /* selecting the Rx(alternate) input pin */
124  IfxAsclin_setClockPolarity(asclinSFR, config->inputOutput.cpol); /* setting the clock polarity */
125  IfxAsclin_setSlavePolarity(asclinSFR, config->inputOutput.spol); /* setting the slave polarity */
126  IfxAsclin_enableLoopBackMode(asclinSFR, config->inputOutput.loopBack); /* selecting loopbak (enable/disable) */
127 
128  /* frame control initialisation */
129  IfxAsclin_setIdleDelay(asclinSFR, config->frame.idleDelay); /* setting idle delay */
130  IfxAsclin_setLeadDelay(asclinSFR, config->frame.leadDelay); /* setting lead delay */
131  IfxAsclin_setStopBit(asclinSFR, config->frame.stopBit); /* setting the stop bit (trail delay) */
132  IfxAsclin_setShiftDirection(asclinSFR, config->frame.shiftDir); /* setting the shift direction */
133 
134  /* data control initialisation */
135  IfxAsclin_setDataLength(asclinSFR, config->dataLength); /* setting the number of bytes to be transfered */
136 
137  /* fifo control initialisation */
138  /* set the FIFO widths based on the supplied datalength */
139  if (config->dataLength <= 8)
140  {
141  IfxAsclin_setTxFifoInletWidth(asclinSFR, IfxAsclin_TxFifoInletWidth_1); /* setting Tx FIFO inlet width to 1 byte */
142  IfxAsclin_setRxFifoOutletWidth(asclinSFR, IfxAsclin_RxFifoOutletWidth_1); /* setting Rx FIFO outlet width to 1 byte */
143  asclin->dataWidth = 1; /* echo the data width to module handle*/
144  }
145 
146  else
147  {
148  IfxAsclin_setTxFifoInletWidth(asclinSFR, IfxAsclin_TxFifoInletWidth_2); /* setting Tx FIFO inlet width to 2 bytes */
149  IfxAsclin_setRxFifoOutletWidth(asclinSFR, IfxAsclin_RxFifoOutletWidth_2); /* setting Rx FIFO outlet width to 2 bytes */
150  asclin->dataWidth = 2; /* echo the data width to module handle*/
151  }
152 
153  IfxAsclin_setRxBufferMode(asclinSFR, config->fifo.buffMode); /* setting Rx FIFO mode */
154  IfxAsclin_setTxFifoInterruptLevel(asclinSFR, config->fifo.txFifoInterruptLevel); /* setting Tx FIFO level at which a Tx interrupt will be triggered */
155  IfxAsclin_setRxFifoInterruptLevel(asclinSFR, config->fifo.rxFifoInterruptLevel); /* setting Rx FIFO interrupt level at which a Rx interrupt will be triggered */
156  IfxAsclin_flushRxFifo(asclinSFR); /* flushing Rx FIFO */
157  IfxAsclin_flushTxFifo(asclinSFR); /* flushing Tx FIFO */
158 
159  IfxAsclin_disableAllFlags(asclinSFR); /* disable all flags */
160  IfxAsclin_clearAllFlags(asclinSFR); /* clear all flags */
161 
162  /* initialising the interrupts */
163  if (config->interrupt.rxPriority > 0)
164  {
165  volatile Ifx_SRC_SRCR *src;
166  src = IfxAsclin_getSrcPointerRx(asclinSFR);
167  IfxSrc_init(src, config->interrupt.typeOfService, config->interrupt.rxPriority);
169  IfxSrc_enable(src);
170  }
171 
172  if (config->interrupt.txPriority > 0)
173  {
174  volatile Ifx_SRC_SRCR *src;
175  src = IfxAsclin_getSrcPointerTx(asclinSFR);
176  IfxSrc_init(src, config->interrupt.typeOfService, config->interrupt.txPriority);
178  IfxSrc_enable(src);
179  }
180 
181  if (config->interrupt.erPriority > 0)
182  {
183  volatile Ifx_SRC_SRCR *src;
184  src = IfxAsclin_getSrcPointerEr(asclinSFR);
185  IfxSrc_init(src, config->interrupt.typeOfService, config->interrupt.erPriority);
187  IfxSrc_enable(src);
188  }
189 
190  /* Pin mapping */
191  const IfxAsclin_Spi_Pins *pins = config->pins;
192 
193  if (pins != NULL_PTR)
194  {
195  IfxAsclin_Sclk_Out *sclk = pins->sclk;
196 
197  if (sclk != NULL_PTR)
198  {
199  IfxAsclin_initSclkPin(sclk, pins->sclkMode, pins->pinDriver);
200  }
201 
202  IfxAsclin_Rx_In *rx = pins->rx;
203 
204  if (rx != NULL_PTR)
205  {
206  IfxAsclin_initRxPin(rx, pins->rxMode);
207  }
208 
209  IfxAsclin_Tx_Out *tx = pins->tx;
210 
211  if (tx != NULL_PTR)
212  {
213  IfxAsclin_initTxPin(tx, pins->txMode, pins->pinDriver);
214  }
215 
216  IfxAsclin_Slso_Out *slso = pins->slso;
217 
218  if (slso != NULL_PTR)
219  {
220  IfxAsclin_initSlsoPin(slso, pins->slsoMode, pins->pinDriver);
221  }
222  }
223 
224  IfxAsclin_enableParity(asclinSFR, FALSE); /* no parity */
225 
226  IfxAsclin_setClockSource(asclinSFR, config->clockSource); /* setting the clock source*/
227 
228  asclin->sending = 0;
229  IfxAsclin_enableTxFifoOutlet(asclinSFR, TRUE); /* disabling Rx FIFO for recieving */
230  IfxAsclin_enableRxFifoInlet(asclinSFR, TRUE); /* disabling Tx FIFO for transmitting */
231 
232  return status;
233 }
234 
235 
236 void IfxAsclin_Spi_initModuleConfig(IfxAsclin_Spi_Config *config, Ifx_ASCLIN *asclin)
237 {
238  const IfxAsclin_Spi_Config defaultConfig = {
239  .asclin = NULL_PTR, /* will be initialized below */
240 
241  .frameMode = IfxAsclin_FrameMode_spi, /* SPI mode */
242  .clockSource = IfxAsclin_ClockSource_kernelClock, /* kernel clock, fclc*/
243 
244  /* Default values for input output control */
245  .inputOutput = {
246  .alti = IfxAsclin_RxInputSelect_0, /* alternate input 0; */
247  .cpol = IfxAsclin_ClockPolarity_idleLow, /* CPOL active low */
248  .spol = IfxAsclin_SlavePolarity_idlehigh, /* SPOL active high */
249  .loopBack = FALSE, /* no loop back */
250  },
251 
252  /* Default values for baudrate */
253  .baudrate = {
254  .baudrate = 100000.0, /* default baudrate (the fractional dividier setup will be calculated in initModule) */
255  .prescaler = 2, /* default prescaler */
256  .oversampling = IfxAsclin_OversamplingFactor_8, /* default oversampling factor */
257  },
258 
259  /* Default Values for Bit sampling */
260  .bitSampling = {
261  .medianFilter = IfxAsclin_SamplesPerBit_one, /* one sample per bit */
262  },
263 
264  /* Default Values for Frame Control */
265  .frame = {
266  .idleDelay = IfxAsclin_IdleDelay_0, /* no idle delay */
267  .leadDelay = IfxAsclin_LeadDelay_1, /* one lead bit */
268  .stopBit = IfxAsclin_StopBit_1, /* one stop bit (trail delay) */
269  .shiftDir = IfxAsclin_ShiftDirection_lsbFirst, /* shift direction LSB first */
270  },
271 
272  /* Default Values for Data Control*/
273  .dataLength = IfxAsclin_DataLength_8, /* number of bits per transfer 8*/
274 
275  /* Default Values for fifo Control */
276  .fifo = {
277  .outWidth = IfxAsclin_RxFifoOutletWidth_1, /* 8-bit wide read */
278  .inWidth = IfxAsclin_TxFifoInletWidth_1, /*8-bit wide write */
279  .buffMode = IfxAsclin_ReceiveBufferMode_rxFifo, /* RxFIFO */
280  .txFifoInterruptLevel = IfxAsclin_TxFifoInterruptLevel_15, /* Tx FIFO interrupt level */
281  .rxFifoInterruptLevel = IfxAsclin_RxFifoInterruptLevel_1, /* Rx FIFO interrupt level */
282  },
283 
284  /* Default Values for Interrupt Config */
285  .interrupt = {
286  .rxPriority = 0, /* receive interrupt priority 0 */
287  .txPriority = 0, /* transmit interrupt priority 0 */
288  .erPriority = 0, /* error interrupt priority 0 */
289  .typeOfService = IfxSrc_Tos_cpu0, /* type of service CPU0 */
290  },
291 
292  .pins = NULL_PTR, /* pins to null pointer */
293  };
294 
295  /* Default Configuration */
296  *config = defaultConfig;
297  /* take over module pointer */
298  config->asclin = asclin;
299 }
300 
301 
303 {
304  Ifx_ASCLIN *asclinSFR = asclin->asclin; /* getting the pointer to ASCLIN registers from module handler */
305 
306  /* store all the flags in the variable */
307  if (IfxAsclin_getFrameErrorFlagStatus(asclinSFR))
308  {
310  asclin->errorFlags.frameError = 1;
311  }
312 
314  {
316  asclin->errorFlags.rxFifoOverflow = 1;
317  }
318 
320  {
322  asclin->errorFlags.rxFifoUnderflow = 1;
323  }
324 
326  {
328  asclin->errorFlags.txFifoOverflow = 1;
329  }
330 }
331 
332 
334 {
335  Ifx_ASCLIN *asclinSFR = asclin->asclin; /* getting the pointer to ASCLIN registers from module handler*/
336  IfxAsclin_clearRxFifoFillLevelFlag(asclinSFR); /* clear the interrupt flag */
337  IfxAsclin_Spi_read(asclin); /* read the remaining data */
338 }
339 
340 
342 {
343  Ifx_ASCLIN *asclinSFR = asclin->asclin; /* getting the pointer to ASCLIN registers from module handler */
344  IfxAsclin_clearTxFifoFillLevelFlag(asclinSFR); /* clear the interrupt flag */
345  IfxAsclin_Spi_write(asclin); /* write the remaining data */
346 }
347 
348 
349 static IfxAsclin_Spi_Status IfxAsclin_Spi_lock(IfxAsclin_Spi *asclin)
350 {
351  sint32 sending = __swap((void *)&asclin->sending, 1UL);
352  return (sending == 0) ? IfxAsclin_Spi_Status_ok : IfxAsclin_Spi_Status_busy;
353 }
354 
355 
357 {
358  Ifx_ASCLIN *asclinSFR = asclin->asclin; /* getting the pointer to ASCLIN registers from module handler */
359  IfxAsclin_Spi_Job *job = &asclin->rxJob; /* getting the rxJob structure from module handler */
360 
361  uint32 count = (uint32)IfxAsclin_getRxFifoFillLevel(asclinSFR); /* get the readable count of Rx fifo */
362  count = __min(job->pending, count); /* check for the end of the data */
363 
364  if (job->data == NULL_PTR) /* incase of no data to be received (only transmit case) */
365  {
366  int i;
367  job->pending = job->pending - count; /* discount the current reading count from job pending */
368 
369  for (i = 0; i < count; i++)
370  {
371  IfxAsclin_readRxData(asclinSFR); /* do dummy reads */
372  }
373  }
374  else if (job->pending > 0)
375  {
376  job->pending = job->pending - count; /* discount the current reading count from job pending */
377 
378  /* read data up to the count based on the out width */
379  switch (asclin->dataWidth)
380  {
381  case 1: /* in case of 8 bit wide */
382  IfxAsclin_read8(asclinSFR, job->data, count); /* reading from Rx FIFO */
383  job->data = &(((uint8 *)job->data)[count]); /* pointing to the remaining data */
384  break;
385 
386  case 2: /* in case of 16 bit wide*/
387  IfxAsclin_read16(asclinSFR, job->data, count); /* reading from Rx FIFO */
388  job->data = &(((uint16 *)job->data)[count]); /* pointing to the remaining data */
389  break;
390  }
391  }
392 
393  if (job->pending == 0)
394  {
395  asclin->transferInProgress = 0; /* clearing the transfer in progress status */
396  IfxAsclin_Spi_unlock(asclin); /* unlock the driver */
397  }
398 }
399 
400 
401 static void IfxAsclin_Spi_unlock(IfxAsclin_Spi *asclin)
402 {
403  asclin->sending = 0UL;
404 }
405 
406 
408 {
409  Ifx_ASCLIN *asclinSFR = asclin->asclin; /* getting the pointer to ASCLIN registers from module handler */
410  IfxAsclin_Spi_Job *job = &asclin->txJob; /* getting the txJob structure from module handler */
411 
412  if (job->pending)
413  {
414  /* following operation must be atomic (FIXME actually, we would only have to stall the Tx interrupt) */
415  boolean interruptState = IfxCpu_disableInterrupts();
416 
417  uint32 count = (uint32)(16 - IfxAsclin_getTxFifoFillLevel(asclinSFR)); /* getting the fillable count of the Tx Fifo */
418  count = __min(job->pending, count); /* checking for the end of the data */
419 
420  if (job->data == NULL_PTR) /* incase of no data to be transmitted (only receive case) */
421  {
422  int i;
423  job->pending = job->pending - count; /* discount the current filling count from job pending */
424 
425  for (i = 0; i < count; i++)
426  {
427  IfxAsclin_writeTxData(asclinSFR, ~0); /* write all 1's */
428  }
429  }
430  else
431  {
432  job->pending = job->pending - count; /* discount the current filling count from job pending */
433 
434  /* write data up to the count based on the in width */
435  switch (asclin->dataWidth)
436  {
437  case 1: /* in case of 8 bit wide */
438  IfxAsclin_write8(asclinSFR, job->data, count); /* writing to Tx FIFO */
439  job->data = &(((uint8 *)job->data)[count]); /* pointing to the remaining data */
440  break;
441 
442  case 2: /* in case of 16 bit wide*/
443  IfxAsclin_write16(asclinSFR, job->data, count); /* writing to Tx FIFO */
444  job->data = &(((uint16 *)job->data)[count]); /* pointing to the remaining data */
445  break;
446  }
447  }
448 
449  IfxCpu_restoreInterrupts(interruptState);
450  }
451 }