iLLD_TC27xD  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_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 "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(IfxI2c_I2c_Device *i2cDevice, const IfxI2c_I2c_deviceConfig *i2cDeviceConfig)
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_setTransmitPacketSize(i2c, 1); // send slave address packet with RnW = 1
101  IfxI2c_setReceivePacketSize(i2c, size); // set number of bytes to reveive
102  IfxI2c_writeFifo(i2c, packet);
107 
108  // wait until aribtration lost, nack, or rx mode flag is set, or error occurres
109  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)))
110  {}
111 
112  // check status
113  if (i2c->ERRIRQSS.U)
114  {
116  status = IfxI2c_I2c_Status_error;
117  }
119  {
121  status = IfxI2c_I2c_Status_al;
122  }
124  {
126  status = IfxI2c_I2c_Status_nak;
127  }
128  else if (size > 0) // required to poll for nak
129 
130  {
131  if (size > 32) // if fifo is too small => disable global interrupts!
132  { // assumes TC is faster than i2c and therefor a fifo overflow is not possible
133  boolean intEnabled = IfxCpu_disableInterrupts(); // disable global interrupts to prevent fifo overflow
134  uint32 i;
135 
136  for (i = 0; i < size; i += 4)
137  {
138  if (bytesToReceive >= 4)
139  {
140  bytes = 4;
141  bytesToReceive -= 4;
142  }
143  else
144  {
145  bytes = bytesToReceive;
146  bytesToReceive = 0;
147  }
148 
149  uint32 ris;
150 
151  while (!(ris = i2c->RIS.U)) // wait for fifo request or error
152 
153  {}
154 
155  // check request flags
156  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)))
157  {
158  rxData = i2c->RXD.U;
159  uint32 k;
160 
161  for (k = 0; k < bytes; k++)
162  {
163  data[i + k] = bytePtrRxData[k];
164  }
165 
170  }
171 
172  // check errors
173  if (ris & (1 << IFX_I2C_RIS_I2C_P_INT_OFF)) // check protocol flags
174  {
176  status = IfxI2c_I2c_Status_error;
177  break;
178  }
179 
180  if (ris & (1 << IFX_I2C_RIS_I2C_ERR_INT_OFF)) // error flags
181  {
183  status = IfxI2c_I2c_Status_error;
184  break;
185  }
186  }
187 
188  IfxCpu_restoreInterrupts(intEnabled); // (re-) enable global interrupts
189 
190  // TX_END: transmission finished
192  {}
193 
195  }
196  else
197  {
198  // wait until all bytes are received
200  {}
201 
203 
204  // check errors
205  uint32 ris;
206  ris = i2c->RIS.U;
207 
208  if (ris & (1 << IFX_I2C_RIS_I2C_P_INT_OFF)) // check protocol flags
209  {
211  status = IfxI2c_I2c_Status_error;
212  }
213 
214  if (ris & (1 << IFX_I2C_RIS_I2C_ERR_INT_OFF)) // error flags
215  {
217  status = IfxI2c_I2c_Status_error;
218  }
219 
220  if (status != IfxI2c_I2c_Status_error)
221  {
222  // read fifo
223  uint32 i;
224 
225  for (i = 0; i < size; i += 4)
226  {
227  if (bytesToReceive >= 4)
228  {
229  bytes = 4;
230  bytesToReceive -= 4;
231  }
232  else
233  {
234  bytes = bytesToReceive;
235  bytesToReceive = 0;
236  }
237 
238  uint32 k;
239  rxData = i2c->RXD.U;
244 
245  for (k = 0; k < bytes; k++)
246  {
247  data[i + k] = bytePtrRxData[k];
248  }
249  }
250  }
251  }
252 
253  // finally check errors
254  uint32 ris;
255  ris = i2c->RIS.U;
256 
257  if (ris & (1 << IFX_I2C_RIS_I2C_P_INT_OFF)) // check protocol flags
258  {
260  status = IfxI2c_I2c_Status_error;
261  }
262 
263  if (ris & (1 << IFX_I2C_RIS_I2C_ERR_INT_OFF)) // error flags
264  {
266  status = IfxI2c_I2c_Status_error;
267  }
268  }
269 
270  IfxI2c_releaseBus(i2c);
271  i2cDevice->i2c->busStatus = IfxI2c_getBusStatus(i2c);
272  i2cDevice->i2c->status = status;
273  return status;
274 }
275 
276 
278 {
280  Ifx_I2C *i2c = i2cDevice->i2c->i2c;
281  uint8 slAddr = i2cDevice->deviceAddress;
282  uint32 packet;
283  sint32 bytesToSend = size + 1; // +1 slave device address
284  uint32 bytes;
285  uint8 *bytePtrPacket = (uint8 *)&packet;
286 
287  if (IfxI2c_busIsFree(i2c) == FALSE)
288  {
290  i2cDevice->i2c->busStatus = IfxI2c_getBusStatus(i2c);
291  i2cDevice->i2c->status = status;
292  return status;
293  }
294 
295  // build one packet containing the slave address
296 
299 
300  // try to seize control, if not return
301  packet = slAddr;
302  // try to seize control, if not return
304  IfxI2c_writeFifo(i2c, packet);
309 
310  // wait until packet is sent
312  {}
313 
315 
316  // check status
318  {
320  status = IfxI2c_I2c_Status_al;
321  }
323  {
325  status = IfxI2c_I2c_Status_nak;
326  }
327  else if (size > 0) // write i2c device
328 
329  {
330  uint32 i, j = 0;
331 
332  // assumes TC is faster then i2c and therefor a fifo underflow is not possible
333  boolean intEnabled = IfxCpu_disableInterrupts(); // disable global interrupts to prevent FIFO underflow
334  IfxI2c_setTransmitPacketSize(i2c, size + 1);
335 
336  for (i = 0; i < size + 1; i += 4)
337  {
338  if (bytesToSend >= 4)
339  {
340  bytes = 4;
341  bytesToSend -= 4;
342  }
343  else
344  {
345  bytes = bytesToSend;
346  bytesToSend = 0;
347  }
348 
349  packet = 0;
350 
351  for (j = 0; j < bytes; j++)
352  {
353  if ((i == 0) && (j == 0))
354  {
355  bytePtrPacket[j] = (uint8)slAddr;
356  }
357 
358  else
359  {
360  bytePtrPacket[j] = (uint8)data[i + j - 1];
361  }
362  }
363 
364  do
365  {
366  // check errors
367  uint32 ris;
368  ris = i2c->RIS.U;
369 
370  if (ris & (1 << IFX_I2C_RIS_I2C_P_INT_OFF)) // check protocol flags
371  {
373  status = IfxI2c_I2c_Status_error;
374  }
375 
376  if (ris & (1 << IFX_I2C_RIS_I2C_ERR_INT_OFF)) // error flags
377  {
379  status = IfxI2c_I2c_Status_error;
380  }
381  } while (i2c->FFSSTAT.B.FFS == 8 && status != IfxI2c_I2c_Status_error); // wait to prevent FIFO overflow
382 
383  if (status == IfxI2c_I2c_Status_error)
384  {
385  break;
386  }
387 
388  IfxI2c_writeFifo(i2c, packet);
393  }
394 
395  IfxCpu_restoreInterrupts(intEnabled); // (re-) enable global interrupts
396 
397  // wait until all bytes are sent
399  {}
400 
402 
403  // finally check errors
404  uint32 ris;
405  ris = i2c->RIS.U;
406 
407  if (ris & (1 << IFX_I2C_RIS_I2C_P_INT_OFF)) // check protocol flags
408  {
410  status = IfxI2c_I2c_Status_error;
411  }
412 
413  if (ris & (1 << IFX_I2C_RIS_I2C_ERR_INT_OFF)) // error flags
414  {
416  status = IfxI2c_I2c_Status_error;
417  }
418  }
419 
420  IfxI2c_releaseBus(i2c);
421  i2cDevice->i2c->busStatus = IfxI2c_getBusStatus(i2c);
422  i2cDevice->i2c->status = status;
423  return status;
424 }