mbed library sources

Dependents:   frdm_kl05z_gpio_test

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Mon Nov 11 13:30:09 2013 +0000
Revision:
46:bebbbd80dd87
Child:
227:7bd0639b8911
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 }