| 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_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 {
51 I2C_XFER_T *xfer;
52 I2C_EVENTHANDLER_T event;
53 };
54
55 /* I2C interfaces */
56 static struct i2c_interface i2c[I2C_NUM_INTERFACE] = {
57 {LPC_I2C, SYSCTL_CLOCK_I2C, Chip_I2C_EventHandler, NULL, NULL, NULL, 0}
58 };
59
60 static struct i2c_slave_interface i2c_slave[I2C_NUM_INTERFACE][I2C_SLAVE_NUM_INTERFACE];
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 */
74 void Chip_I2C_EventHandler(I2C_ID_T id, I2C_EVENT_T event)
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 */
90 void Chip_I2C_EventHandlerPolling(I2C_ID_T id, I2C_EVENT_T event)
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)) {
104 Chip_I2C_MasterStateHandler(id);
105 }
106 }
107 }
108
109 /* Initializes the LPC_I2C peripheral with specified parameter */
110 void Chip_I2C_Init(I2C_ID_T id)
111 {
112 /* Enable I2C Clocking */
113 Chip_Clock_EnablePeriphClock(i2c[id].clk);
114
115 IP_I2C_Init(i2c[id].ip);
116 }
117
118 /* De-initializes the I2C peripheral registers to their default reset values */
119 void Chip_I2C_DeInit(I2C_ID_T id)
120 {
121 IP_I2C_DeInit(i2c[id].ip);
122
123 /* Disable I2C clocking */
124 Chip_Clock_DisablePeriphClock(i2c[id].clk);
125 }
126
127 /* Set up clock rate for LPC_I2C peripheral */
128 void Chip_I2C_SetClockRate(I2C_ID_T id, uint32_t clockrate)
129 {
130 IP_I2C_SetClockRate(i2c[id].ip, (Chip_Clock_GetSystemClockRate() / clockrate));
131 }
132
133 /* Get current clock rate for LPC_I2C peripheral */
134 uint32_t Chip_I2C_GetClockRate(I2C_ID_T id)
135 {
136 return Chip_Clock_GetSystemClockRate() / IP_I2C_GetClockDiv(i2c[id].ip);
137 }
138
139 /* Set the master event handler */
140 int Chip_I2C_SetMasterEventHandler(I2C_ID_T id, I2C_EVENTHANDLER_T event)
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 */
150 I2C_EVENTHANDLER_T Chip_I2C_GetMasterEventHandler(I2C_ID_T id)
151 {
152 return i2c[id].mEvent;
153 }
154
155 /* Transmit and Receive data in master mode */
156 int Chip_I2C_MasterTransfer(I2C_ID_T id, I2C_XFER_T *xfer)
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) {
166 IP_I2C_Master_StartXfer(iic->ip);
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)) {
176 IP_I2C_Slave_StartXfer(iic->ip);
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 */
221 int Chip_I2C_IsMasterActive(I2C_ID_T id)
222 {
223 return IP_I2C_IsMasterState(i2c[id].ip);
224 }
225
226 /* State change handler for master transfer */
227 void Chip_I2C_MasterStateHandler(I2C_ID_T id)
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 */
235 void Chip_I2C_SlaveSetup(I2C_ID_T id,
236 I2C_SLAVE_ID sid,
237 I2C_XFER_T *xfer,
238 I2C_EVENTHANDLER_T event,
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) {
252 IP_I2C_Slave_StartXfer(iic->ip);
253 }
254 iic->flags |= 1 << (sid + 8);
255 }
256
257 /* I2C Slave event handler */
258 void Chip_I2C_SlaveStateHandler(I2C_ID_T id)
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
267 I2C_SLAVE_ID sid = IP_I2C_GetSlaveIndex(iic->ip);
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 */
284 void Chip_I2C_Disable(I2C_ID_T id)
285 {
286 IP_I2C_Disable(i2c[id].ip);
287 }
288
289 /* State change checking */
290 int Chip_I2C_IsStateChanged(I2C_ID_T id)
291 {
292 return IP_I2C_IsStateChanged(i2c[id].ip);
293 }