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