mbed SDK library sources

Fork of mbed-src by mbed official

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Mon Nov 11 13:30:09 2013 +0000
Revision:
46:bebbbd80dd87
Synchronized with git revision b2733e9b9af906952b295cd6abcf916bf79780ab

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 46:bebbbd80dd87 1 /* mbed Microcontroller Library
mbed_official 46:bebbbd80dd87 2 * Copyright (c) 2006-2013 ARM Limited
mbed_official 46:bebbbd80dd87 3 *
mbed_official 46:bebbbd80dd87 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 46:bebbbd80dd87 5 * you may not use this file except in compliance with the License.
mbed_official 46:bebbbd80dd87 6 * You may obtain a copy of the License at
mbed_official 46:bebbbd80dd87 7 *
mbed_official 46:bebbbd80dd87 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 46:bebbbd80dd87 9 *
mbed_official 46:bebbbd80dd87 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 46:bebbbd80dd87 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 46:bebbbd80dd87 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 46:bebbbd80dd87 13 * See the License for the specific language governing permissions and
mbed_official 46:bebbbd80dd87 14 * limitations under the License.
mbed_official 46:bebbbd80dd87 15 */
mbed_official 46:bebbbd80dd87 16 #include "i2c_api.h"
mbed_official 46:bebbbd80dd87 17 #include "cmsis.h"
mbed_official 46:bebbbd80dd87 18 #include "pinmap.h"
mbed_official 46:bebbbd80dd87 19 #include "error.h"
mbed_official 46:bebbbd80dd87 20
mbed_official 46:bebbbd80dd87 21 static const SWM_Map SWM_I2C_SDA[] = {
mbed_official 46:bebbbd80dd87 22 {7, 24},
mbed_official 46:bebbbd80dd87 23 };
mbed_official 46:bebbbd80dd87 24
mbed_official 46:bebbbd80dd87 25 static const SWM_Map SWM_I2C_SCL[] = {
mbed_official 46:bebbbd80dd87 26 {8, 0},
mbed_official 46:bebbbd80dd87 27 };
mbed_official 46:bebbbd80dd87 28
mbed_official 46:bebbbd80dd87 29 static uint8_t repeated_start = 0;
mbed_official 46:bebbbd80dd87 30
mbed_official 46:bebbbd80dd87 31 #define I2C_DAT(x) (x->i2c->MSTDAT)
mbed_official 46:bebbbd80dd87 32 #define I2C_STAT(x) ((x->i2c->STAT >> 1) & (0x07))
mbed_official 46:bebbbd80dd87 33
mbed_official 46:bebbbd80dd87 34 static inline int i2c_status(i2c_t *obj) {
mbed_official 46:bebbbd80dd87 35 return I2C_STAT(obj);
mbed_official 46:bebbbd80dd87 36 }
mbed_official 46:bebbbd80dd87 37
mbed_official 46:bebbbd80dd87 38 // Wait until the Serial Interrupt (SI) is set
mbed_official 46:bebbbd80dd87 39 static int i2c_wait_SI(i2c_t *obj) {
mbed_official 46:bebbbd80dd87 40 int timeout = 0;
mbed_official 46:bebbbd80dd87 41 while (!(obj->i2c->STAT & (1 << 0))) {
mbed_official 46:bebbbd80dd87 42 timeout++;
mbed_official 46:bebbbd80dd87 43 if (timeout > 100000) return -1;
mbed_official 46:bebbbd80dd87 44 }
mbed_official 46:bebbbd80dd87 45 return 0;
mbed_official 46:bebbbd80dd87 46 }
mbed_official 46:bebbbd80dd87 47
mbed_official 46:bebbbd80dd87 48 static inline void i2c_interface_enable(i2c_t *obj) {
mbed_official 46:bebbbd80dd87 49 obj->i2c->CFG |= (1 << 0);
mbed_official 46:bebbbd80dd87 50 }
mbed_official 46:bebbbd80dd87 51
mbed_official 46:bebbbd80dd87 52 static inline void i2c_power_enable(i2c_t *obj) {
mbed_official 46:bebbbd80dd87 53 LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5);
mbed_official 46:bebbbd80dd87 54 LPC_SYSCON->PRESETCTRL &= ~(0x1<<6);
mbed_official 46:bebbbd80dd87 55 LPC_SYSCON->PRESETCTRL |= (0x1<<6);
mbed_official 46:bebbbd80dd87 56 }
mbed_official 46:bebbbd80dd87 57
mbed_official 46:bebbbd80dd87 58 void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
mbed_official 46:bebbbd80dd87 59 obj->i2c = (LPC_I2C_TypeDef *)LPC_I2C;
mbed_official 46:bebbbd80dd87 60
mbed_official 46:bebbbd80dd87 61 const SWM_Map *swm;
mbed_official 46:bebbbd80dd87 62 uint32_t regVal;
mbed_official 46:bebbbd80dd87 63
mbed_official 46:bebbbd80dd87 64 swm = &SWM_I2C_SDA[0];
mbed_official 46:bebbbd80dd87 65 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
mbed_official 46:bebbbd80dd87 66 LPC_SWM->PINASSIGN[swm->n] = regVal | (sda << swm->offset);
mbed_official 46:bebbbd80dd87 67
mbed_official 46:bebbbd80dd87 68 swm = &SWM_I2C_SCL[0];
mbed_official 46:bebbbd80dd87 69 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
mbed_official 46:bebbbd80dd87 70 LPC_SWM->PINASSIGN[swm->n] = regVal | (scl << swm->offset);
mbed_official 46:bebbbd80dd87 71
mbed_official 46:bebbbd80dd87 72 // enable power
mbed_official 46:bebbbd80dd87 73 i2c_power_enable(obj);
mbed_official 46:bebbbd80dd87 74 // set default frequency at 100k
mbed_official 46:bebbbd80dd87 75 i2c_frequency(obj, 100000);
mbed_official 46:bebbbd80dd87 76 i2c_interface_enable(obj);
mbed_official 46:bebbbd80dd87 77 }
mbed_official 46:bebbbd80dd87 78
mbed_official 46:bebbbd80dd87 79 inline int i2c_start(i2c_t *obj) {
mbed_official 46:bebbbd80dd87 80 int status = 0;
mbed_official 46:bebbbd80dd87 81 if (repeated_start) {
mbed_official 46:bebbbd80dd87 82 obj->i2c->MSTCTL = (1 << 1) | (1 << 0);
mbed_official 46:bebbbd80dd87 83 repeated_start = 0;
mbed_official 46:bebbbd80dd87 84 } else {
mbed_official 46:bebbbd80dd87 85 obj->i2c->MSTCTL = (1 << 1);
mbed_official 46:bebbbd80dd87 86 }
mbed_official 46:bebbbd80dd87 87 return status;
mbed_official 46:bebbbd80dd87 88 }
mbed_official 46:bebbbd80dd87 89
mbed_official 46:bebbbd80dd87 90 inline int i2c_stop(i2c_t *obj) {
mbed_official 46:bebbbd80dd87 91 int timeout = 0;
mbed_official 46:bebbbd80dd87 92
mbed_official 46:bebbbd80dd87 93 obj->i2c->MSTCTL = (1 << 2) | (1 << 0);
mbed_official 46:bebbbd80dd87 94 while ((obj->i2c->STAT & ((1 << 0) | (7 << 1))) != ((1 << 0) | (0 << 1))) {
mbed_official 46:bebbbd80dd87 95 timeout ++;
mbed_official 46:bebbbd80dd87 96 if (timeout > 100000) return 1;
mbed_official 46:bebbbd80dd87 97 }
mbed_official 46:bebbbd80dd87 98
mbed_official 46:bebbbd80dd87 99 return 0;
mbed_official 46:bebbbd80dd87 100 }
mbed_official 46:bebbbd80dd87 101
mbed_official 46:bebbbd80dd87 102
mbed_official 46:bebbbd80dd87 103 static inline int i2c_do_write(i2c_t *obj, int value, uint8_t addr) {
mbed_official 46:bebbbd80dd87 104 // write the data
mbed_official 46:bebbbd80dd87 105 I2C_DAT(obj) = value;
mbed_official 46:bebbbd80dd87 106
mbed_official 46:bebbbd80dd87 107 if (!addr)
mbed_official 46:bebbbd80dd87 108 obj->i2c->MSTCTL = (1 << 0);
mbed_official 46:bebbbd80dd87 109
mbed_official 46:bebbbd80dd87 110 // wait and return status
mbed_official 46:bebbbd80dd87 111 i2c_wait_SI(obj);
mbed_official 46:bebbbd80dd87 112 return i2c_status(obj);
mbed_official 46:bebbbd80dd87 113 }
mbed_official 46:bebbbd80dd87 114
mbed_official 46:bebbbd80dd87 115 static inline int i2c_do_read(i2c_t *obj, int last) {
mbed_official 46:bebbbd80dd87 116 // wait for it to arrive
mbed_official 46:bebbbd80dd87 117 i2c_wait_SI(obj);
mbed_official 46:bebbbd80dd87 118 if (!last)
mbed_official 46:bebbbd80dd87 119 obj->i2c->MSTCTL = (1 << 0);
mbed_official 46:bebbbd80dd87 120
mbed_official 46:bebbbd80dd87 121 // return the data
mbed_official 46:bebbbd80dd87 122 return (I2C_DAT(obj) & 0xFF);
mbed_official 46:bebbbd80dd87 123 }
mbed_official 46:bebbbd80dd87 124
mbed_official 46:bebbbd80dd87 125 void i2c_frequency(i2c_t *obj, int hz) {
mbed_official 46:bebbbd80dd87 126 // No peripheral clock divider on the M0
mbed_official 46:bebbbd80dd87 127 uint32_t PCLK = SystemCoreClock;
mbed_official 46:bebbbd80dd87 128
mbed_official 46:bebbbd80dd87 129 uint32_t clkdiv = PCLK / (hz * 4) - 1;
mbed_official 46:bebbbd80dd87 130
mbed_official 46:bebbbd80dd87 131 obj->i2c->DIV = clkdiv;
mbed_official 46:bebbbd80dd87 132 obj->i2c->MSTTIME = 0;
mbed_official 46:bebbbd80dd87 133 }
mbed_official 46:bebbbd80dd87 134
mbed_official 46:bebbbd80dd87 135 // The I2C does a read or a write as a whole operation
mbed_official 46:bebbbd80dd87 136 // There are two types of error conditions it can encounter
mbed_official 46:bebbbd80dd87 137 // 1) it can not obtain the bus
mbed_official 46:bebbbd80dd87 138 // 2) it gets error responses at part of the transmission
mbed_official 46:bebbbd80dd87 139 //
mbed_official 46:bebbbd80dd87 140 // We tackle them as follows:
mbed_official 46:bebbbd80dd87 141 // 1) we retry until we get the bus. we could have a "timeout" if we can not get it
mbed_official 46:bebbbd80dd87 142 // which basically turns it in to a 2)
mbed_official 46:bebbbd80dd87 143 // 2) on error, we use the standard error mechanisms to report/debug
mbed_official 46:bebbbd80dd87 144 //
mbed_official 46:bebbbd80dd87 145 // Therefore an I2C transaction should always complete. If it doesn't it is usually
mbed_official 46:bebbbd80dd87 146 // because something is setup wrong (e.g. wiring), and we don't need to programatically
mbed_official 46:bebbbd80dd87 147 // check for that
mbed_official 46:bebbbd80dd87 148
mbed_official 46:bebbbd80dd87 149 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
mbed_official 46:bebbbd80dd87 150 int count, status;
mbed_official 46:bebbbd80dd87 151
mbed_official 46:bebbbd80dd87 152 i2c_start(obj);
mbed_official 46:bebbbd80dd87 153
mbed_official 46:bebbbd80dd87 154 status = i2c_do_write(obj, (address | 0x01), 1);
mbed_official 46:bebbbd80dd87 155 if (status != 0x01) {
mbed_official 46:bebbbd80dd87 156 i2c_stop(obj);
mbed_official 46:bebbbd80dd87 157 return I2C_ERROR_NO_SLAVE;
mbed_official 46:bebbbd80dd87 158 }
mbed_official 46:bebbbd80dd87 159
mbed_official 46:bebbbd80dd87 160 // Read in all except last byte
mbed_official 46:bebbbd80dd87 161 for (count = 0; count < (length - 1); count++) {
mbed_official 46:bebbbd80dd87 162 int value = i2c_do_read(obj, 0);
mbed_official 46:bebbbd80dd87 163 status = i2c_status(obj);
mbed_official 46:bebbbd80dd87 164 if (status != 0x00) {
mbed_official 46:bebbbd80dd87 165 i2c_stop(obj);
mbed_official 46:bebbbd80dd87 166 return count;
mbed_official 46:bebbbd80dd87 167 }
mbed_official 46:bebbbd80dd87 168 data[count] = (char) value;
mbed_official 46:bebbbd80dd87 169 }
mbed_official 46:bebbbd80dd87 170
mbed_official 46:bebbbd80dd87 171 // read in last byte
mbed_official 46:bebbbd80dd87 172 int value = i2c_do_read(obj, 1);
mbed_official 46:bebbbd80dd87 173 status = i2c_status(obj);
mbed_official 46:bebbbd80dd87 174 if (status != 0x01) {
mbed_official 46:bebbbd80dd87 175 i2c_stop(obj);
mbed_official 46:bebbbd80dd87 176 return length - 1;
mbed_official 46:bebbbd80dd87 177 }
mbed_official 46:bebbbd80dd87 178
mbed_official 46:bebbbd80dd87 179 data[count] = (char) value;
mbed_official 46:bebbbd80dd87 180
mbed_official 46:bebbbd80dd87 181 // If not repeated start, send stop.
mbed_official 46:bebbbd80dd87 182 if (stop) {
mbed_official 46:bebbbd80dd87 183 i2c_stop(obj);
mbed_official 46:bebbbd80dd87 184 } else {
mbed_official 46:bebbbd80dd87 185 repeated_start = 1;
mbed_official 46:bebbbd80dd87 186 }
mbed_official 46:bebbbd80dd87 187
mbed_official 46:bebbbd80dd87 188 return length;
mbed_official 46:bebbbd80dd87 189 }
mbed_official 46:bebbbd80dd87 190
mbed_official 46:bebbbd80dd87 191 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
mbed_official 46:bebbbd80dd87 192 int i, status;
mbed_official 46:bebbbd80dd87 193
mbed_official 46:bebbbd80dd87 194 i2c_start(obj);
mbed_official 46:bebbbd80dd87 195
mbed_official 46:bebbbd80dd87 196 status = i2c_do_write(obj, (address & 0xFE), 1);
mbed_official 46:bebbbd80dd87 197 if (status != 0x02) {
mbed_official 46:bebbbd80dd87 198 i2c_stop(obj);
mbed_official 46:bebbbd80dd87 199 return I2C_ERROR_NO_SLAVE;
mbed_official 46:bebbbd80dd87 200 }
mbed_official 46:bebbbd80dd87 201
mbed_official 46:bebbbd80dd87 202 for (i=0; i<length; i++) {
mbed_official 46:bebbbd80dd87 203 status = i2c_do_write(obj, data[i], 0);
mbed_official 46:bebbbd80dd87 204 if (status != 0x02) {
mbed_official 46:bebbbd80dd87 205 i2c_stop(obj);
mbed_official 46:bebbbd80dd87 206 return i;
mbed_official 46:bebbbd80dd87 207 }
mbed_official 46:bebbbd80dd87 208 }
mbed_official 46:bebbbd80dd87 209
mbed_official 46:bebbbd80dd87 210 // If not repeated start, send stop.
mbed_official 46:bebbbd80dd87 211 if (stop) {
mbed_official 46:bebbbd80dd87 212 i2c_stop(obj);
mbed_official 46:bebbbd80dd87 213 } else {
mbed_official 46:bebbbd80dd87 214 repeated_start = 1;
mbed_official 46:bebbbd80dd87 215 }
mbed_official 46:bebbbd80dd87 216
mbed_official 46:bebbbd80dd87 217 return length;
mbed_official 46:bebbbd80dd87 218 }
mbed_official 46:bebbbd80dd87 219
mbed_official 46:bebbbd80dd87 220 void i2c_reset(i2c_t *obj) {
mbed_official 46:bebbbd80dd87 221 i2c_stop(obj);
mbed_official 46:bebbbd80dd87 222 }
mbed_official 46:bebbbd80dd87 223
mbed_official 46:bebbbd80dd87 224 int i2c_byte_read(i2c_t *obj, int last) {
mbed_official 46:bebbbd80dd87 225 return (i2c_do_read(obj, last) & 0xFF);
mbed_official 46:bebbbd80dd87 226 }
mbed_official 46:bebbbd80dd87 227
mbed_official 46:bebbbd80dd87 228 int i2c_byte_write(i2c_t *obj, int data) {
mbed_official 46:bebbbd80dd87 229 int ack;
mbed_official 46:bebbbd80dd87 230 int status = i2c_do_write(obj, (data & 0xFF), 0);
mbed_official 46:bebbbd80dd87 231
mbed_official 46:bebbbd80dd87 232 switch(status) {
mbed_official 46:bebbbd80dd87 233 case 2:
mbed_official 46:bebbbd80dd87 234 ack = 1;
mbed_official 46:bebbbd80dd87 235 break;
mbed_official 46:bebbbd80dd87 236 default:
mbed_official 46:bebbbd80dd87 237 ack = 0;
mbed_official 46:bebbbd80dd87 238 break;
mbed_official 46:bebbbd80dd87 239 }
mbed_official 46:bebbbd80dd87 240
mbed_official 46:bebbbd80dd87 241 return ack;
mbed_official 46:bebbbd80dd87 242 }