LPCOpen Platform for LPC112X microcontrollers  112X
LPCOpen Platform for the NXP LPC112X family of Microcontrollers
i2c_112x.c
Go to the documentation of this file.
1 /*
2  * @brief LPC11xx I2C driver
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2012
6  * All rights reserved.
7  *
8  * @par
9  * Software that is described herein is for illustrative purposes only
10  * which provides customers with programming information regarding the
11  * LPC products. This software is supplied "AS IS" without any warranties of
12  * any kind, and NXP Semiconductors and its licensor disclaim any and
13  * all warranties, express or implied, including all implied warranties of
14  * merchantability, fitness for a particular purpose and non-infringement of
15  * intellectual property rights. NXP Semiconductors assumes no responsibility
16  * or liability for the use of the software, conveys no license or rights under any
17  * patent, copyright, mask work right, or any other intellectual property rights in
18  * or to any products. NXP Semiconductors reserves the right to make changes
19  * in the software without notification. NXP Semiconductors also makes no
20  * representation or warranty that such application will be suitable for the
21  * specified use without further testing or modification.
22  *
23  * @par
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation is hereby granted, under NXP Semiconductors' and its
26  * licensor's relevant copyrights in the software, without fee, provided that it
27  * is used in conjunction with NXP Semiconductors microcontrollers. This
28  * copyright, permission, and disclaimer notice must appear in all copies of
29  * this code.
30  */
31 
32 #include "chip.h"
33 
34 /*****************************************************************************
35  * Private types/enumerations/variables
36  ****************************************************************************/
37 
38 /* Control flags */
39 #define I2C_CON_FLAGS (I2C_CON_AA | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA)
40 #define LPC_I2Cx(id) ((i2c[id].ip))
41 #define SLAVE_ACTIVE(iic) (((iic)->flags & 0xFF00) != 0)
42 
43 /* I2C common interface structure */
44 struct i2c_interface {
45  LPC_I2C_T *ip; /* IP base address of the I2C device */
46  CHIP_SYSCON_CLOCK_T clk; /* Clock used by I2C */
47  I2C_EVENTHANDLER_T mEvent; /* Current active Master event handler */
48  I2C_EVENTHANDLER_T sEvent; /* Slave transfer events */
49  I2C_XFER_T *mXfer; /* Current active xfer pointer */
50  I2C_XFER_T *sXfer; /* Pointer to store xfer when bus is busy */
51  uint32_t flags; /* Flags used by I2C master and slave */
52 };
53 
54 /* Slave interface structure */
58 };
59 
60 /* I2C interfaces */
63 };
64 
66 
67 /*****************************************************************************
68  * Public types/enumerations/variables
69  ****************************************************************************/
70 
71 /*****************************************************************************
72  * Private functions
73  ****************************************************************************/
74 
76 {
77  Chip_Clock_EnablePeriphClock(i2c[id].clk);
78 }
79 
81 {
82  Chip_Clock_DisablePeriphClock(i2c[id].clk);
83 }
84 
85 /* Get the ADC Clock Rate */
87 {
89 }
90 
91 /* Enable I2C and start master transfer */
93 {
94  /* Reset STA, STO, SI */
96 
97  /* Enter to Master Transmitter mode */
99 }
100 
101 /* Enable I2C and enable slave transfers */
103 {
104  /* Reset STA, STO, SI */
105  pI2C->CONCLR = I2C_CON_SI | I2C_CON_STA;
106 
107  /* Enter to Master Transmitter mode */
108  pI2C->CONSET = I2C_CON_I2EN | I2C_CON_AA;
109 }
110 
111 /* Check if I2C bus is free */
113 {
114  return !(pI2C->CONSET & I2C_CON_STO);
115 }
116 
117 /* Get current state of the I2C peripheral */
119 {
120  return (int) (pI2C->STAT & I2C_STAT_CODE_BITMASK);
121 }
122 
123 /* Check if the active state belongs to master mode*/
125 {
126  return getCurState(pI2C) < 0x60;
127 }
128 
129 /* Set OWN slave address for specific slave ID */
130 STATIC void setSlaveAddr(LPC_I2C_T *pI2C, I2C_SLAVE_ID sid, uint8_t addr, uint8_t mask)
131 {
132  uint32_t index = (uint32_t) sid - 1;
133  pI2C->MASK[index] = mask;
134  if (sid == I2C_SLAVE_0) {
135  pI2C->ADR0 = addr;
136  }
137  else {
138  volatile uint32_t *abase = &pI2C->ADR1;
139  abase[index - 1] = addr;
140  }
141 }
142 
143 /* Match the slave address */
144 STATIC int isSlaveAddrMatching(uint8_t addr1, uint8_t addr2, uint8_t mask)
145 {
146  mask |= 1;
147  return (addr1 & ~mask) == (addr2 & ~mask);
148 }
149 
150 /* Get the index of the active slave */
152 {
153  if (!(slaveAddr >> 1)) {
154  return I2C_SLAVE_GENERAL; /* General call address */
155  }
156  if (isSlaveAddrMatching(pI2C->ADR0, slaveAddr, pI2C->MASK[0])) {
157  return I2C_SLAVE_0;
158  }
159  if (isSlaveAddrMatching(pI2C->ADR1, slaveAddr, pI2C->MASK[1])) {
160  return I2C_SLAVE_1;
161  }
162  if (isSlaveAddrMatching(pI2C->ADR2, slaveAddr, pI2C->MASK[2])) {
163  return I2C_SLAVE_2;
164  }
165  if (isSlaveAddrMatching(pI2C->ADR3, slaveAddr, pI2C->MASK[3])) {
166  return I2C_SLAVE_3;
167  }
168 
169  /* If everything is fine the code should never come here */
170  return I2C_SLAVE_GENERAL;
171 }
172 
173 /* Master transfer state change handler handler */
175 {
176  uint32_t cclr = I2C_CON_FLAGS;
177 
178  switch (getCurState(pI2C)) {
179  case 0x08: /* Start condition on bus */
180  case 0x10: /* Repeated start condition */
181  pI2C->DAT = (xfer->slaveAddr << 1) | (xfer->txSz == 0);
182  break;
183 
184  /* Tx handling */
185  case 0x18: /* SLA+W sent and ACK received */
186  case 0x28: /* DATA sent and ACK received */
187  if (!xfer->txSz) {
188  cclr &= ~(xfer->rxSz ? I2C_CON_STA : I2C_CON_STO);
189  }
190  else {
191  pI2C->DAT = *xfer->txBuff++;
192  xfer->txSz--;
193  }
194  break;
195 
196  /* Rx handling */
197  case 0x58: /* Data Received and NACK sent */
198  cclr &= ~I2C_CON_STO;
199 
200  case 0x50: /* Data Received and ACK sent */
201  *xfer->rxBuff++ = pI2C->DAT;
202  xfer->rxSz--;
203 
204  case 0x40: /* SLA+R sent and ACK received */
205  if (xfer->rxSz > 1) {
206  cclr &= ~I2C_CON_AA;
207  }
208  break;
209 
210  /* NAK Handling */
211  case 0x20: /* SLA+W sent NAK received */
212  case 0x30: /* DATA sent NAK received */
213  case 0x48: /* SLA+R sent NAK received */
214  xfer->status = I2C_STATUS_NAK;
215  cclr &= ~I2C_CON_STO;
216  break;
217 
218  case 0x38: /* Arbitration lost */
219  xfer->status = I2C_STATUS_ARBLOST;
220  break;
221 
222  /* Bus Error */
223  case 0x00:
224  xfer->status = I2C_STATUS_BUSERR;
225  cclr &= ~I2C_CON_STO;
226  }
227 
228  /* Set clear control flags */
229  pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
230  pI2C->CONCLR = cclr & ~I2C_CON_STO;
231 
232  /* If stopped return 0 */
233  if (!(cclr & I2C_CON_STO) || (xfer->status == I2C_STATUS_ARBLOST)) {
234  if (xfer->status == I2C_STATUS_BUSY) {
235  xfer->status = I2C_STATUS_DONE;
236  }
237  return 0;
238  }
239  return 1;
240 }
241 
242 /* Find the slave address of SLA+W or SLA+R */
244 {
245  switch (getCurState(pI2C)) {
246  case 0x60:
247  case 0x68:
248  case 0x70:
249  case 0x78:
250  case 0xA8:
251  case 0xB0:
252  return lookupSlaveIndex(pI2C, pI2C->DAT);
253  }
254 
255  /* If everything is fine code should never come here */
256  return I2C_SLAVE_GENERAL;
257 }
258 
259 /* Slave state machine handler */
261 {
262  uint32_t cclr = I2C_CON_FLAGS;
263  int ret = RET_SLAVE_BUSY;
264 
265  xfer->status = I2C_STATUS_BUSY;
266  switch (getCurState(pI2C)) {
267  case 0x80: /* SLA: Data received + ACK sent */
268  case 0x90: /* GC: Data received + ACK sent */
269  *xfer->rxBuff++ = pI2C->DAT;
270  xfer->rxSz--;
271  ret = RET_SLAVE_RX;
272  if (xfer->rxSz > 1) {
273  cclr &= ~I2C_CON_AA;
274  }
275  break;
276 
277  case 0x60: /* Own SLA+W received */
278  case 0x68: /* Own SLA+W received after losing arbitration */
279  case 0x70: /* GC+W received */
280  case 0x78: /* GC+W received after losing arbitration */
281  xfer->slaveAddr = pI2C->DAT & ~1;
282  if (xfer->rxSz > 1) {
283  cclr &= ~I2C_CON_AA;
284  }
285  break;
286 
287  case 0xA8: /* SLA+R received */
288  case 0xB0: /* SLA+R received after losing arbitration */
289  xfer->slaveAddr = pI2C->DAT & ~1;
290 
291  case 0xB8: /* DATA sent and ACK received */
292  pI2C->DAT = *xfer->txBuff++;
293  xfer->txSz--;
294  if (xfer->txSz > 0) {
295  cclr &= ~I2C_CON_AA;
296  }
297  ret = RET_SLAVE_TX;
298  break;
299 
300  case 0xC0: /* Data transmitted and NAK received */
301  case 0xC8: /* Last data transmitted and ACK received */
302  case 0x88: /* SLA: Data received + NAK sent */
303  case 0x98: /* GC: Data received + NAK sent */
304  case 0xA0: /* STOP/Repeated START condition received */
305  ret = RET_SLAVE_IDLE;
306  cclr &= ~I2C_CON_AA;
307  xfer->status = I2C_STATUS_DONE;
308  if (xfer->slaveAddr & 1) {
309  cclr &= ~I2C_CON_STA;
310  }
311  break;
312  }
313 
314  /* Set clear control flags */
315  pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
316  pI2C->CONCLR = cclr & ~I2C_CON_STO;
317 
318  return ret;
319 }
320 
321 /*****************************************************************************
322  * Public functions
323  ****************************************************************************/
324 
325 /* Chip event handler interrupt based */
327 {
328  struct i2c_interface *iic = &i2c[id];
329  volatile I2C_STATUS_T *stat;
330 
331  /* Only WAIT event needs to be handled */
332  if (event != I2C_EVENT_WAIT) {
333  return;
334  }
335 
336  stat = &iic->mXfer->status;
337  /* Wait for the status to change */
338  while (*stat == I2C_STATUS_BUSY) {}
339 }
340 
341 /* Chip polling event handler */
343 {
344  struct i2c_interface *iic = &i2c[id];
345  volatile I2C_STATUS_T *stat;
346 
347  /* Only WAIT event needs to be handled */
348  if (event != I2C_EVENT_WAIT) {
349  return;
350  }
351 
352  stat = &iic->mXfer->status;
353  /* Call the state change handler till xfer is done */
354  while (*stat == I2C_STATUS_BUSY) {
355  if (Chip_I2C_IsStateChanged(id)) {
357  }
358  }
359 }
360 
361 /* Initializes the LPC_I2C peripheral with specified parameter */
363 {
364  enableClk(id);
365 
366  /* Bring I2C out of reset */
368 
369  /* Set I2C operation to default */
370  LPC_I2Cx(id)->CONCLR = (I2C_CON_AA | I2C_CON_SI | I2C_CON_STA | I2C_CON_I2EN);
371 }
372 
373 /* De-initializes the I2C peripheral registers to their default reset values */
375 {
376  /* Disable I2C control */
378 
379  disableClk(id);
380 }
381 
382 /* Set up clock rate for LPC_I2C peripheral */
383 void Chip_I2C_SetClockRate(I2C_ID_T id, uint32_t clockrate)
384 {
385  uint32_t SCLValue;
386 
387  SCLValue = (getClkRate(id) / clockrate);
388  LPC_I2Cx(id)->SCLH = (uint32_t) (SCLValue >> 1);
389  LPC_I2Cx(id)->SCLL = (uint32_t) (SCLValue - LPC_I2Cx(id)->SCLH);
390 }
391 
392 /* Get current clock rate for LPC_I2C peripheral */
394 {
395  return getClkRate(id) / (LPC_I2Cx(id)->SCLH + LPC_I2Cx(id)->SCLL);
396 }
397 
398 /* Set the master event handler */
400 {
401  struct i2c_interface *iic = &i2c[id];
402  if (!iic->mXfer) {
403  iic->mEvent = event;
404  }
405  return iic->mEvent == event;
406 }
407 
408 /* Get the master event handler */
410 {
411  return i2c[id].mEvent;
412 }
413 
414 /* Transmit and Receive data in master mode */
416 {
417  struct i2c_interface *iic = &i2c[id];
418 
419  iic->mEvent(id, I2C_EVENT_LOCK);
420  xfer->status = I2C_STATUS_BUSY;
421  iic->mXfer = xfer;
422 
423  /* If slave xfer not in progress */
424  if (!iic->sXfer) {
425  startMasterXfer(iic->ip);
426  }
427  iic->mEvent(id, I2C_EVENT_WAIT);
428  iic->mXfer = 0;
429 
430  /* Wait for stop condition to appear on bus */
431  while (!isI2CBusFree(iic->ip)) {}
432 
433  /* Start slave if one is active */
434  if (SLAVE_ACTIVE(iic)) {
435  startSlaverXfer(iic->ip);
436  }
437 
438  iic->mEvent(id, I2C_EVENT_UNLOCK);
439  return (int) xfer->status;
440 }
441 
442 /* Master tx only */
443 int Chip_I2C_MasterSend(I2C_ID_T id, uint8_t slaveAddr, const uint8_t *buff, uint8_t len)
444 {
445  I2C_XFER_T xfer = {0};
446  xfer.slaveAddr = slaveAddr;
447  xfer.txBuff = buff;
448  xfer.txSz = len;
449  while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
450  return len - xfer.txSz;
451 }
452 
453 /* Transmit one byte and receive an array of bytes after a repeated start condition is generated in Master mode.
454  * This function is useful for communicating with the I2C slave registers
455  */
456 int Chip_I2C_MasterCmdRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t cmd, uint8_t *buff, int len)
457 {
458  I2C_XFER_T xfer = {0};
459  xfer.slaveAddr = slaveAddr;
460  xfer.txBuff = &cmd;
461  xfer.txSz = 1;
462  xfer.rxBuff = buff;
463  xfer.rxSz = len;
464  while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
465  return len - xfer.rxSz;
466 }
467 
468 /* Sequential master read */
469 int Chip_I2C_MasterRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t *buff, int len)
470 {
471  I2C_XFER_T xfer = {0};
472  xfer.slaveAddr = slaveAddr;
473  xfer.rxBuff = buff;
474  xfer.rxSz = len;
475  while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
476  return len - xfer.rxSz;
477 }
478 
479 /* Check if master state is active */
481 {
482  return isMasterState(i2c[id].ip);
483 }
484 
485 /* State change handler for master transfer */
487 {
488  if (!handleMasterXferState(i2c[id].ip, i2c[id].mXfer)) {
489  i2c[id].mEvent(id, I2C_EVENT_DONE);
490  }
491 }
492 
493 /* Setup slave function */
495  I2C_SLAVE_ID sid,
496  I2C_XFER_T *xfer,
497  I2C_EVENTHANDLER_T event,
498  uint8_t addrMask)
499 {
500  struct i2c_interface *iic = &i2c[id];
501  struct i2c_slave_interface *si2c = &i2c_slave[id][sid];
502  si2c->xfer = xfer;
503  si2c->event = event;
504 
505  /* Set up the slave address */
506  if (sid != I2C_SLAVE_GENERAL) {
507  setSlaveAddr(iic->ip, sid, xfer->slaveAddr, addrMask);
508  }
509 
510  if (!SLAVE_ACTIVE(iic) && !iic->mXfer) {
511  startSlaverXfer(iic->ip);
512  }
513  iic->flags |= 1 << (sid + 8);
514 }
515 
516 /* I2C Slave event handler */
518 {
519  int ret;
520  struct i2c_interface *iic = &i2c[id];
521 
522  /* Get the currently addressed slave */
523  if (!iic->sXfer) {
524  struct i2c_slave_interface *si2c;
525 
526  I2C_SLAVE_ID sid = getSlaveIndex(iic->ip);
527  si2c = &i2c_slave[id][sid];
528  iic->sXfer = si2c->xfer;
529  iic->sEvent = si2c->event;
530  }
531 
532  iic->sXfer->slaveAddr |= iic->mXfer != 0;
533  ret = handleSlaveXferState(iic->ip, iic->sXfer);
534  if (ret) {
535  if (iic->sXfer->status == I2C_STATUS_DONE) {
536  iic->sXfer = 0;
537  }
538  iic->sEvent(id, (I2C_EVENT_T) ret);
539  }
540 }
541 
542 /* Disable I2C device */
544 {
545  LPC_I2Cx(id)->CONCLR = I2C_I2CONCLR_I2ENC;
546 }
547 
548 /* State change checking */
550 {
551  return (LPC_I2Cx(id)->CONSET & I2C_CON_SI) != 0;
552 }