LPCOpen Platform for LPC18XX/43XX microcontrollers  18XX43XX
LPCOpen Platform for the NXP LPC18XX/43XX family of Microcontrollers
i2c_18xx_43xx.c
Go to the documentation of this file.
1 /*
2  * @brief LPC18xx/43xx I2C driver
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2013
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_CCU_CLK_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 */
64 };
65 
67 
68 /*****************************************************************************
69  * Public types/enumerations/variables
70  ****************************************************************************/
71 
72 /*****************************************************************************
73  * Private functions
74  ****************************************************************************/
75 
77 {
78  Chip_Clock_Enable(i2c[id].clk);
79 }
80 
82 {
83  Chip_Clock_Disable(i2c[id].clk);
84 }
85 
86 /* Get the ADC Clock Rate */
88 {
89  return Chip_Clock_GetRate(i2c[id].clk);
90 }
91 
92 /* Enable I2C and start master transfer */
94 {
95  /* Reset STA, STO, SI */
97 
98  /* Enter to Master Transmitter mode */
100 }
101 
102 /* Enable I2C and enable slave transfers */
104 {
105  /* Reset STA, STO, SI */
106  pI2C->CONCLR = I2C_CON_SI | I2C_CON_STA;
107 
108  /* Enter to Master Transmitter mode */
109  pI2C->CONSET = I2C_CON_I2EN | I2C_CON_AA;
110 }
111 
112 /* Check if I2C bus is free */
114 {
115  return !(pI2C->CONSET & I2C_CON_STO);
116 }
117 
118 /* Get current state of the I2C peripheral */
120 {
121  return (int) (pI2C->STAT & I2C_STAT_CODE_BITMASK);
122 }
123 
124 /* Check if the active state belongs to master mode*/
126 {
127  return getCurState(pI2C) < 0x60;
128 }
129 
130 /* Set OWN slave address for specific slave ID */
131 STATIC void setSlaveAddr(LPC_I2C_T *pI2C, I2C_SLAVE_ID sid, uint8_t addr, uint8_t mask)
132 {
133  uint32_t index = (uint32_t) sid - 1;
134  pI2C->MASK[index] = mask;
135  if (sid == I2C_SLAVE_0) {
136  pI2C->ADR0 = addr;
137  }
138  else {
139  volatile uint32_t *abase = &pI2C->ADR1;
140  abase[index - 1] = addr;
141  }
142 }
143 
144 /* Match the slave address */
145 STATIC int isSlaveAddrMatching(uint8_t addr1, uint8_t addr2, uint8_t mask)
146 {
147  mask |= 1;
148  return (addr1 & ~mask) == (addr2 & ~mask);
149 }
150 
151 /* Get the index of the active slave */
153 {
154  if (!(slaveAddr >> 1)) {
155  return I2C_SLAVE_GENERAL; /* General call address */
156  }
157  if (isSlaveAddrMatching(pI2C->ADR0, slaveAddr, pI2C->MASK[0])) {
158  return I2C_SLAVE_0;
159  }
160  if (isSlaveAddrMatching(pI2C->ADR1, slaveAddr, pI2C->MASK[1])) {
161  return I2C_SLAVE_1;
162  }
163  if (isSlaveAddrMatching(pI2C->ADR2, slaveAddr, pI2C->MASK[2])) {
164  return I2C_SLAVE_2;
165  }
166  if (isSlaveAddrMatching(pI2C->ADR3, slaveAddr, pI2C->MASK[3])) {
167  return I2C_SLAVE_3;
168  }
169 
170  /* If everything is fine the code should never come here */
171  return I2C_SLAVE_GENERAL;
172 }
173 
174 /* Master transfer state change handler handler */
176 {
177  uint32_t cclr = I2C_CON_FLAGS;
178 
179  switch (getCurState(pI2C)) {
180  case 0x08: /* Start condition on bus */
181  case 0x10: /* Repeated start condition */
182  pI2C->DAT = (xfer->slaveAddr << 1) | (xfer->txSz == 0);
183  break;
184 
185  /* Tx handling */
186  case 0x18: /* SLA+W sent and ACK received */
187  case 0x28: /* DATA sent and ACK received */
188  if (!xfer->txSz) {
189  cclr &= ~(xfer->rxSz ? I2C_CON_STA : I2C_CON_STO);
190  }
191  else {
192  pI2C->DAT = *xfer->txBuff++;
193  xfer->txSz--;
194  }
195  break;
196 
197  /* Rx handling */
198  case 0x58: /* Data Received and NACK sent */
199  cclr &= ~I2C_CON_STO;
200 
201  case 0x50: /* Data Received and ACK sent */
202  *xfer->rxBuff++ = pI2C->DAT;
203  xfer->rxSz--;
204 
205  case 0x40: /* SLA+R sent and ACK received */
206  if (xfer->rxSz > 1) {
207  cclr &= ~I2C_CON_AA;
208  }
209  break;
210 
211  /* NAK Handling */
212  case 0x20: /* SLA+W sent NAK received */
213  case 0x48: /* SLA+R sent NAK received */
214  xfer->status = I2C_STATUS_SLAVENAK;
215  cclr &= ~I2C_CON_STO;
216  break;
217 
218  case 0x30: /* DATA sent NAK received */
219  xfer->status = I2C_STATUS_NAK;
220  cclr &= ~I2C_CON_STO;
221  break;
222 
223  case 0x38: /* Arbitration lost */
224  xfer->status = I2C_STATUS_ARBLOST;
225  break;
226 
227  /* Bus Error */
228  case 0x00:
229  xfer->status = I2C_STATUS_BUSERR;
230  cclr &= ~I2C_CON_STO;
231  }
232 
233  /* Set clear control flags */
234  pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
235  pI2C->CONCLR = cclr & ~I2C_CON_STO;
236 
237  /* If stopped return 0 */
238  if (!(cclr & I2C_CON_STO) || (xfer->status == I2C_STATUS_ARBLOST)) {
239  if (xfer->status == I2C_STATUS_BUSY) {
240  xfer->status = I2C_STATUS_DONE;
241  }
242  return 0;
243  }
244  return 1;
245 }
246 
247 /* Find the slave address of SLA+W or SLA+R */
249 {
250  switch (getCurState(pI2C)) {
251  case 0x60:
252  case 0x68:
253  case 0x70:
254  case 0x78:
255  case 0xA8:
256  case 0xB0:
257  return lookupSlaveIndex(pI2C, pI2C->DAT);
258  }
259 
260  /* If everything is fine code should never come here */
261  return I2C_SLAVE_GENERAL;
262 }
263 
264 /* Slave state machine handler */
266 {
267  uint32_t cclr = I2C_CON_FLAGS;
268  int ret = RET_SLAVE_BUSY;
269 
270  xfer->status = I2C_STATUS_BUSY;
271  switch (getCurState(pI2C)) {
272  case 0x80: /* SLA: Data received + ACK sent */
273  case 0x90: /* GC: Data received + ACK sent */
274  *xfer->rxBuff++ = pI2C->DAT;
275  xfer->rxSz--;
276  ret = RET_SLAVE_RX;
277  if (xfer->rxSz > 1) {
278  cclr &= ~I2C_CON_AA;
279  }
280  break;
281 
282  case 0x60: /* Own SLA+W received */
283  case 0x68: /* Own SLA+W received after losing arbitration */
284  case 0x70: /* GC+W received */
285  case 0x78: /* GC+W received after losing arbitration */
286  xfer->slaveAddr = pI2C->DAT & ~1;
287  if (xfer->rxSz > 1) {
288  cclr &= ~I2C_CON_AA;
289  }
290  break;
291 
292  case 0xA8: /* SLA+R received */
293  case 0xB0: /* SLA+R received after losing arbitration */
294  xfer->slaveAddr = pI2C->DAT & ~1;
295 
296  case 0xB8: /* DATA sent and ACK received */
297  pI2C->DAT = *xfer->txBuff++;
298  xfer->txSz--;
299  if (xfer->txSz > 0) {
300  cclr &= ~I2C_CON_AA;
301  }
302  ret = RET_SLAVE_TX;
303  break;
304 
305  case 0xC0: /* Data transmitted and NAK received */
306  case 0xC8: /* Last data transmitted and ACK received */
307  case 0x88: /* SLA: Data received + NAK sent */
308  case 0x98: /* GC: Data received + NAK sent */
309  case 0xA0: /* STOP/Repeated START condition received */
310  ret = RET_SLAVE_IDLE;
311  cclr &= ~I2C_CON_AA;
312  xfer->status = I2C_STATUS_DONE;
313  if (xfer->slaveAddr & 1) {
314  cclr &= ~I2C_CON_STA;
315  }
316  break;
317  }
318 
319  /* Set clear control flags */
320  pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
321  pI2C->CONCLR = cclr & ~I2C_CON_STO;
322 
323  return ret;
324 }
325 
326 /*****************************************************************************
327  * Public functions
328  ****************************************************************************/
329 /* Chip event handler interrupt based */
331 {
332  struct i2c_interface *iic = &i2c[id];
333  volatile I2C_STATUS_T *stat;
334 
335  /* Only WAIT event needs to be handled */
336  if (event != I2C_EVENT_WAIT) {
337  return;
338  }
339 
340  stat = &iic->mXfer->status;
341  /* Wait for the status to change */
342  while (*stat == I2C_STATUS_BUSY) {}
343 }
344 
345 /* Chip polling event handler */
347 {
348  struct i2c_interface *iic = &i2c[id];
349  volatile I2C_STATUS_T *stat;
350 
351  /* Only WAIT event needs to be handled */
352  if (event != I2C_EVENT_WAIT) {
353  return;
354  }
355 
356  stat = &iic->mXfer->status;
357  /* Call the state change handler till xfer is done */
358  while (*stat == I2C_STATUS_BUSY) {
359  if (Chip_I2C_IsStateChanged(id)) {
361  }
362  }
363 }
364 
365 /* Initializes the LPC_I2C peripheral with specified parameter */
367 {
368  enableClk(id);
369 
370  /* Set I2C operation to default */
371  LPC_I2Cx(id)->CONCLR = (I2C_CON_AA | I2C_CON_SI | I2C_CON_STA | I2C_CON_I2EN);
372 }
373 
374 /* De-initializes the I2C peripheral registers to their default reset values */
376 {
377  /* Disable I2C control */
379 
380  disableClk(id);
381 }
382 
383 /* Set up clock rate for LPC_I2C peripheral */
384 void Chip_I2C_SetClockRate(I2C_ID_T id, uint32_t clockrate)
385 {
386  uint32_t SCLValue;
387 
388  SCLValue = (getClkRate(id) / clockrate);
389  LPC_I2Cx(id)->SCLH = (uint32_t) (SCLValue >> 1);
390  LPC_I2Cx(id)->SCLL = (uint32_t) (SCLValue - LPC_I2Cx(id)->SCLH);
391 }
392 
393 /* Get current clock rate for LPC_I2C peripheral */
395 {
396  return getClkRate(id) / (LPC_I2Cx(id)->SCLH + LPC_I2Cx(id)->SCLL);
397 }
398 
399 /* Set the master event handler */
401 {
402  struct i2c_interface *iic = &i2c[id];
403  if (!iic->mXfer) {
404  iic->mEvent = event;
405  }
406  return iic->mEvent == event;
407 }
408 
409 /* Get the master event handler */
411 {
412  return i2c[id].mEvent;
413 }
414 
415 /* Transmit and Receive data in master mode */
417 {
418  struct i2c_interface *iic = &i2c[id];
419 
420  iic->mEvent(id, I2C_EVENT_LOCK);
421  xfer->status = I2C_STATUS_BUSY;
422  iic->mXfer = xfer;
423 
424  /* If slave xfer not in progress */
425  if (!iic->sXfer) {
426  startMasterXfer(iic->ip);
427  }
428  iic->mEvent(id, I2C_EVENT_WAIT);
429  iic->mXfer = 0;
430 
431  /* Wait for stop condition to appear on bus */
432  while (!isI2CBusFree(iic->ip)) {}
433 
434  /* Start slave if one is active */
435  if (SLAVE_ACTIVE(iic)) {
436  startSlaverXfer(iic->ip);
437  }
438 
439  iic->mEvent(id, I2C_EVENT_UNLOCK);
440  return (int) xfer->status;
441 }
442 
443 /* Master tx only */
444 int Chip_I2C_MasterSend(I2C_ID_T id, uint8_t slaveAddr, const uint8_t *buff, uint8_t len)
445 {
446  I2C_XFER_T xfer = {0};
447  xfer.slaveAddr = slaveAddr;
448  xfer.txBuff = buff;
449  xfer.txSz = len;
450  while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
451  return len - xfer.txSz;
452 }
453 
454 /* Transmit one byte and receive an array of bytes after a repeated start condition is generated in Master mode.
455  * This function is useful for communicating with the I2C slave registers
456  */
457 int Chip_I2C_MasterCmdRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t cmd, uint8_t *buff, int len)
458 {
459  I2C_XFER_T xfer = {0};
460  xfer.slaveAddr = slaveAddr;
461  xfer.txBuff = &cmd;
462  xfer.txSz = 1;
463  xfer.rxBuff = buff;
464  xfer.rxSz = len;
465  while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
466  return len - xfer.rxSz;
467 }
468 
469 /* Sequential master read */
470 int Chip_I2C_MasterRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t *buff, int len)
471 {
472  I2C_XFER_T xfer = {0};
473  xfer.slaveAddr = slaveAddr;
474  xfer.rxBuff = buff;
475  xfer.rxSz = len;
476  while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
477  return len - xfer.rxSz;
478 }
479 
480 /* Check if master state is active */
482 {
483  return isMasterState(i2c[id].ip);
484 }
485 
486 /* State change handler for master transfer */
488 {
489  if (!handleMasterXferState(i2c[id].ip, i2c[id].mXfer)) {
490  i2c[id].mEvent(id, I2C_EVENT_DONE);
491  }
492 }
493 
494 /* Setup slave function */
496  I2C_SLAVE_ID sid,
497  I2C_XFER_T *xfer,
498  I2C_EVENTHANDLER_T event,
499  uint8_t addrMask)
500 {
501  struct i2c_interface *iic = &i2c[id];
502  struct i2c_slave_interface *si2c = &i2c_slave[id][sid];
503  si2c->xfer = xfer;
504  si2c->event = event;
505 
506  /* Set up the slave address */
507  if (sid != I2C_SLAVE_GENERAL) {
508  setSlaveAddr(iic->ip, sid, xfer->slaveAddr, addrMask);
509  }
510 
511  if (!SLAVE_ACTIVE(iic) && !iic->mXfer) {
512  startSlaverXfer(iic->ip);
513  }
514  iic->flags |= 1 << (sid + 8);
515 }
516 
517 /* I2C Slave event handler */
519 {
520  int ret;
521  struct i2c_interface *iic = &i2c[id];
522 
523  /* Get the currently addressed slave */
524  if (!iic->sXfer) {
525  struct i2c_slave_interface *si2c;
526 
527  I2C_SLAVE_ID sid = getSlaveIndex(iic->ip);
528  si2c = &i2c_slave[id][sid];
529  iic->sXfer = si2c->xfer;
530  iic->sEvent = si2c->event;
531  }
532 
533  iic->sXfer->slaveAddr |= iic->mXfer != 0;
534  ret = handleSlaveXferState(iic->ip, iic->sXfer);
535  if (ret) {
536  if (iic->sXfer->status == I2C_STATUS_DONE) {
537  iic->sXfer = 0;
538  }
539  iic->sEvent(id, (I2C_EVENT_T) ret);
540  }
541 }
542 
543 /* Disable I2C device */
545 {
546  LPC_I2Cx(id)->CONCLR = I2C_I2CONCLR_I2ENC;
547 }
548 
549 /* State change checking */
551 {
552  return (LPC_I2Cx(id)->CONSET & I2C_CON_SI) != 0;
553 }
554