iLLD_TC27xC  1.0
IfxI2c_I2c.c
Go to the documentation of this file.
1 /**
2  * \file IfxI2c_I2c.c
3  * \brief I2C I2C details
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 "IfxI2c_I2c.h"
30 
31 /******************************************************************************/
32 /*-------------------------Function Implementations---------------------------*/
33 /******************************************************************************/
34 
35 void IfxI2c_I2c_initConfig(IfxI2c_I2c_Config *config, Ifx_I2C *i2c)
36 {
37  config->i2c = i2c;
38  config->baudrate = 400000;
39  config->pins = NULL_PTR;
40 }
41 
42 
43 void IfxI2c_I2c_initDevice(const IfxI2c_I2c_deviceConfig *i2cDeviceConfig, IfxI2c_I2c_Device *i2cDevice)
44 {
45  i2cDevice->i2c = i2cDeviceConfig->i2c;
46  i2cDevice->deviceAddress = i2cDeviceConfig->deviceAddress;
47 }
48 
49 
51 {
52  i2cDeviceConfig->i2c = i2c;
53  i2cDeviceConfig->deviceAddress = 0xff;
54 }
55 
56 
58 {
59  Ifx_I2C *i2cSFR = config->i2c;
60  i2c->i2c = i2cSFR;
61 
62  IfxI2c_enableModule(i2cSFR);
63  IfxI2c_stop(i2cSFR); // enter config Mode
65  IfxI2c_setBaudrate(i2cSFR, config->baudrate);
66  IfxI2c_initSclSdaPin(config->pins->scl, config->pins->sda, config->pins->padDriver);
67  IfxI2c_run(i2cSFR);
68  i2c->baudrate = IfxI2c_getBaudrate(i2cSFR);
69  i2c->busStatus = IfxI2c_getBusStatus(i2cSFR);
71 }
72 
73 
75 {
77  Ifx_I2C *i2c = i2cDevice->i2c->i2c;
78  uint32 packet;
79  uint8 slAddr = i2cDevice->deviceAddress;
80 
81  uint32 rxData = 0;
82  sint32 bytesToReceive = size;
83  uint8 *bytePtrRxData = (uint8 *)&rxData;
84  uint32 bytes;
85 
86  // bus free?
87  if (IfxI2c_busIsFree(i2c) == FALSE)
88  {
90  i2cDevice->i2c->busStatus = IfxI2c_getBusStatus(i2c);
91  i2cDevice->i2c->status = status;
92  return status;
93  }
94 
97 
98  // send device address with RnW bit set
99  packet = slAddr | 1; // set read bit
100  IfxI2c_setReceivePacketSize(i2c, size); // set number of bytes to reveive
101  IfxI2c_setTransmitPacketSize(i2c, 1); // send slave address packet with RnW = 1
102  IfxI2c_writeFifo(i2c, packet);
104 
105  // wait until aribtration lost, nack, or rx mode flag is set, or error occurres
106  while ((i2c->PIRQSM.U & ((1 << IFX_I2C_PIRQSS_AL_OFF) | (1 << IFX_I2C_PIRQSS_NACK_OFF) | (1 << IFX_I2C_PIRQSS_RX_OFF) || i2c->ERRIRQSS.U)))
107  {}
108 
109  // check status
110  if (i2c->ERRIRQSS.U)
111  {
113  status = IfxI2c_I2c_Status_error;
114  }
115  else if (IfxI2c_arbitrationLostFlag(i2c) == TRUE)
116  {
118  status = IfxI2c_I2c_Status_al;
119  }
120  else if (IfxI2c_receivedNakFlag(i2c) == TRUE)
121  {
123  status = IfxI2c_I2c_Status_nak;
124  }
125  else if (size > 0) // required to poll for nak
126 
127  {
128  if (size > 32) // if fifo is too small => disable global interrupts!
129  { // assumes TC is faster than i2c and therefor a fifo overflow is not possible
130  boolean intEnabled = IfxCpu_disableInterrupts(); // disable global interrupts to prevent fifo overflow
131  uint32 i;
132 
133  for (i = 0; i < size; i += 4)
134  {
135  if (bytesToReceive >= 4)
136  {
137  bytes = 4;
138  bytesToReceive -= 4;
139  }
140  else
141  {
142  bytes = bytesToReceive;
143  bytesToReceive = 0;
144  }
145 
146  uint32 ris;
147 
148  while (!(ris = i2c->RIS.U)) // wait for fifo request or error
149 
150  {}
151 
152  // check request flags
153  if (ris & ((1 << IFX_I2C_RIS_LSREQ_INT_OFF) | (1 << IFX_I2C_RIS_SREQ_INT_OFF) | (1 << IFX_I2C_RIS_LBREQ_INT_OFF) | (1 << IFX_I2C_RIS_BREQ_INT_OFF)))
154  {
155  rxData = i2c->RXD.U;
156  uint32 k;
157 
158  for (k = 0; k < bytes; k++)
159  {
160  data[i + k] = bytePtrRxData[k];
161  }
162 
164  }
165 
166  // check errors
167  if (ris & (1 << IFX_I2C_RIS_I2C_P_INT_OFF)) // check protocol flags
168  {
170  status = IfxI2c_I2c_Status_error;
171  break;
172  }
173 
174  if (ris & (1 << IFX_I2C_RIS_I2C_ERR_INT_OFF)) // error flags
175  {
177  status = IfxI2c_I2c_Status_error;
178  break;
179  }
180  }
181 
182  IfxCpu_restoreInterrupts(intEnabled); // (re-) enable global interrupts
183 
184  // TX_END: transmission finished
185  while (IfxI2c_isTxEndInterrupt(i2c) == FALSE)
186  {}
187 
189  }
190  else
191  {
192  // wait until all bytes are received
193  while (IfxI2c_isTxEndInterrupt(i2c) == FALSE)
194  {}
195 
197 
198  // check errors
199  uint32 ris;
200  ris = i2c->RIS.U;
201 
202  if (ris & (1 << IFX_I2C_RIS_I2C_P_INT_OFF)) // check protocol flags
203  {
205  status = IfxI2c_I2c_Status_error;
206  }
207 
208  if (ris & (1 << IFX_I2C_RIS_I2C_ERR_INT_OFF)) // error flags
209  {
211  status = IfxI2c_I2c_Status_error;
212  }
213 
214  if (status != IfxI2c_I2c_Status_error)
215  {
216  // read fifo
217  uint32 i;
218 
219  for (i = 0; i < size; i += 4)
220  {
221  if (bytesToReceive >= 4)
222  {
223  bytes = 4;
224  bytesToReceive -= 4;
225  }
226  else
227  {
228  bytes = bytesToReceive;
229  bytesToReceive = 0;
230  }
231 
232  uint32 k;
233  rxData = i2c->RXD.U;
235 
236  for (k = 0; k < bytes; k++)
237  {
238  data[i + k] = bytePtrRxData[k];
239  }
240  }
241  }
242  }
243 
244  // finally check errors
245  uint32 ris;
246  ris = i2c->RIS.U;
247 
248  if (ris & (1 << IFX_I2C_RIS_I2C_P_INT_OFF)) // check protocol flags
249  {
251  status = IfxI2c_I2c_Status_error;
252  }
253 
254  if (ris & (1 << IFX_I2C_RIS_I2C_ERR_INT_OFF)) // error flags
255  {
257  status = IfxI2c_I2c_Status_error;
258  }
259  }
260 
261  IfxI2c_releaseBus(i2c);
262  i2cDevice->i2c->busStatus = IfxI2c_getBusStatus(i2c);
263  i2cDevice->i2c->status = status;
264  return status;
265 }
266 
267 
269 {
271  Ifx_I2C *i2c = i2cDevice->i2c->i2c;
272  uint8 slAddr = i2cDevice->deviceAddress;
273  uint32 packet;
274  sint32 bytesToSend = size + 1; // +1 slave device address
275  uint32 bytes;
276  uint8 *bytePtrPacket = (uint8 *)&packet;
277 
278  if (IfxI2c_busIsFree(i2c) == FALSE)
279  {
281  i2cDevice->i2c->busStatus = IfxI2c_getBusStatus(i2c);
282  i2cDevice->i2c->status = status;
283  return status;
284  }
285 
286  // build one packet containing the slave address
287  packet = slAddr;
288 
291 
292  // try to seize control, if not return
294  IfxI2c_writeFifo(i2c, packet);
296 
297  // wait until packet is sent
298  while (IfxI2c_isTxEndInterrupt(i2c) == FALSE)
299  {}
300 
302 
303  // check status
304  if (IfxI2c_arbitrationLostFlag(i2c) == TRUE)
305  {
307  status = IfxI2c_I2c_Status_al;
308  }
309  else if (IfxI2c_receivedNakFlag(i2c) == TRUE)
310  {
312  status = IfxI2c_I2c_Status_nak;
313  }
314  else if (size > 0) // write i2c device
315 
316  {
317  uint32 i, j = 0;
318 
319  // assumes TC is faster then i2c and therefor a fifo underflow is not possible
320  boolean intEnabled = IfxCpu_disableInterrupts(); // disable global interrupts to prevent FIFO underflow
321  IfxI2c_setTransmitPacketSize(i2c, size + 1);
322 
323  for (i = 0; i < size + 1; i += 4)
324  {
325  if (bytesToSend >= 4)
326  {
327  bytes = 4;
328  bytesToSend -= 4;
329  }
330  else
331  {
332  bytes = bytesToSend;
333  bytesToSend = 0;
334  }
335 
336  packet = 0;
337 
338  for (j = 0; j < bytes; j++)
339  {
340  if ((i == 0) && (j == 0))
341  {
342  bytePtrPacket[j] = slAddr;
343  }
344  else
345  {
346  bytePtrPacket[j] = data[i + j - 1];
347  }
348  }
349 
350  do
351  {
352  // check errors
353  uint32 ris;
354  ris = i2c->RIS.U;
355 
356  if (ris & (1 << IFX_I2C_RIS_I2C_P_INT_OFF)) // check protocol flags
357  {
359  status = IfxI2c_I2c_Status_error;
360  }
361 
362  if (ris & (1 << IFX_I2C_RIS_I2C_ERR_INT_OFF)) // error flags
363  {
365  status = IfxI2c_I2c_Status_error;
366  }
367  } while (i2c->FFSSTAT.B.FFS == 8 && status != IfxI2c_I2c_Status_error); // wait to prevent FIFO overflow
368 
369  if (status == IfxI2c_I2c_Status_error)
370  {
371  break;
372  }
373 
374  IfxI2c_writeFifo(i2c, packet);
376  }
377 
378  IfxCpu_restoreInterrupts(intEnabled); // (re-) enable global interrupts
379 
380  // wait until all bytes are sent
381  while (IfxI2c_isTxEndInterrupt(i2c) == FALSE)
382  {}
383 
385 
386  // finally check errors
387  uint32 ris;
388  ris = i2c->RIS.U;
389 
390  if (ris & (1 << IFX_I2C_RIS_I2C_P_INT_OFF)) // check protocol flags
391  {
393  status = IfxI2c_I2c_Status_error;
394  }
395 
396  if (ris & (1 << IFX_I2C_RIS_I2C_ERR_INT_OFF)) // error flags
397  {
399  status = IfxI2c_I2c_Status_error;
400  }
401  }
402 
403  IfxI2c_releaseBus(i2c);
404  i2cDevice->i2c->busStatus = IfxI2c_getBusStatus(i2c);
405  i2cDevice->i2c->status = status;
406  return status;
407 }