KM3NeT CLB  2.0
KM3NeT CLB v2 Embedded Software
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
i2c.c
1 /*
2  * KM3NeT CLB v2 Firmware
3  * ----------------------
4  *
5  * Copyright 2013 KM3NeT Collaboration
6  *
7  * All Rights Reserved.
8  *
9  *
10  * File : i2c.c
11  * Created : 8 mrt. 2013
12  * Author : Vincent van Beveren
13  */
14 
15 #include <stdio.h>
16 
17 #include "drv/wb/i2c.h"
18 #include "kernel/tm.h"
19 #include "kernel/err.h"
20 
21 
22 #define I2C_TIMEOUT 100
23 
24 
25 static bool _dbg = false;
26 
27 static inline bool i2cWait(I2C_Device * dev)
28 {
29 // printf("I2C wait: status = %02x\n", dev->CMDSTS);
30  uint32_t to = timeOutInit(I2C_TIMEOUT);
31  while (dev->CMDSTS & I2C_STS_TIP)
32  {
33  if (dev->CMDSTS & I2C_STS_ARBLOST) {
35  return false;
36  }
37  if (timeOut(to))
38  {
40  return false;
41  }
42  }
43 
44  return true;
45 
46 }
47 
48 
49 static inline bool i2cOut(I2C_Device * dev, uint8_t data, uint8_t flags)
50 {
51  // printf("I2C out: %02x (flags=%02x, status=%02x)\n", data, flags | I2C_CMD_WR, dev->CMDSTS);
52  dev->TXRX = data;
53  dev->CMDSTS = flags | I2C_CMD_WR;
54 
55 
56 
57  if (!i2cWait(dev)) return false;
58 
59  // device may noAck on last byte out.
60  if ((dev->CMDSTS & I2C_STS_RXACK) && !(flags & I2C_CMD_STOP) )
61  {
62  // otherwise error!
64  return false;
65  }
66 
67  return true;
68 }
69 
70 static inline bool i2cIn(I2C_Device * dev, uint8_t * data, uint8_t flags)
71 {
72 // printf("I2C in: (flags=%02x, status=%02x...\n", flags | I2C_CMD_RD, dev->CMDSTS);
73  dev->CMDSTS = flags | I2C_CMD_RD;
74 
75  if (!i2cWait(dev)) return false;
76 
77 
78  *data = dev->TXRX;
79  // if (_dbg) printf("I2C in: %02x\n", *data);
80  return true;
81 }
82 
83 
84 void i2cAbort(I2C_Device * dev)
85 {
86  int i;
87  for (i = 0; i < 2; i++) {
88  dev->TXRX = 0xFF;
90  uint32_t to = timeOutInit(10);
91  while (dev->CMDSTS & I2C_STS_TIP)
92  {
93  if (timeOut(to))
94  {
95  // reset core
96  dev->CTL = 0;
97  dev->CTL = I2C_CTL_CORE_ENA;
98  break;
99  }
100  }
101  }
102  timeDelay(10);
103 }
104 
105 /*
106  Converts the virtual I2C device to a real device address, and sets the interface number correct.
107  */
108 static inline I2C_Device * vir2Real(I2C_Device * dev_)
109 {
110  I2C_Device * dev = (I2C_Device *) ( ((uint32_t)dev_) & 0xFFFFFF00 );
111  int ifno = (((uint32_t)dev_) >> 4) & 0x0F;
112 
113  if ( ( dev->IF & I2C_IF_NO_MASK ) >> I2C_IF_NO_SHIFT == ifno) return dev;
114 
115  i2cWait(dev);
116 
117  dev->IF = (ifno << I2C_IF_NO_SHIFT) & I2C_IF_NO_MASK;
118 
119  return dev;
120 }
121 
122 bool i2cInit(I2C_Device * dev_, uint32_t bitrate)
123 {
124 
125  I2C_Device * dev = vir2Real(dev_);
126 
127 
128  dev->CTL = 0;
129 
130  // value is calculated by:
131  // = wb_clk/(5*100)-1 = 125Mhz/500Khz - 1 = 249dec = 0xF9
132 
133  uint32_t pres = ( WISHBONE_FREQ / ( 5 * bitrate ) ) - 1;
134 
135  dev->PRE_LO = pres & 0xff;
136  dev->PRE_HI = ( pres >> 8 ) & 0xff;
137 
138  dev->CTL = 0;
139  dev->CTL = I2C_CTL_CORE_ENA;
140  dev->CMDSTS = I2C_CMD_IACK;
141 
142 /* printf("i2C Configured: PreLo=%02lx PreHi=%02lx Ctrl=%02lx Sts=%02lx\n",
143  dev->PRE_LO, dev->PRE_HI, dev->CTL, dev->CMDSTS);*/
144 
145  if ( ( dev->CTL & I2C_CTL_CORE_ENA ) == 0)
146  {
148  return false;
149  }
150 
151  // it always says arb lost in the beginning.
152 /* if (dev->CMDSTS & I2C_STS_ARBLOST) {
153  return I2C_ERR_ARBLOST;
154  }*/
155  i2cAbort(dev);
156  errClear();
157  return true;
158 }
159 
160 
161 bool i2cRead(I2C_Device * dev_, i2cAddr addr, uint8_t * byte, int len)
162 {
163  int i;
164 
165  I2C_Device * dev = vir2Real(dev_);
166 
167 
168  if (_dbg) printf("I2C %02x (Rd)", addr);
169  // shift address, and with 1 -> start read.
170  if (!i2cOut(dev, ( addr << 1 ) | 1, I2C_CMD_START)) goto exit_f;
171 
172  for (i = 0; i < len; ++i)
173  {
174  if (!i2cIn(dev, byte, i == ( len - 1 ) ? I2C_CMD_STOP | I2C_CMD_ACK : 0)) goto exit_f;
175  if (_dbg) printf(" %02x", *byte);
176  byte++;
177  }
178  if (_dbg) puts("");
179 
180  return true;
181 exit_f:
182  i2cAbort(dev);
183  if (_dbg) puts(" (err!)");
184  return false;
185 }
186 
187 
188 bool i2cReadReg(I2C_Device * dev_, i2cAddr addr, uint8_t reg, uint8_t * byte, int len)
189 {
190  int i;
191 
192  I2C_Device * dev = vir2Real(dev_);
193 
194  if (_dbg) printf("I2C %02x (RdReg=%02x)", addr, reg);
195 
196  // shift address, and with 1 -> start wrie.
197  if (!i2cOut(dev, ( addr << 1 ) | 0, I2C_CMD_START)) goto exit_f;
198  // write register value, command ack
199  if (!i2cOut(dev, reg, I2C_CMD_ACK | I2C_CMD_STOP)) goto exit_f;
200 
201  // shift address, and with 1 -> start read. (repeated start)
202  if (!i2cOut(dev, ( addr << 1 ) | 1, I2C_CMD_START)) goto exit_f;
203 
204  for (i = 0; i < len; ++i)
205  {
206  if (!i2cIn(dev, byte, i == ( len - 1 ) ? I2C_CMD_STOP | I2C_CMD_ACK : 0)) goto exit_f;
207  if (_dbg) printf(" %02x", *byte);
208  byte++;
209  }
210  if (_dbg) puts("");
211  return true;
212 exit_f:
213  i2cAbort(dev);
214  if (_dbg) puts(" (err!)");
215  return false;
216 }
217 
218 
219 bool i2cWrite(I2C_Device * dev_, i2cAddr addr, uint8_t * byte, int len)
220 {
221  int i;
222 
223  I2C_Device * dev = vir2Real(dev_);
224  if (_dbg) printf("I2C %02x (Wr)", addr);
225 
226  // shift address, and with 0 -> start write
227  if (!i2cOut(dev, ( addr << 1 ) | 0, I2C_CMD_START)) goto exit_f;
228 
229  for (i = 0; i < len; ++i)
230  {
231  if (_dbg) printf(" %02x", *byte);
232 
233  if (!i2cOut(dev, *byte, i == ( len - 1 ) ? I2C_CMD_STOP : 0)) goto exit_f;
234  byte++;
235  }
236  if (_dbg) puts("");
237 
238  return true;
239 exit_f:
240  i2cAbort(dev);
241  if (_dbg) puts(" (err!)");
242 
243  return false;
244 }
245 
246 
247 bool i2cWriteReg(I2C_Device * dev_, i2cAddr addr, uint8_t reg, uint8_t * byte, int len)
248 {
249  int i;
250 
251 
252  if (_dbg) printf("I2C %02x (WrReg=%02x)", addr, reg);
253  I2C_Device * dev = vir2Real(dev_);
254 
255  // shift address, and with 0 -> start write
256  if (!i2cOut(dev, ( addr << 1 ) | 0, I2C_CMD_START)) goto exit_f;
257 
258 
259  // write out register value
260  if (!i2cOut(dev, reg, 0)) goto exit_f;
261 
262  for (i = 0; i < len; ++i)
263  {
264  if (_dbg) printf(" %02x", *byte);
265 
266  if (!i2cOut(dev, *byte, i == ( len - 1 ) ? I2C_CMD_STOP : 0)) goto exit_f;
267  byte++;
268  }
269 
270  if (_dbg) puts("");
271 
272  return true;
273 exit_f:
274  i2cAbort(dev);
275  if (_dbg) puts(" (err!)");
276  return false;
277 }
278 
279 
280 bool i2cWriteRead(I2C_Device * dev, i2cAddr addr, uint8_t * wr, int wrLen, uint8_t * rd, int rdLen)
281 {
282  if (!i2cWrite(dev, addr, wr, wrLen)) return false;
283  return i2cRead(dev, addr, rd, rdLen);
284 }
285 
286 
287 bool i2cSendCmdAlt(I2C_Device * dev_, i2cAddr addr, uint8_t * cmd, int cmd_len, uint8_t * answer, int answer_len)
288 {
289  int i;
290 
291  I2C_Device * dev = vir2Real(dev_);
292 
293 
294 
295  // shift address, and with 0 -> start write
296  if (!i2cOut(dev, ( addr << 1 ) | 0, I2C_CMD_START)) goto exit_f;
297 
298  // write the command
299  for (i = 0; i < cmd_len; ++i)
300  {
301  if (!i2cOut(dev, *cmd, 0)) goto exit_f;
302  cmd++;
303  }
304 
305  // receive the answer
306  for (i = 0; i < answer_len; ++i)
307  {
308  if (!i2cIn(dev, answer, i == ( answer_len - 1 ) ? I2C_CMD_STOP | I2C_CMD_ACK : 0)) goto exit_f;
309 
310  answer++;
311 
312  }
313  return true;
314 exit_f:
315  i2cAbort(dev);
316  return false;
317 }
318 
319 
320 static bool i2cCheckedStart(I2C_Device * dev, uint8_t rawAddr) {
321  bool ok = i2cOut(dev, rawAddr, I2C_CMD_START);
322  i2cAbort(dev);
323  return ok;
324 }
325 
326 bool i2cExists(I2C_Device * dev_, i2cAddr addr, bool * canRead, bool * canWrite)
327 {
328  I2C_Device * dev = vir2Real(dev_);
329 
330  // shift address, and with 1 -> start read
331 
332 
333  if (i2cCheckedStart(dev, (addr << 1) | 1)) {
334  *canRead = true;
335  } else {
336  if (errGet() != E_I2C_NO_ACK) {
337  return false;
338  }
339  *canRead = false;
340  errClear();
341  }
342 
343 
344  if (i2cCheckedStart(dev, (addr << 1))) {
345  *canWrite = true;
346  } else {
347  if (errGet() != E_I2C_NO_ACK) {
348  return false;
349  }
350  *canWrite = false;
351  errClear();
352  }
353  return true;
354 }
355 
356 bool i2cReadRegAlt(I2C_Device * dev_, i2cAddr addr, uint8_t reg_addr, uint8_t * answer, int len)
357 {
358  int i, f;
359 
360 
361  if (_dbg) printf("I2C %02x (RdRegAlt=%02x)", addr, reg_addr);
362 
363  I2C_Device * dev = vir2Real(dev_);
364 
365  // shift address, and with 1 -> start read
366  if (!i2cOut(dev, ( addr << 1 ) | 1, I2C_CMD_START)) goto exit_f;
367 
368  // write register to read
369  if (!i2cOut(dev, reg_addr, 0)) goto exit_f;
370 
371  // receive the answer
372  for (i = 0; i < len; ++i)
373  {
374  f = 0;
375 
376  if (i == ( len - 1 )) f |= I2C_CMD_STOP | I2C_CMD_ACK;
377 
378  if (!i2cIn(dev, answer, f)) goto exit_f;
379 
380  if (_dbg) printf(" %02x", *answer);
381 
382  answer++;
383  }
384  if (_dbg) puts("");
385 
386  return true;
387 exit_f:
388  i2cAbort(dev);
389  if (_dbg) puts(" (err!)");
390 
391  return false;
392 }
393 
394 void i2cDebug(bool enable)
395 {
396  _dbg = enable;
397 }
bool i2cWrite(I2C_Device *dev, i2cAddr addr, uint8_t *bytes, int len)
Writes to the I2C device.
Definition: i2c.c:219
volatile unsigned int PRE_HI
Prescaler high.
Definition: dev_i2c.h:58
bool i2cExists(I2C_Device *dev, i2cAddr addr, bool *canRead, bool *canWrite)
Checks whether or not an I2C address is present on the bus.
Definition: i2c.c:326
#define I2C_IF_NO_MASK
Interface number mask.
Definition: dev_i2c.h:48
#define E_I2C_NO_ACK
I2C device did not acknowledge TX.
Definition: i2c.h:69
volatile unsigned int PRE_LO
Prescaler low.
Definition: dev_i2c.h:57
volatile unsigned int CTL
Control.
Definition: dev_i2c.h:59
volatile unsigned int IF
Interface no. register (WR extension)
Definition: dev_i2c.h:62
Structure defines OpenCores I2C Device.
Definition: dev_i2c.h:55
#define I2C_STS_ARBLOST
Arbitration lost.
Definition: dev_i2c.h:41
#define E_I2C_TIME_OUT
I2C device timed out.
Definition: i2c.h:74
#define I2C_STS_RXACK
Not Acknowledge receive.
Definition: dev_i2c.h:43
void timeDelay(uint32_t msec)
Simple busy-wait delay.
Definition: tm.c:18
bool i2cSendCmdAlt(I2C_Device *dev, i2cAddr addr, uint8_t *cmd, int cmd_len, uint8_t *answer, int answer_len)
Writes a command to the I2C device and receive the answer.
Definition: i2c.c:287
#define E_I2C_ARB_LOST
Arbitration on the I2C bus lost.
Definition: i2c.h:66
uint8_t i2cAddr
I2C address type.
Definition: i2c.h:93
#define I2C_CMD_IACK
I2C ACK interrupt.
Definition: dev_i2c.h:32
bool i2cReadReg(I2C_Device *dev, i2cAddr addr, uint8_t regNo, uint8_t *rd, int rdLen)
Reads from the I2C device register.
Definition: i2c.c:188
#define I2C_CMD_WR
Write command.
Definition: dev_i2c.h:34
#define I2C_CMD_ACK
Though bit is named ACK, its really NACK when set to 1.
Definition: dev_i2c.h:33
bool i2cWriteRead(I2C_Device *dev, i2cAddr addr, uint8_t *wr, int wrLen, uint8_t *rd, int rdLen)
Writes and Reads To and from the I2C device.
Definition: i2c.c:280
bool i2cWriteReg(I2C_Device *dev, i2cAddr addr, uint8_t regNo, uint8_t *wr, int wrLen)
Writes to the I2C device register.
Definition: i2c.c:247
static uint32_t timeOutInit(uint32_t msec)
Initializes a timeout with the specified no of msecs.
Definition: tm.h:53
#define I2C_CTL_CORE_ENA
Enable core.
Definition: dev_i2c.h:46
#define I2C_CMD_STOP
Issue stop.
Definition: dev_i2c.h:36
#define E_I2C_INIT
I2C WB device failed to initialize properly.
Definition: i2c.h:62
static bool timeOut(uint32_t to)
Checks whether or not the timeout has expired.
Definition: tm.h:77
Manages the global system error.
bool i2cInit(I2C_Device *dev, uint32_t bitrate)
Initializes the I2C device with the specified bitrate.
Definition: i2c.c:122
volatile unsigned int TXRX
Transmit / Receive.
Definition: dev_i2c.h:60
bool i2cReadRegAlt(I2C_Device *dev, i2cAddr addr, uint8_t reg_addr, uint8_t *answer, int len)
Reads a register from a I2C device.
Definition: i2c.c:356
#define I2C_CMD_START
Issue start.
Definition: dev_i2c.h:37
Simple timer functions.
void errClear()
Clears the current error.
Definition: err.c:46
#define I2C_IF_NO_SHIFT
Interface no shift.
Definition: dev_i2c.h:49
#define I2C_CMD_RD
Read command.
Definition: dev_i2c.h:35
uint32_t errGet()
Returns the last error code, or null.
Definition: err.c:74
bool i2cRead(I2C_Device *dev, i2cAddr addr, uint8_t *bytes, int len)
Reads from the I2C device.
Definition: i2c.c:161
volatile unsigned int CMDSTS
Command and Status.
Definition: dev_i2c.h:61
bool errSet(uint32_t code, const char *error, const char *name)
Sets an error.
#define ERROR(CODE,...)
Expands an error code to an error code with a description (if ERROR_W_DESCR is declared).
#define I2C_STS_TIP
Transfer in progress.
Definition: dev_i2c.h:40
OpenCores I2C device driver.