fix for mbed lib issue 3 (i2c problem) see also https://mbed.org/users/mbed_official/code/mbed/issues/3 affected implementations: LPC812, LPC11U24, LPC1768, LPC2368, LPC4088

Fork of mbed-src by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers i2c_api.c Source File

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 #include "cmsis.h"
00018 #include "pinmap.h"
00019 #include "error.h"
00020 
00021 static const SWM_Map SWM_I2C_SDA[] = {
00022     {7, 24},
00023 };
00024 
00025 static const SWM_Map SWM_I2C_SCL[] = {
00026     {8, 0},
00027 };
00028 
00029 static uint8_t repeated_start = 0;
00030 
00031 #define I2C_DAT(x)          (x->i2c->MSTDAT)
00032 #define I2C_STAT(x)         ((x->i2c->STAT >> 1) & (0x07))
00033 
00034 static inline int i2c_status(i2c_t *obj) {
00035     return I2C_STAT(obj);
00036 }
00037 
00038 // Wait until the Serial Interrupt (SI) is set
00039 static int i2c_wait_SI(i2c_t *obj) {
00040     int timeout = 0;
00041     while (!(obj->i2c->STAT & (1 << 0))) {
00042         timeout++;
00043         if (timeout > 100000) return -1;
00044     }
00045     return 0;
00046 }
00047 
00048 static inline void i2c_interface_enable(i2c_t *obj) {
00049     obj->i2c->CFG |= (1 << 0);
00050 }
00051 
00052 static inline void i2c_power_enable(i2c_t *obj) {
00053     LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5);    
00054     LPC_SYSCON->PRESETCTRL &= ~(0x1<<6);
00055     LPC_SYSCON->PRESETCTRL |= (0x1<<6);
00056 }
00057 
00058 void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
00059     obj->i2c = (LPC_I2C_TypeDef *)LPC_I2C;
00060     
00061     const SWM_Map *swm;
00062     uint32_t regVal;
00063     
00064     swm = &SWM_I2C_SDA[0];
00065     regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
00066     LPC_SWM->PINASSIGN[swm->n] = regVal |  (sda   << swm->offset);
00067     
00068     swm = &SWM_I2C_SCL[0];
00069     regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
00070     LPC_SWM->PINASSIGN[swm->n] = regVal |  (scl   << swm->offset);
00071     
00072     // enable power
00073     i2c_power_enable(obj);
00074     // set default frequency at 100k
00075     i2c_frequency(obj, 100000);
00076     i2c_interface_enable(obj);
00077 }
00078 
00079 inline int i2c_start(i2c_t *obj) {
00080     int status = 0;
00081     if (repeated_start) {
00082         obj->i2c->MSTCTL = (1 << 1) | (1 << 0);
00083         repeated_start = 0;
00084     } else {
00085         obj->i2c->MSTCTL = (1 << 1);
00086     }
00087     return status;
00088 }
00089 
00090 inline int i2c_stop(i2c_t *obj) {
00091     obj->i2c->MSTCTL = (1 << 2) | (1 << 0);
00092     while ((obj->i2c->STAT & ((1 << 0) | (7 << 1))) != ((1 << 0) | (0 << 1))){
00093         timeout++;
00094         if(timeout > 10000) return -1;
00095     }
00096     return 0;
00097 }
00098 
00099 
00100 static inline int i2c_do_write(i2c_t *obj, int value, uint8_t addr) {
00101     // write the data
00102     I2C_DAT(obj) = value;
00103     
00104     if (!addr)
00105         obj->i2c->MSTCTL = (1 << 0);
00106     
00107     // wait and return status
00108     i2c_wait_SI(obj);
00109     return i2c_status(obj);
00110 }
00111 
00112 static inline int i2c_do_read(i2c_t *obj, int last) {
00113     // wait for it to arrive
00114     i2c_wait_SI(obj);
00115     if (!last)
00116         obj->i2c->MSTCTL = (1 << 0);
00117     
00118     // return the data
00119     return (I2C_DAT(obj) & 0xFF);
00120 }
00121 
00122 void i2c_frequency(i2c_t *obj, int hz) {
00123     // No peripheral clock divider on the M0
00124     uint32_t PCLK = SystemCoreClock;
00125     
00126     uint32_t clkdiv = PCLK / (hz * 4) - 1;
00127     
00128     obj->i2c->DIV = clkdiv;
00129     obj->i2c->MSTTIME = 0;
00130 }
00131 
00132 // The I2C does a read or a write as a whole operation
00133 // There are two types of error conditions it can encounter
00134 //  1) it can not obtain the bus
00135 //  2) it gets error responses at part of the transmission
00136 //
00137 // We tackle them as follows:
00138 //  1) we retry until we get the bus. we could have a "timeout" if we can not get it
00139 //      which basically turns it in to a 2)
00140 //  2) on error, we use the standard error mechanisms to report/debug
00141 //
00142 // Therefore an I2C transaction should always complete. If it doesn't it is usually
00143 // because something is setup wrong (e.g. wiring), and we don't need to programatically
00144 // check for that
00145 
00146 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
00147     int count, status;
00148     
00149     i2c_start(obj);
00150     
00151     status = i2c_do_write(obj, (address | 0x01), 1);
00152     if (status != 0x01) {
00153         i2c_stop(obj);
00154         return status;
00155     }
00156     
00157     // Read in all except last byte
00158     for (count = 0; count < (length - 1); count++) {
00159         int value = i2c_do_read(obj, 0);
00160         status = i2c_status(obj);
00161         if (status != 0x00) {
00162             i2c_stop(obj);
00163             return status;
00164         }
00165         data[count] = (char) value;
00166     }
00167     
00168     // read in last byte
00169     int value = i2c_do_read(obj, 1);
00170     status = i2c_status(obj);
00171     if (status != 0x01) {
00172         i2c_stop(obj);
00173         return status;
00174     }
00175     
00176     data[count] = (char) value;
00177     
00178     // If not repeated start, send stop.
00179     if (stop) {
00180         i2c_stop(obj);
00181     } else {
00182         repeated_start = 1;
00183     }
00184     
00185     return 0;
00186 }
00187 
00188 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
00189     int i, status;
00190     
00191     i2c_start(obj);
00192     
00193     status = i2c_do_write(obj, (address & 0xFE), 1);
00194     if (status != 0x02) {
00195         i2c_stop(obj);
00196         return status;
00197     }
00198     
00199     for (i=0; i<length; i++) {
00200         status = i2c_do_write(obj, data[i], 0);
00201         if (status != 0x02) {
00202             i2c_stop(obj);
00203             return status;
00204         }
00205     }
00206     
00207     // If not repeated start, send stop.
00208     if (stop) {
00209         i2c_stop(obj);
00210     } else {
00211         repeated_start = 1;
00212     }
00213     
00214     return 0;
00215 }
00216 
00217 void i2c_reset(i2c_t *obj) {
00218     i2c_stop(obj);
00219 }
00220 
00221 int i2c_byte_read(i2c_t *obj, int last) {
00222     return (i2c_do_read(obj, last) & 0xFF);
00223 }
00224 
00225 int i2c_byte_write(i2c_t *obj, int data) {
00226     int ack;
00227     int status = i2c_do_write(obj, (data & 0xFF), 0);
00228     
00229     switch(status) {
00230         case 2:
00231             ack = 1;
00232             break;
00233         default:
00234             ack = 0;
00235             break;
00236     }
00237 
00238     return ack;
00239 }