Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
i2c_api.c
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "i2c_api.h" 00017 00018 #if DEVICE_I2C 00019 00020 #include "cmsis.h" 00021 #include "pinmap.h" 00022 #include "error.h" 00023 00024 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00025 static const PinMap PinMap_I2C_SDA[] = { 00026 {P0_0 , I2C_1, 3}, 00027 {P0_10, I2C_2, 2}, 00028 {P0_19, I2C_1, 3}, 00029 {P0_27, I2C_0, 1}, 00030 {NC , NC , 0} 00031 }; 00032 00033 static const PinMap PinMap_I2C_SCL[] = { 00034 {P0_1 , I2C_1, 3}, 00035 {P0_11, I2C_2, 2}, 00036 {P0_20, I2C_1, 3}, 00037 {P0_28, I2C_0, 1}, 00038 {NC , NC, 0} 00039 }; 00040 00041 #define I2C_CONSET(x) (x->i2c->I2CONSET) 00042 #define I2C_CONCLR(x) (x->i2c->I2CONCLR) 00043 #define I2C_STAT(x) (x->i2c->I2STAT) 00044 #define I2C_DAT(x) (x->i2c->I2DAT) 00045 #define I2C_SCLL(x, val) (x->i2c->I2SCLL = val) 00046 #define I2C_SCLH(x, val) (x->i2c->I2SCLH = val) 00047 00048 #elif defined(TARGET_LPC11U24) 00049 static const PinMap PinMap_I2C_SDA[] = { 00050 {P0_5, I2C_0, 1}, 00051 {NC , NC , 0} 00052 }; 00053 00054 static const PinMap PinMap_I2C_SCL[] = { 00055 {P0_4, I2C_0, 1}, 00056 {NC , NC, 0} 00057 }; 00058 00059 #define I2C_CONSET(x) (x->i2c->CONSET) 00060 #define I2C_CONCLR(x) (x->i2c->CONCLR) 00061 #define I2C_STAT(x) (x->i2c->STAT) 00062 #define I2C_DAT(x) (x->i2c->DAT) 00063 #define I2C_SCLL(x, val) (x->i2c->SCLL = val) 00064 #define I2C_SCLH(x, val) (x->i2c->SCLH = val) 00065 00066 #elif defined(TARGET_LPC812) 00067 static const SWM_Map SWM_I2C_SDA[] = { 00068 {7, 24}, 00069 }; 00070 00071 static const SWM_Map SWM_I2C_SCL[] = { 00072 {8, 0}, 00073 }; 00074 00075 static uint8_t repeated_start = 0; 00076 00077 #define I2C_DAT(x) (x->i2c->MSTDAT) 00078 #define I2C_STAT(x) ((x->i2c->STAT >> 1) & (0x07)) 00079 00080 #endif 00081 00082 00083 #if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) 00084 static const uint32_t I2C_addr_offset[2][4] = { 00085 {0x0C, 0x20, 0x24, 0x28}, 00086 {0x30, 0x34, 0x38, 0x3C} 00087 }; 00088 00089 static inline void i2c_conclr(i2c_t *obj, int start, int stop, int interrupt, int acknowledge) { 00090 I2C_CONCLR(obj) = (start << 5) 00091 | (stop << 4) 00092 | (interrupt << 3) 00093 | (acknowledge << 2); 00094 } 00095 00096 static inline void i2c_conset(i2c_t *obj, int start, int stop, int interrupt, int acknowledge) { 00097 I2C_CONSET(obj) = (start << 5) 00098 | (stop << 4) 00099 | (interrupt << 3) 00100 | (acknowledge << 2); 00101 } 00102 00103 // Clear the Serial Interrupt (SI) 00104 static inline void i2c_clear_SI(i2c_t *obj) { 00105 i2c_conclr(obj, 0, 0, 1, 0); 00106 } 00107 #endif 00108 00109 00110 static inline int i2c_status(i2c_t *obj) { 00111 return I2C_STAT(obj); 00112 } 00113 00114 // Wait until the Serial Interrupt (SI) is set 00115 static int i2c_wait_SI(i2c_t *obj) { 00116 int timeout = 0; 00117 #if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) 00118 while (!(I2C_CONSET(obj) & (1 << 3))) { 00119 #elif defined(TARGET_LPC812) 00120 while (!(obj->i2c->STAT & (1 << 0))) { 00121 #endif 00122 timeout++; 00123 if (timeout > 100000) return -1; 00124 } 00125 return 0; 00126 } 00127 00128 static inline void i2c_interface_enable(i2c_t *obj) { 00129 #if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) 00130 I2C_CONSET(obj) = 0x40; 00131 #elif defined(TARGET_LPC812) 00132 obj->i2c->CFG |= (1 << 0); 00133 #endif 00134 } 00135 00136 static inline void i2c_power_enable(i2c_t *obj) { 00137 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00138 switch ((int)obj->i2c) { 00139 case I2C_0: LPC_SC->PCONP |= 1 << 7; break; 00140 case I2C_1: LPC_SC->PCONP |= 1 << 19; break; 00141 case I2C_2: LPC_SC->PCONP |= 1 << 26; break; 00142 } 00143 #elif defined(TARGET_LPC11U24) 00144 LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 5); 00145 LPC_SYSCON->PRESETCTRL |= 1 << 1; 00146 #elif defined(TARGET_LPC812) 00147 LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5); 00148 LPC_SYSCON->PRESETCTRL &= ~(0x1<<6); 00149 LPC_SYSCON->PRESETCTRL |= (0x1<<6); 00150 #endif 00151 } 00152 00153 void i2c_init(i2c_t *obj, PinName sda, PinName scl) { 00154 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24) 00155 // determine the SPI to use 00156 I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA); 00157 I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL); 00158 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00159 obj->i2c = (LPC_I2C_TypeDef *)pinmap_merge(i2c_sda, i2c_scl); 00160 #elif defined(TARGET_LPC11U24) 00161 obj->i2c = (LPC_I2C_Type *)pinmap_merge(i2c_sda, i2c_scl); 00162 #endif 00163 00164 if ((int)obj->i2c == NC) { 00165 error("I2C pin mapping failed"); 00166 } 00167 00168 // enable power 00169 i2c_power_enable(obj); 00170 00171 // set default frequency at 100k 00172 i2c_frequency(obj, 100000); 00173 i2c_conclr(obj, 1, 1, 1, 1); 00174 i2c_interface_enable(obj); 00175 00176 pinmap_pinout(sda, PinMap_I2C_SDA); 00177 pinmap_pinout(scl, PinMap_I2C_SCL); 00178 00179 #elif defined (TARGET_LPC812) 00180 obj->i2c = (LPC_I2C_TypeDef *)LPC_I2C; 00181 00182 const SWM_Map *swm; 00183 uint32_t regVal; 00184 00185 swm = &SWM_I2C_SDA[0]; 00186 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); 00187 LPC_SWM->PINASSIGN[swm->n] = regVal | (sda << swm->offset); 00188 00189 swm = &SWM_I2C_SCL[0]; 00190 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); 00191 LPC_SWM->PINASSIGN[swm->n] = regVal | (scl << swm->offset); 00192 00193 // enable power 00194 i2c_power_enable(obj); 00195 // set default frequency at 100k 00196 i2c_frequency(obj, 100000); 00197 i2c_interface_enable(obj); 00198 #endif 00199 00200 } 00201 00202 inline int i2c_start(i2c_t *obj) { 00203 int status = 0; 00204 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24) 00205 // 8.1 Before master mode can be entered, I2CON must be initialised to: 00206 // - I2EN STA STO SI AA - - 00207 // - 1 0 0 0 x - - 00208 // if AA = 0, it can't enter slave mode 00209 i2c_conclr(obj, 1, 1, 1, 1); 00210 00211 // The master mode may now be entered by setting the STA bit 00212 // this will generate a start condition when the bus becomes free 00213 i2c_conset(obj, 1, 0, 0, 1); 00214 00215 i2c_wait_SI(obj); 00216 status = i2c_status(obj); 00217 00218 // Clear start bit now transmitted, and interrupt bit 00219 i2c_conclr(obj, 1, 0, 0, 0); 00220 #elif defined(TARGET_LPC812) 00221 if (repeated_start) { 00222 obj->i2c->MSTCTL = (1 << 1) | (1 << 0); 00223 repeated_start = 0; 00224 } else { 00225 obj->i2c->MSTCTL = (1 << 1); 00226 } 00227 #endif 00228 return status; 00229 } 00230 00231 inline void i2c_stop(i2c_t *obj) { 00232 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24) 00233 // write the stop bit 00234 i2c_conset(obj, 0, 1, 0, 0); 00235 i2c_clear_SI(obj); 00236 00237 // wait for STO bit to reset 00238 while(I2C_CONSET(obj) & (1 << 4)); 00239 #elif defined(TARGET_LPC812) 00240 obj->i2c->MSTCTL = (1 << 2) | (1 << 0); 00241 while ((obj->i2c->STAT & ((1 << 0) | (7 << 1))) != ((1 << 0) | (0 << 1))); 00242 #endif 00243 } 00244 00245 00246 static inline int i2c_do_write(i2c_t *obj, int value, uint8_t addr) { 00247 // write the data 00248 I2C_DAT(obj) = value; 00249 00250 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24) 00251 // clear SI to init a send 00252 i2c_clear_SI(obj); 00253 #elif defined(TARGET_LPC812) 00254 if (!addr) 00255 obj->i2c->MSTCTL = (1 << 0); 00256 #endif 00257 00258 // wait and return status 00259 i2c_wait_SI(obj); 00260 return i2c_status(obj); 00261 } 00262 00263 static inline int i2c_do_read(i2c_t *obj, int last) { 00264 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24) 00265 // we are in state 0x40 (SLA+R tx'd) or 0x50 (data rx'd and ack) 00266 if(last) { 00267 i2c_conclr(obj, 0, 0, 0, 1); // send a NOT ACK 00268 } else { 00269 i2c_conset(obj, 0, 0, 0, 1); // send a ACK 00270 } 00271 00272 // accept byte 00273 i2c_clear_SI(obj); 00274 #endif 00275 00276 // wait for it to arrive 00277 i2c_wait_SI(obj); 00278 00279 #if defined(TARGET_LPC812) 00280 if (!last) 00281 obj->i2c->MSTCTL = (1 << 0); 00282 #endif 00283 00284 // return the data 00285 return (I2C_DAT(obj) & 0xFF); 00286 } 00287 00288 void i2c_frequency(i2c_t *obj, int hz) { 00289 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00290 // [TODO] set pclk to /4 00291 uint32_t PCLK = SystemCoreClock / 4; 00292 #elif defined(TARGET_LPC11U24) || defined(TARGET_LPC812) 00293 // No peripheral clock divider on the M0 00294 uint32_t PCLK = SystemCoreClock ; 00295 #endif 00296 00297 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24) 00298 uint32_t pulse = PCLK / (hz * 2); 00299 00300 // I2C Rate 00301 I2C_SCLL(obj, pulse); 00302 I2C_SCLH(obj, pulse); 00303 #elif defined(TARGET_LPC812) 00304 uint32_t clkdiv = PCLK / (hz * 4) - 1; 00305 00306 obj->i2c->DIV = clkdiv; 00307 obj->i2c->MSTTIME = 0; 00308 #endif 00309 } 00310 00311 // The I2C does a read or a write as a whole operation 00312 // There are two types of error conditions it can encounter 00313 // 1) it can not obtain the bus 00314 // 2) it gets error responses at part of the transmission 00315 // 00316 // We tackle them as follows: 00317 // 1) we retry until we get the bus. we could have a "timeout" if we can not get it 00318 // which basically turns it in to a 2) 00319 // 2) on error, we use the standard error mechanisms to report/debug 00320 // 00321 // Therefore an I2C transaction should always complete. If it doesn't it is usually 00322 // because something is setup wrong (e.g. wiring), and we don't need to programatically 00323 // check for that 00324 00325 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { 00326 int count, status; 00327 00328 status = i2c_start(obj); 00329 00330 #if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) 00331 if ((status != 0x10) && (status != 0x08)) { 00332 i2c_stop(obj); 00333 return status; 00334 } 00335 #endif 00336 00337 status = i2c_do_write(obj, (address | 0x01), 1); 00338 #if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) 00339 if (status != 0x40) { 00340 #elif defined(TARGET_LPC812) 00341 if (status != 0x01) { 00342 #endif 00343 i2c_stop(obj); 00344 return status; 00345 } 00346 00347 // Read in all except last byte 00348 for (count = 0; count < (length - 1); count++) { 00349 int value = i2c_do_read(obj, 0); 00350 status = i2c_status(obj); 00351 #if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) 00352 if (status != 0x50) { 00353 #elif defined(TARGET_LPC812) 00354 if (status != 0x00) { 00355 #endif 00356 i2c_stop(obj); 00357 return status; 00358 } 00359 data[count] = (char) value; 00360 } 00361 00362 // read in last byte 00363 int value = i2c_do_read(obj, 1); 00364 status = i2c_status(obj); 00365 #if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) 00366 if (status != 0x58) { 00367 #elif defined(TARGET_LPC812) 00368 if (status != 0x01) { 00369 #endif 00370 i2c_stop(obj); 00371 return status; 00372 } 00373 00374 data[count] = (char) value; 00375 00376 // If not repeated start, send stop. 00377 if (stop) { 00378 i2c_stop(obj); 00379 } 00380 #if defined(TARGET_LPC812) 00381 else { 00382 repeated_start = 1; 00383 } 00384 #endif 00385 00386 return 0; 00387 } 00388 00389 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { 00390 int i, status; 00391 00392 status = i2c_start(obj); 00393 00394 #if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) 00395 if ((status != 0x10) && (status != 0x08)) { 00396 i2c_stop(obj); 00397 return status; 00398 } 00399 #endif 00400 00401 status = i2c_do_write(obj, (address & 0xFE), 1); 00402 #if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) 00403 if (status != 0x18) { 00404 #elif defined(TARGET_LPC812) 00405 if (status != 0x02) { 00406 #endif 00407 i2c_stop(obj); 00408 return status; 00409 } 00410 00411 for (i=0; i<length; i++) { 00412 status = i2c_do_write(obj, data[i], 0); 00413 #if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) 00414 if(status != 0x28) { 00415 #elif defined(TARGET_LPC812) 00416 if (status != 0x02) { 00417 #endif 00418 i2c_stop(obj); 00419 return status; 00420 } 00421 } 00422 00423 #if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) 00424 i2c_clear_SI(obj); 00425 #endif 00426 00427 // If not repeated start, send stop. 00428 if (stop) { 00429 i2c_stop(obj); 00430 } 00431 #if defined(TARGET_LPC812) 00432 else { 00433 repeated_start = 1; 00434 } 00435 #endif 00436 00437 return 0; 00438 } 00439 00440 void i2c_reset(i2c_t *obj) { 00441 i2c_stop(obj); 00442 } 00443 00444 int i2c_byte_read(i2c_t *obj, int last) { 00445 return (i2c_do_read(obj, last) & 0xFF); 00446 } 00447 00448 int i2c_byte_write(i2c_t *obj, int data) { 00449 int ack; 00450 int status = i2c_do_write(obj, (data & 0xFF), 0); 00451 00452 switch(status) { 00453 #if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) 00454 case 0x18: case 0x28: // Master transmit ACKs 00455 ack = 1; 00456 break; 00457 case 0x40: // Master receive address transmitted ACK 00458 ack = 1; 00459 break; 00460 case 0xB8: // Slave transmit ACK 00461 ack = 1; 00462 break; 00463 #elif defined(TARGET_LPC812) 00464 case 2: 00465 ack = 1; 00466 break; 00467 #endif 00468 default: 00469 ack = 0; 00470 break; 00471 } 00472 00473 return ack; 00474 } 00475 00476 #if DEVICE_I2CSLAVE 00477 void i2c_slave_mode(i2c_t *obj, int enable_slave) { 00478 if (enable_slave != 0) { 00479 i2c_conclr(obj, 1, 1, 1, 0); 00480 i2c_conset(obj, 0, 0, 0, 1); 00481 } else { 00482 i2c_conclr(obj, 1, 1, 1, 1); 00483 } 00484 } 00485 00486 int i2c_slave_receive(i2c_t *obj) { 00487 int status; 00488 int retval; 00489 00490 status = i2c_status(obj); 00491 switch(status) { 00492 case 0x60: retval = 3; break; 00493 case 0x70: retval = 2; break; 00494 case 0xA8: retval = 1; break; 00495 default : retval = 0; break; 00496 } 00497 00498 return(retval); 00499 } 00500 00501 int i2c_slave_read(i2c_t *obj, char *data, int length) { 00502 int count = 0; 00503 int status; 00504 00505 do { 00506 i2c_clear_SI(obj); 00507 i2c_wait_SI(obj); 00508 status = i2c_status(obj); 00509 if((status == 0x80) || (status == 0x90)) { 00510 data[count] = I2C_DAT(obj) & 0xFF; 00511 } 00512 count++; 00513 } while (((status == 0x80) || (status == 0x90) || 00514 (status == 0x060) || (status == 0x70)) && (count < length)); 00515 00516 if(status != 0xA0) { 00517 i2c_stop(obj); 00518 } 00519 00520 i2c_clear_SI(obj); 00521 00522 return (count - 1); 00523 } 00524 00525 int i2c_slave_write(i2c_t *obj, const char *data, int length) { 00526 int count = 0; 00527 int status; 00528 00529 if(length <= 0) { 00530 return(0); 00531 } 00532 00533 do { 00534 status = i2c_do_write(obj, data[count], 0); 00535 count++; 00536 } while ((count < length) && (status == 0xB8)); 00537 00538 if((status != 0xC0) && (status != 0xC8)) { 00539 i2c_stop(obj); 00540 } 00541 00542 i2c_clear_SI(obj); 00543 00544 return(count); 00545 } 00546 00547 void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) { 00548 uint32_t addr; 00549 00550 if ((idx >= 0) && (idx <= 3)) { 00551 addr = ((uint32_t)obj->i2c) + I2C_addr_offset[0][idx]; 00552 *((uint32_t *) addr) = address & 0xFF; 00553 #ifdef TARGET_LPC1768 00554 addr = ((uint32_t)obj->i2c) + I2C_addr_offset[1][idx]; 00555 *((uint32_t *) addr) = mask & 0xFE; 00556 #endif 00557 } 00558 } 00559 #endif 00560 00561 #endif
Generated on Thu Jul 14 2022 07:43:04 by
1.7.2