| 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_18xx_43xx.c
Go to the documentation of this file.
1 /*
2 * @brief LPC18xx/43xx 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 /* I2C common interface structure */
40 struct i2c_interface {
41 LPC_I2C_T *ip; /* IP base address of the I2C device */
42 CHIP_CCU_CLK_T clk; /* Clock used by I2C */
43 I2C_EVENTHANDLER_T mEvent; /* Current active Master event handler */
44 I2C_EVENTHANDLER_T sEvent; /* Slave transfer events */
45 I2C_XFER_T *mXfer; /* Current active xfer pointer */
46 I2C_XFER_T *sXfer; /* Pointer to store xfer when bus is busy */
47 uint32_t flags; /* Flags used by I2C master and slave */
48 };
49
50 /* Slave interface structure */
51 struct i2c_slave_interface {
52 I2C_XFER_T *xfer;
53 I2C_EVENTHANDLER_T event;
54 };
55
56 /*****************************************************************************
57 * Public types/enumerations/variables
58 ****************************************************************************/
59 /* I2C interfaces */
60 static struct i2c_interface i2c[I2C_NUM_INTERFACE] = {
61 {LPC_I2C0, CLK_APB1_I2C0, Chip_I2C_EventHandler, NULL, NULL, NULL, 0},
62 {LPC_I2C1, CLK_APB3_I2C1, Chip_I2C_EventHandler, NULL, NULL, NULL, 0}
63 };
64
65 static struct i2c_slave_interface i2c_slave[I2C_NUM_INTERFACE][I2C_SLAVE_NUM_INTERFACE];
66
67 /*****************************************************************************
68 * Private functions
69 ****************************************************************************/
70
71 /*****************************************************************************
72 * Public functions
73 ****************************************************************************/
74 /* Chip event handler interrupt based */
75 void Chip_I2C_EventHandler(I2C_ID_T id, I2C_EVENT_T event)
76 {
77 struct i2c_interface *iic = &i2c[id];
78 volatile I2C_STATUS_T *stat;
79
80 /* Only WAIT event needs to be handled */
81 if (event != I2C_EVENT_WAIT) {
82 return;
83 }
84
85 stat = &iic->mXfer->status;
86 /* Wait for the status to change */
87 while (*stat == I2C_STATUS_BUSY) {}
88 }
89
90 /* Chip polling event handler */
91 void Chip_I2C_EventHandlerPolling(I2C_ID_T id, I2C_EVENT_T event)
92 {
93 struct i2c_interface *iic = &i2c[id];
94 volatile I2C_STATUS_T *stat;
95
96 /* Only WAIT event needs to be handled */
97 if (event != I2C_EVENT_WAIT) {
98 return;
99 }
100
101 stat = &iic->mXfer->status;
102 /* Call the state change handler till xfer is done */
103 while (*stat == I2C_STATUS_BUSY) {
104 if (IP_I2C_IsStateChanged(iic->ip)) {
105 Chip_I2C_MasterStateHandler(id);
106 }
107 }
108 }
109
110 /* Initializes the LPC_I2C peripheral with specified parameter */
111 void Chip_I2C_Init(I2C_ID_T id)
112 {
113 /* Enable I2C Clocking */
114 Chip_Clock_Enable(i2c[id].clk);
115
116 IP_I2C_Init(i2c[id].ip);
117 }
118
119 /* De-initializes the I2C peripheral registers to their default reset values */
120 void Chip_I2C_DeInit(I2C_ID_T id)
121 {
122 IP_I2C_DeInit(i2c[id].ip);
123
124 /* Disable I2C clocking */
125 Chip_Clock_Disable(i2c[id].clk);
126 }
127
128 /* Set up clock rate for LPC_I2C peripheral */
129 void Chip_I2C_SetClockRate(I2C_ID_T id, uint32_t clockrate)
130 {
131 IP_I2C_SetClockRate(i2c[id].ip, Chip_Clock_GetRate(i2c[id].clk) / clockrate);
132 }
133
134 /* Get current clock rate for LPC_I2C peripheral */
135 uint32_t Chip_I2C_GetClockRate(I2C_ID_T id)
136 {
137 return Chip_Clock_GetRate(i2c[id].clk) / IP_I2C_GetClockDiv(i2c[id].ip);
138 }
139
140 /* Set the master event handler */
141 int Chip_I2C_SetMasterEventHandler(I2C_ID_T id, I2C_EVENTHANDLER_T event)
142 {
143 struct i2c_interface *iic = &i2c[id];
144 if (!iic->mXfer) {
145 iic->mEvent = event;
146 }
147 return iic->mEvent == event;
148 }
149
150 /* Get the master event handler */
151 I2C_EVENTHANDLER_T Chip_I2C_GetMasterEventHandler(I2C_ID_T id)
152 {
153 return i2c[id].mEvent;
154 }
155
156 /* Transmit and Receive data in master mode */
157 int Chip_I2C_MasterTransfer(I2C_ID_T id, I2C_XFER_T *xfer)
158 {
159 struct i2c_interface *iic = &i2c[id];
160
161 iic->mEvent(id, I2C_EVENT_LOCK);
162 xfer->status = I2C_STATUS_BUSY;
163 iic->mXfer = xfer;
164
165 /* If slave xfer not in progress */
166 if (!iic->sXfer) {
167 IP_I2C_Master_StartXfer(iic->ip);
168 }
169
170 iic->mEvent(id, I2C_EVENT_WAIT);
171 iic->mXfer = 0;
172
173 /* Wait for stop condition to appear on bus */
174 while (!IP_I2C_BusFree(iic->ip)) {}
175
176 /* Start slave if one is active */
177 if (SLAVE_ACTIVE(iic)) {
178 IP_I2C_Slave_StartXfer(iic->ip);
179 }
180
181 iic->mEvent(id, I2C_EVENT_UNLOCK);
182
183 return 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 }