| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

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 */
53 struct i2c_slave_interface {
54 I2C_XFER_T *xfer;
55 I2C_EVENTHANDLER_T event;
56 };
57
58 /* I2C interfaces */
59 static struct i2c_interface i2c[I2C_NUM_INTERFACE] = {
60 {LPC_I2C, SYSCTL_CLOCK_I2C, Chip_I2C_EventHandler, NULL, NULL, NULL, 0}
61 };
62
63 static struct i2c_slave_interface i2c_slave[I2C_NUM_INTERFACE][I2C_SLAVE_NUM_INTERFACE];
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 */
77 void Chip_I2C_EventHandler(I2C_ID_T id, I2C_EVENT_T event)
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 */
93 void Chip_I2C_EventHandlerPolling(I2C_ID_T id, I2C_EVENT_T event)
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)) {
107 Chip_I2C_MasterStateHandler(id);
108 }
109 }
110 }
111
112 /* Initializes the LPC_I2C peripheral with specified parameter */
113 void Chip_I2C_Init(I2C_ID_T id)
114 {
115 /* Enable I2C Clocking */
116 Chip_Clock_EnablePeriphClock(i2c[id].clk);
117
118 IP_I2C_Init(i2c[id].ip);
119 }
120
121 /* De-initializes the I2C peripheral registers to their default reset values */
122 void Chip_I2C_DeInit(I2C_ID_T id)
123 {
124 IP_I2C_DeInit(i2c[id].ip);
125
126 /* Disable I2C clocking */
127 Chip_Clock_DisablePeriphClock(i2c[id].clk);
128 }
129
130 /* Set up clock rate for LPC_I2C peripheral */
131 void Chip_I2C_SetClockRate(I2C_ID_T id, uint32_t clockrate)
132 {
133 IP_I2C_SetClockRate(i2c[id].ip, (Chip_Clock_GetMainClockRate() / clockrate));
134 }
135
136 /* Get current clock rate for LPC_I2C peripheral */
137 uint32_t Chip_I2C_GetClockRate(I2C_ID_T id)
138 {
139 return Chip_Clock_GetMainClockRate() / IP_I2C_GetClockDiv(i2c[id].ip);
140 }
141
142 /* Set the master event handler */
143 int Chip_I2C_SetMasterEventHandler(I2C_ID_T id, I2C_EVENTHANDLER_T event)
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 */
153 I2C_EVENTHANDLER_T Chip_I2C_GetMasterEventHandler(I2C_ID_T id)
154 {
155 return i2c[id].mEvent;
156 }
157
158 /* Transmit and Receive data in master mode */
159 int Chip_I2C_MasterTransfer(I2C_ID_T id, I2C_XFER_T *xfer)
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) {
169 IP_I2C_Master_StartXfer(iic->ip);
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)) {
179 IP_I2C_Slave_StartXfer(iic->ip);
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 */
224 int Chip_I2C_IsMasterActive(I2C_ID_T id)
225 {
226 return IP_I2C_IsMasterState(i2c[id].ip);
227 }
228
229 /* State change handler for master transfer */
230 void Chip_I2C_MasterStateHandler(I2C_ID_T id)
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 */
238 void Chip_I2C_SlaveSetup(I2C_ID_T id,
239 I2C_SLAVE_ID sid,
240 I2C_XFER_T *xfer,
241 I2C_EVENTHANDLER_T event,
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) {
255 IP_I2C_Slave_StartXfer(iic->ip);
256 }
257 iic->flags |= 1 << (sid + 8);
258 }
259
260 /* I2C Slave event handler */
261 void Chip_I2C_SlaveStateHandler(I2C_ID_T id)
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
270 I2C_SLAVE_ID sid = IP_I2C_GetSlaveIndex(iic->ip);
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 */
287 void Chip_I2C_Disable(I2C_ID_T id)
288 {
289 IP_I2C_Disable(i2c[id].ip);
290 }
291
292 /* State change checking */
293 int Chip_I2C_IsStateChanged(I2C_ID_T id)
294 {
295 return IP_I2C_IsStateChanged(i2c[id].ip);
296 }
297
298 #endif