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.
Fork of mbed-src by
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 }
Generated on Tue Jul 12 2022 13:47:01 by
 1.7.2
 1.7.2 
    