LPCOpen Platform for LPC18XX/43XX microcontrollers: C:/w/lpcopen_docs/software/lpc_core/lpc_chip/chip_18xx_43xx/i2cm_18xx_43xx.c Source File

| LPCOpen Platform for LPC18XX/43XX microcontrollers 18XX43XX LPCOpen Platform for the NXP LPC18XX/43XX family of Microcontrollers

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

i2cm_18xx_43xx.c
Go to the documentation of this file.
1 /*
2 * @brief LPC18xx/43xx I2C master driver
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2013
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
38 /* Control flags */
39 #define I2C_CON_FLAGS (I2C_CON_AA | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA)
40
41 /*****************************************************************************
42 * Public types/enumerations/variables
43 ****************************************************************************/
44
45 /*****************************************************************************
46 * Private functions
47 ****************************************************************************/
48 /* Get the ADC Clock Rate */
49 static CHIP_CCU_CLK_T i2cm_getClkId(LPC_I2C_T *pI2C)
50 {
51 return (pI2C == LPC_I2C0)? CLK_APB1_I2C0 : CLK_APB3_I2C1;
52 }
53
54 /*****************************************************************************
55 * Public functions
56 ****************************************************************************/
57
58 /* Initializes the LPC_I2C peripheral with specified parameter */
59 void Chip_I2CM_Init(LPC_I2C_T *pI2C)
60 {
61 /* Enable I2C clock */
62 Chip_Clock_Enable(i2cm_getClkId(pI2C));
63 /* Reset I2C state machine */
64 Chip_I2CM_ResetControl(pI2C);
65 }
66
67 /* De-initializes the I2C peripheral registers to their default reset values */
68 void Chip_I2CM_DeInit(LPC_I2C_T *pI2C)
69 {
70 /* Reset I2C state machine */
71 Chip_I2CM_ResetControl(pI2C);
72 /* Disable I2C clock */
73 Chip_Clock_Disable(i2cm_getClkId(pI2C));
74 }
75
76 /* Set up bus speed for LPC_I2C interface */
77 void Chip_I2CM_SetBusSpeed(LPC_I2C_T *pI2C, uint32_t busSpeed)
78 {
79 uint32_t clockDiv = (Chip_Clock_GetRate(i2cm_getClkId(pI2C)) / busSpeed);
80
81 Chip_I2CM_SetDutyCycle(pI2C, (clockDiv >> 1), (clockDiv - (clockDiv >> 1)));
82 }
83
84 /* Master transfer state change handler handler */
85 uint32_t Chip_I2CM_XferHandler(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer)
86 {
87 uint32_t cclr = I2C_CON_FLAGS;
88
89 switch (Chip_I2CM_GetCurState(pI2C)) {
90 case 0x08: /* Start condition on bus */
91 case 0x10: /* Repeated start condition */
92 pI2C->DAT = (xfer->slaveAddr << 1) | (xfer->txSz == 0);
93 break;
94
95 /* Tx handling */
96 case 0x20: /* SLA+W sent NAK received */
97 case 0x30: /* DATA sent NAK received */
98 if ((xfer->options & I2CM_XFER_OPTION_IGNORE_NACK) == 0) {
99 xfer->status = I2CM_STATUS_NAK;
100 cclr &= ~I2C_CON_STO;
101 break;
102 }
103
104 case 0x18: /* SLA+W sent and ACK received */
105 case 0x28: /* DATA sent and ACK received */
106 if (!xfer->txSz) {
107 if (xfer->rxSz) {
108 cclr &= ~I2C_CON_STA;
109 }
110 else {
111 xfer->status = I2CM_STATUS_OK;
112 cclr &= ~I2C_CON_STO;
113 }
114
115 }
116 else {
117 pI2C->DAT = *xfer->txBuff++;
118 xfer->txSz--;
119 }
120 break;
121
122 /* Rx handling */
123 case 0x58: /* Data Received and NACK sent */
124 case 0x50: /* Data Received and ACK sent */
125 *xfer->rxBuff++ = pI2C->DAT;
126 xfer->rxSz--;
127
128 case 0x40: /* SLA+R sent and ACK received */
129 if ((xfer->rxSz > 1) || (xfer->options & I2CM_XFER_OPTION_LAST_RX_ACK)) {
130 cclr &= ~I2C_CON_AA;
131 }
132 if (xfer->rxSz == 0) {
133 xfer->status = I2CM_STATUS_OK;
134 cclr &= ~I2C_CON_STO;
135 }
136 break;
137
138 /* NAK Handling */
139 case 0x48: /* SLA+R sent NAK received */
140 xfer->status = I2CM_STATUS_SLAVE_NAK;
141 cclr &= ~I2C_CON_STO;
142 break;
143
144 case 0x38: /* Arbitration lost */
145 xfer->status = I2CM_STATUS_ARBLOST;
146 break;
147
148 case 0x00: /* Bus Error */
149 xfer->status = I2CM_STATUS_BUS_ERROR;
150 cclr &= ~I2C_CON_STO;
151 break;
152 default:
153 xfer->status = I2CM_STATUS_ERROR;
154 cclr &= ~I2C_CON_STO;
155 break;
156 }
157
158 /* Set clear control flags */
159 pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
160 /* Stop flag should not be cleared as it is a reserved bit */
161 pI2C->CONCLR = cclr & (I2C_CON_AA | I2C_CON_SI | I2C_CON_STA);
162
163 return xfer->status != I2CM_STATUS_BUSY;
164 }
165
166 /* Transmit and Receive data in master mode */
167 void Chip_I2CM_Xfer(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer)
168 {
169 /* set the transfer status as busy */
170 xfer->status = I2CM_STATUS_BUSY;
171 /* Clear controller state. */
172 Chip_I2CM_ResetControl(pI2C);
173 /* Enter to Master Transmitter mode */
174 Chip_I2CM_SendStart(pI2C);
175 }
176
177 /* Transmit and Receive data in master mode */
178 uint32_t Chip_I2CM_XferBlocking(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer)
179 {
180 uint32_t ret = 0;
181 /* start transfer */
182 Chip_I2CM_Xfer(pI2C, xfer);
183
184 while (ret == 0) {
185 /* wait for status change interrupt */
186 while ( Chip_I2CM_StateChanged(pI2C) == 0) {}
187 /* call state change handler */
188 ret = Chip_I2CM_XferHandler(pI2C, xfer);
189 }
190 return ret;
191 }
192
193 /* Master tx only */
194 uint32_t Chip_I2CM_Write(LPC_I2C_T *pI2C, const uint8_t *buff, uint32_t len)
195 {
196 uint32_t txLen = 0, err = 0;
197
198 /* clear state change interrupt status */
199 Chip_I2CM_ClearSI(pI2C);
200 /* generate START condition */
201 Chip_I2CM_SendStart(pI2C);
202
203 while ((txLen < len) && (err == 0)) {
204 /* wait for status change interrupt */
205 while ( Chip_I2CM_StateChanged(pI2C) == 0) {}
206
207 /* check status and send data */
208 switch (Chip_I2CM_GetCurState(pI2C)) {
209 case 0x08: /* Start condition on bus */
210 case 0x10: /* Repeated start condition */
211 case 0x18: /* SLA+W sent and ACK received */
212 case 0x28: /* DATA sent and ACK received */
213 Chip_I2CM_WriteByte(pI2C, buff[txLen++]);
214 break;
215
216 case 0x38: /* Arbitration lost */
217 break;
218
219 default: /* we shouldn't be in any other state */
220 err = 1;
221 break;
222 }
223 /* clear state change interrupt status */
224 Chip_I2CM_ClearSI(pI2C);
225 }
226
227 return txLen;
228 }
229
230 /* Sequential master read */
231 uint32_t Chip_I2CM_Read(LPC_I2C_T *pI2C, uint8_t *buff, uint32_t len)
232 {
233 uint32_t rxLen = 0, err = 0;
234
235 /* clear state change interrupt status */
236 Chip_I2CM_ClearSI(pI2C);
237 /* generate START condition and auto-ack data received */
238 pI2C->CONSET = I2C_CON_AA | I2C_CON_STA;
239
240 while ((rxLen < len) && (err == 0)) {
241 /* wait for status change interrupt */
242 while ( Chip_I2CM_StateChanged(pI2C) == 0) {}
243
244 /* check status and send data */
245 switch (Chip_I2CM_GetCurState(pI2C)) {
246 case 0x08: /* Start condition on bus */
247 case 0x10: /* Repeated start condition */
248 case 0x40: /* SLA+R sent and ACK received */
249 case 0x50: /* Data Received and ACK sent */
250 buff[rxLen++] = Chip_I2CM_ReadByte(pI2C);
251 break;
252
253 case 0x38: /* Arbitration lost */
254 break;
255
256 default: /* we shouldn't be in any other state */
257 err = 1;
258 break;
259 }
260 /* clear state change interrupt status */
261 Chip_I2CM_ClearSI(pI2C);
262 }
263
264 return rxLen;
265 }