LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
i2c_11xx.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 #if !defined(CHIP_LPC110X) /* Chip 110x does not have I2C IP in it */
33 
34 #include "chip.h"
35 
36 /*****************************************************************************
37  * Private types/enumerations/variables
38  ****************************************************************************/
39 #define SLAVE_ACTIVE(iic) (((iic)->flags & 0xFF00) != 0)
40 
41 /* I2C common interface structure */
42 struct i2c_interface {
43  LPC_I2C_T *ip; /* IP base address of the I2C device */
44  CHIP_SYSCTL_CLOCK_T clk; /* Clock used by I2C */
45  I2C_EVENTHANDLER_T mEvent; /* Current active Master event handler */
46  I2C_EVENTHANDLER_T sEvent; /* Slave transfer events */
47  I2C_XFER_T *mXfer; /* Current active xfer pointer */
48  I2C_XFER_T *sXfer; /* Pointer to store xfer when bus is busy */
49  uint32_t flags; /* Flags used by I2C master and slave */
50 };
51 
52 /* Slave interface structure */
56 };
57 
58 /* I2C interfaces */
61 };
62 
64 
65 /*****************************************************************************
66  * Public types/enumerations/variables
67  ****************************************************************************/
68 
69 /*****************************************************************************
70  * Private functions
71  ****************************************************************************/
72 
73 /*****************************************************************************
74  * Public functions
75  ****************************************************************************/
76 /* Chip event handler interrupt based */
78 {
79  struct i2c_interface *iic = &i2c[id];
80  volatile I2C_STATUS_T *stat;
81 
82  /* Only WAIT event needs to be handled */
83  if (event != I2C_EVENT_WAIT) {
84  return;
85  }
86 
87  stat = &iic->mXfer->status;
88  /* Wait for the status to change */
89  while (*stat == I2C_STATUS_BUSY) {}
90 }
91 
92 /* Chip polling event handler */
94 {
95  struct i2c_interface *iic = &i2c[id];
96  volatile I2C_STATUS_T *stat;
97 
98  /* Only WAIT event needs to be handled */
99  if (event != I2C_EVENT_WAIT) {
100  return;
101  }
102 
103  stat = &iic->mXfer->status;
104  /* Call the state change handler till xfer is done */
105  while (*stat == I2C_STATUS_BUSY) {
106  if (IP_I2C_IsStateChanged(iic->ip)) {
108  }
109  }
110 }
111 
112 /* Initializes the LPC_I2C peripheral with specified parameter */
114 {
115  /* Enable I2C Clocking */
117 
118  IP_I2C_Init(i2c[id].ip);
119 }
120 
121 /* De-initializes the I2C peripheral registers to their default reset values */
123 {
124  IP_I2C_DeInit(i2c[id].ip);
125 
126  /* Disable I2C clocking */
128 }
129 
130 /* Set up clock rate for LPC_I2C peripheral */
132 {
133  IP_I2C_SetClockRate(i2c[id].ip, (Chip_Clock_GetMainClockRate() / clockrate));
134 }
135 
136 /* Get current clock rate for LPC_I2C peripheral */
138 {
140 }
141 
142 /* Set the master event handler */
144 {
145  struct i2c_interface *iic = &i2c[id];
146  if (!iic->mXfer) {
147  iic->mEvent = event;
148  }
149  return iic->mEvent == event;
150 }
151 
152 /* Get the master event handler */
154 {
155  return i2c[id].mEvent;
156 }
157 
158 /* Transmit and Receive data in master mode */
160 {
161  struct i2c_interface *iic = &i2c[id];
162 
163  iic->mEvent(id, I2C_EVENT_LOCK);
164  xfer->status = I2C_STATUS_BUSY;
165  iic->mXfer = xfer;
166 
167  /* If slave xfer not in progress */
168  if (!iic->sXfer) {
170  }
171  iic->mEvent(id, I2C_EVENT_WAIT);
172  iic->mXfer = 0;
173 
174  /* Wait for stop condition to appear on bus */
175  while (!IP_I2C_BusFree(iic->ip)) {}
176 
177  /* Start slave if one is active */
178  if (SLAVE_ACTIVE(iic)) {
180  }
181 
182  iic->mEvent(id, I2C_EVENT_UNLOCK);
183  return (int) xfer->status;
184 }
185 
186 /* Master tx only */
187 int Chip_I2C_MasterSend(I2C_ID_T id, uint8_t slaveAddr, const uint8_t *buff, uint8_t len)
188 {
189  I2C_XFER_T xfer = {0};
190  xfer.slaveAddr = slaveAddr;
191  xfer.txBuff = buff;
192  xfer.txSz = len;
193  while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
194  return len - xfer.txSz;
195 }
196 
197 /* Transmit one byte and receive an array of bytes after a repeated start condition is generated in Master mode.
198  * This function is useful for communicating with the I2C slave registers
199  */
200 int Chip_I2C_MasterCmdRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t cmd, uint8_t *buff, int len)
201 {
202  I2C_XFER_T xfer = {0};
203  xfer.slaveAddr = slaveAddr;
204  xfer.txBuff = &cmd;
205  xfer.txSz = 1;
206  xfer.rxBuff = buff;
207  xfer.rxSz = len;
208  while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
209  return len - xfer.rxSz;
210 }
211 
212 /* Sequential master read */
213 int Chip_I2C_MasterRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t *buff, int len)
214 {
215  I2C_XFER_T xfer = {0};
216  xfer.slaveAddr = slaveAddr;
217  xfer.rxBuff = buff;
218  xfer.rxSz = len;
219  while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
220  return len - xfer.rxSz;
221 }
222 
223 /* Check if master state is active */
225 {
226  return IP_I2C_IsMasterState(i2c[id].ip);
227 }
228 
229 /* State change handler for master transfer */
231 {
232  if (!IP_I2C_MasterXfer_StateHandler(i2c[id].ip, i2c[id].mXfer)) {
233  i2c[id].mEvent(id, I2C_EVENT_DONE);
234  }
235 }
236 
237 /* Setup slave function */
239  I2C_SLAVE_ID sid,
240  I2C_XFER_T *xfer,
242  uint8_t addrMask)
243 {
244  struct i2c_interface *iic = &i2c[id];
245  struct i2c_slave_interface *si2c = &i2c_slave[id][sid];
246  si2c->xfer = xfer;
247  si2c->event = event;
248 
249  /* Set up the slave address */
250  if (sid != I2C_SLAVE_GENERAL) {
251  IP_I2C_SetSlaveAddress(iic->ip, sid, xfer->slaveAddr, addrMask);
252  }
253 
254  if (!SLAVE_ACTIVE(iic) && !iic->mXfer) {
256  }
257  iic->flags |= 1 << (sid + 8);
258 }
259 
260 /* I2C Slave event handler */
262 {
263  int ret;
264  struct i2c_interface *iic = &i2c[id];
265 
266  /* Get the currently addressed slave */
267  if (!iic->sXfer) {
268  struct i2c_slave_interface *si2c;
269 
271  si2c = &i2c_slave[id][sid];
272  iic->sXfer = si2c->xfer;
273  iic->sEvent = si2c->event;
274  }
275 
276  iic->sXfer->slaveAddr |= iic->mXfer != 0;
277  ret = IP_I2C_SlaveXfer_StateHandler(iic->ip, iic->sXfer);
278  if (ret) {
279  if (iic->sXfer->status == I2C_STATUS_DONE) {
280  iic->sXfer = 0;
281  }
282  iic->sEvent(id, (I2C_EVENT_T) ret);
283  }
284 }
285 
286 /* Disable I2C device */
288 {
289  IP_I2C_Disable(i2c[id].ip);
290 }
291 
292 /* State change checking */
294 {
295  return IP_I2C_IsStateChanged(i2c[id].ip);
296 }
297 
298 #endif