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