| 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_17xx_40xx.c
Go to the documentation of this file.
1 /*
2 * @brief LPC17xx/40xx 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 #define SLAVE_ACTIVE(iic) (((iic)->flags & 0xFF00) != 0)
38
39 #ifdef CHIP_LPC175X_6X
40 static const CHIP_SYSCTL_PCLK_T I2C_PeriphClk[I2C_NUM_INTERFACE] = {
41 SYSCTL_PCLK_I2C0,
42 SYSCTL_PCLK_I2C1,
43 SYSCTL_PCLK_I2C2
44 };
45 #define I2C_GetClk(x) Chip_Clock_GetPeripheralClockRate(I2C_PeriphClk[x])
46 #else
47 #define I2C_GetClk(x) Chip_Clock_GetPeripheralClockRate()
48 #endif
49
50 /* I2C common interface structure */
51 struct i2c_interface {
52 LPC_I2C_T *ip; /* IP base address of the I2C device */
53 CHIP_SYSCTL_CLOCK_T clk; /* Clock used by I2C */
54 I2C_EVENTHANDLER_T mEvent; /* Current active Master event handler */
55 I2C_EVENTHANDLER_T sEvent; /* Slave transfer events */
56 I2C_XFER_T *mXfer; /* Current active xfer pointer */
57 I2C_XFER_T *sXfer; /* Pointer to store xfer when bus is busy */
58 uint32_t flags; /* Flags used by I2C master and slave */
59 };
60
61 /* Slave interface structure */
62 struct i2c_slave_interface {
63 I2C_XFER_T *xfer;
64 I2C_EVENTHANDLER_T event;
65 };
66
67 /* I2C interfaces */
68 static struct i2c_interface i2c[I2C_NUM_INTERFACE] = {
69 {LPC_I2C0, SYSCTL_CLOCK_I2C0, Chip_I2C_EventHandler, NULL, NULL, NULL, 0},
70 {LPC_I2C1, SYSCTL_CLOCK_I2C1, Chip_I2C_EventHandler, NULL, NULL, NULL, 0},
71 {LPC_I2C2, SYSCTL_CLOCK_I2C2, Chip_I2C_EventHandler, NULL, NULL, NULL, 0}
72 };
73
74 static struct i2c_slave_interface i2c_slave[I2C_NUM_INTERFACE][I2C_SLAVE_NUM_INTERFACE];
75
76 /*****************************************************************************
77 * Public types/enumerations/variables
78 ****************************************************************************/
79
80 /*****************************************************************************
81 * Private functions
82 ****************************************************************************/
83
84 /*****************************************************************************
85 * Public functions
86 ****************************************************************************/
87 /* Chip event handler interrupt based */
88 void Chip_I2C_EventHandler(I2C_ID_T id, I2C_EVENT_T event)
89 {
90 struct i2c_interface *iic = &i2c[id];
91 volatile I2C_STATUS_T *stat;
92
93 /* Only WAIT event needs to be handled */
94 if (event != I2C_EVENT_WAIT) {
95 return;
96 }
97
98 stat = &iic->mXfer->status;
99 /* Wait for the status to change */
100 while (*stat == I2C_STATUS_BUSY) {}
101 }
102
103 /* Chip polling event handler */
104 void Chip_I2C_EventHandlerPolling(I2C_ID_T id, I2C_EVENT_T event)
105 {
106 struct i2c_interface *iic = &i2c[id];
107 volatile I2C_STATUS_T *stat;
108
109 /* Only WAIT event needs to be handled */
110 if (event != I2C_EVENT_WAIT) {
111 return;
112 }
113
114 stat = &iic->mXfer->status;
115 /* Call the state change handler till xfer is done */
116 while (*stat == I2C_STATUS_BUSY) {
117 if (IP_I2C_IsStateChanged(iic->ip)) {
118 Chip_I2C_MasterStateHandler(id);
119 }
120 }
121 }
122
123 /* Initializes the LPC_I2C peripheral with specified parameter */
124 void Chip_I2C_Init(I2C_ID_T id)
125 {
126 /* Enable I2C Clocking */
127 Chip_Clock_EnablePeriphClock(i2c[id].clk);
128
129 IP_I2C_Init(i2c[id].ip);
130 }
131
132 /* De-initializes the I2C peripheral registers to their default reset values */
133 void Chip_I2C_DeInit(I2C_ID_T id)
134 {
135 IP_I2C_DeInit(i2c[id].ip);
136
137 /* Disable I2C clocking */
138 Chip_Clock_DisablePeriphClock(i2c[id].clk);
139 }
140
141 /* Set up clock rate for LPC_I2C peripheral */
142 void Chip_I2C_SetClockRate(I2C_ID_T id, uint32_t clockrate)
143 {
144 IP_I2C_SetClockRate(i2c[id].ip, I2C_GetClk(id) / clockrate);
145 }
146
147 /* Get current clock rate for LPC_I2C peripheral */
148 uint32_t Chip_I2C_GetClockRate(I2C_ID_T id)
149 {
150 return I2C_GetClk(id) / IP_I2C_GetClockDiv(i2c[id].ip);
151 }
152
153 /* Set the master event handler */
154 int Chip_I2C_SetMasterEventHandler(I2C_ID_T id, I2C_EVENTHANDLER_T event)
155 {
156 struct i2c_interface *iic = &i2c[id];
157 if (!iic->mXfer) {
158 iic->mEvent = event;
159 }
160 return iic->mEvent == event;
161 }
162
163 /* Get the master event handler */
164 I2C_EVENTHANDLER_T Chip_I2C_GetMasterEventHandler(I2C_ID_T id)
165 {
166 return i2c[id].mEvent;
167 }
168
169 /* Transmit and Receive data in master mode */
170 int Chip_I2C_MasterTransfer(I2C_ID_T id, I2C_XFER_T *xfer)
171 {
172 struct i2c_interface *iic = &i2c[id];
173
174 iic->mEvent(id, I2C_EVENT_LOCK);
175 xfer->status = I2C_STATUS_BUSY;
176 iic->mXfer = xfer;
177
178 /* If slave xfer not in progress */
179 if (!iic->sXfer) {
180 IP_I2C_Master_StartXfer(iic->ip);
181 }
182 iic->mEvent(id, I2C_EVENT_WAIT);
183 iic->mXfer = 0;
184
185 /* Wait for stop condition to appear on bus */
186 while (!IP_I2C_BusFree(iic->ip)) {}
187
188 /* Start slave if one is active */
189 if (SLAVE_ACTIVE(iic)) {
190 IP_I2C_Slave_StartXfer(iic->ip);
191 }
192
193 iic->mEvent(id, I2C_EVENT_UNLOCK);
194 return (int) xfer->status;
195 }
196
197 /* Master tx only */
198 int Chip_I2C_MasterSend(I2C_ID_T id, uint8_t slaveAddr, const uint8_t *buff, uint8_t len)
199 {
200 I2C_XFER_T xfer = {0};
201 xfer.slaveAddr = slaveAddr;
202 xfer.txBuff = buff;
203 xfer.txSz = len;
204 while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
205 return len - xfer.txSz;
206 }
207
208 /* Transmit one byte and receive an array of bytes after a repeated start condition is generated in Master mode.
209 * This function is useful for communicating with the I2C slave registers
210 */
211 int Chip_I2C_MasterCmdRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t cmd, uint8_t *buff, int len)
212 {
213 I2C_XFER_T xfer = {0};
214 xfer.slaveAddr = slaveAddr;
215 xfer.txBuff = &cmd;
216 xfer.txSz = 1;
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 /* Sequential master read */
224 int Chip_I2C_MasterRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t *buff, int len)
225 {
226 I2C_XFER_T xfer = {0};
227 xfer.slaveAddr = slaveAddr;
228 xfer.rxBuff = buff;
229 xfer.rxSz = len;
230 while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
231 return len - xfer.rxSz;
232 }
233
234 /* Check if master state is active */
235 int Chip_I2C_IsMasterActive(I2C_ID_T id)
236 {
237 return IP_I2C_IsMasterState(i2c[id].ip);
238 }
239
240 /* State change handler for master transfer */
241 void Chip_I2C_MasterStateHandler(I2C_ID_T id)
242 {
243 if (!IP_I2C_MasterXfer_StateHandler(i2c[id].ip, i2c[id].mXfer)) {
244 i2c[id].mEvent(id, I2C_EVENT_DONE);
245 }
246 }
247
248 /* Setup slave function */
249 void Chip_I2C_SlaveSetup(I2C_ID_T id,
250 I2C_SLAVE_ID sid,
251 I2C_XFER_T *xfer,
252 I2C_EVENTHANDLER_T event,
253 uint8_t addrMask)
254 {
255 struct i2c_interface *iic = &i2c[id];
256 struct i2c_slave_interface *si2c = &i2c_slave[id][sid];
257 si2c->xfer = xfer;
258 si2c->event = event;
259
260 /* Set up the slave address */
261 if (sid != I2C_SLAVE_GENERAL) {
262 IP_I2C_SetSlaveAddress(iic->ip, sid, xfer->slaveAddr, addrMask);
263 }
264
265 if (!SLAVE_ACTIVE(iic) && !iic->mXfer) {
266 IP_I2C_Slave_StartXfer(iic->ip);
267 }
268 iic->flags |= 1 << (sid + 8);
269 }
270
271 /* I2C Slave event handler */
272 void Chip_I2C_SlaveStateHandler(I2C_ID_T id)
273 {
274 int ret;
275 struct i2c_interface *iic = &i2c[id];
276
277 /* Get the currently addressed slave */
278 if (!iic->sXfer) {
279 struct i2c_slave_interface *si2c;
280
281 I2C_SLAVE_ID sid = IP_I2C_GetSlaveIndex(iic->ip);
282 si2c = &i2c_slave[id][sid];
283 iic->sXfer = si2c->xfer;
284 iic->sEvent = si2c->event;
285 }
286
287 iic->sXfer->slaveAddr |= iic->mXfer != 0;
288 ret = IP_I2C_SlaveXfer_StateHandler(iic->ip, iic->sXfer);
289 if (ret) {
290 if (iic->sXfer->status == I2C_STATUS_DONE) {
291 iic->sXfer = 0;
292 }
293 iic->sEvent(id, (I2C_EVENT_T) ret);
294 }
295 }
296
297 /* Disable I2C device */
298 void Chip_I2C_Disable(I2C_ID_T id)
299 {
300 IP_I2C_Disable(i2c[id].ip);
301 }
302
303 /* State change checking */
304 int Chip_I2C_IsStateChanged(I2C_ID_T id)
305 {
306 return IP_I2C_IsStateChanged(i2c[id].ip);
307 }