mbed library sources

Dependents:   frdm_kl05z_gpio_test

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Wed May 07 13:30:07 2014 +0100
Revision:
182:242346c42295
Parent:
117:e0a7df0a9a56
Child:
227:7bd0639b8911
Synchronized with git revision 06edaf703a558d25d9e05e38adc502c6474a5d61

Full URL: https://github.com/mbedmicro/mbed/commit/06edaf703a558d25d9e05e38adc502c6474a5d61/

increase timeout for slow I2C slaves that make use of extensive clock stretching

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 103:9b881da47c92 1 /* mbed Microcontroller Library
mbed_official 103:9b881da47c92 2 * Copyright (c) 2006-2013 ARM Limited
mbed_official 103:9b881da47c92 3 *
mbed_official 103:9b881da47c92 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 103:9b881da47c92 5 * you may not use this file except in compliance with the License.
mbed_official 103:9b881da47c92 6 * You may obtain a copy of the License at
mbed_official 103:9b881da47c92 7 *
mbed_official 103:9b881da47c92 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 103:9b881da47c92 9 *
mbed_official 103:9b881da47c92 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 103:9b881da47c92 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 103:9b881da47c92 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 103:9b881da47c92 13 * See the License for the specific language governing permissions and
mbed_official 103:9b881da47c92 14 * limitations under the License.
mbed_official 103:9b881da47c92 15 */
mbed_official 103:9b881da47c92 16
mbed_official 103:9b881da47c92 17 #include "i2c_api.h"
mbed_official 103:9b881da47c92 18 #include "cmsis.h"
mbed_official 103:9b881da47c92 19 #include "pinmap.h"
mbed_official 103:9b881da47c92 20 #include "error.h"
mbed_official 103:9b881da47c92 21
mbed_official 103:9b881da47c92 22 static uint8_t repeated_start = 0;
mbed_official 103:9b881da47c92 23
mbed_official 103:9b881da47c92 24 #define I2C_STAT(x) ((LPC_I2C0->STAT >> 1) & (0x07))
mbed_official 103:9b881da47c92 25
mbed_official 103:9b881da47c92 26 static inline int i2c_status(i2c_t *obj) {
mbed_official 103:9b881da47c92 27 return I2C_STAT(obj);
mbed_official 103:9b881da47c92 28 }
mbed_official 103:9b881da47c92 29
mbed_official 103:9b881da47c92 30 // Wait until the Serial Interrupt (SI) is set
mbed_official 103:9b881da47c92 31 static int i2c_wait_SI(i2c_t *obj) {
mbed_official 117:e0a7df0a9a56 32 volatile int timeout = 0;
mbed_official 103:9b881da47c92 33 while (!(LPC_I2C0->STAT & (1 << 0))) {
mbed_official 103:9b881da47c92 34 timeout++;
mbed_official 103:9b881da47c92 35 if (timeout > 100000) return -1;
mbed_official 103:9b881da47c92 36 }
mbed_official 103:9b881da47c92 37 return 0;
mbed_official 103:9b881da47c92 38 }
mbed_official 103:9b881da47c92 39
mbed_official 103:9b881da47c92 40 static inline void i2c_interface_enable(i2c_t *obj) {
mbed_official 103:9b881da47c92 41 LPC_I2C0->CFG |= (1 << 0);
mbed_official 103:9b881da47c92 42 }
mbed_official 103:9b881da47c92 43
mbed_official 117:e0a7df0a9a56 44 void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
mbed_official 117:e0a7df0a9a56 45 if ((sda != P0_23) | (scl != P0_22)) {
mbed_official 117:e0a7df0a9a56 46 error("I2C pin mapping failed");
mbed_official 117:e0a7df0a9a56 47 }
mbed_official 117:e0a7df0a9a56 48
mbed_official 103:9b881da47c92 49 // Enables clock for I2C0
mbed_official 117:e0a7df0a9a56 50 LPC_SYSCON->SYSAHBCLKCTRL1 |= (1 << 13);
mbed_official 103:9b881da47c92 51
mbed_official 117:e0a7df0a9a56 52 LPC_SYSCON->PRESETCTRL1 |= (1 << 13);
mbed_official 117:e0a7df0a9a56 53 LPC_SYSCON->PRESETCTRL1 &= ~(1 << 13);
mbed_official 103:9b881da47c92 54
mbed_official 103:9b881da47c92 55 // pin enable
mbed_official 103:9b881da47c92 56 LPC_SWM->PINENABLE1 &= ~(0x3 << 3);
mbed_official 117:e0a7df0a9a56 57
mbed_official 117:e0a7df0a9a56 58 // set default frequency at 100kHz
mbed_official 103:9b881da47c92 59 i2c_frequency(obj, 100000);
mbed_official 103:9b881da47c92 60 i2c_interface_enable(obj);
mbed_official 103:9b881da47c92 61 }
mbed_official 103:9b881da47c92 62
mbed_official 103:9b881da47c92 63 inline int i2c_start(i2c_t *obj) {
mbed_official 103:9b881da47c92 64 int status = 0;
mbed_official 103:9b881da47c92 65 if (repeated_start) {
mbed_official 103:9b881da47c92 66 LPC_I2C0->MSTCTL = (1 << 1) | (1 << 0);
mbed_official 103:9b881da47c92 67 repeated_start = 0;
mbed_official 103:9b881da47c92 68 } else {
mbed_official 103:9b881da47c92 69 LPC_I2C0->MSTCTL = (1 << 1);
mbed_official 103:9b881da47c92 70 }
mbed_official 103:9b881da47c92 71 return status;
mbed_official 103:9b881da47c92 72 }
mbed_official 103:9b881da47c92 73
mbed_official 103:9b881da47c92 74 inline int i2c_stop(i2c_t *obj) {
mbed_official 117:e0a7df0a9a56 75 volatile int timeout = 0;
mbed_official 103:9b881da47c92 76
mbed_official 103:9b881da47c92 77 LPC_I2C0->MSTCTL = (1 << 2) | (1 << 0);
mbed_official 103:9b881da47c92 78 while ((LPC_I2C0->STAT & ((1 << 0) | (7 << 1))) != ((1 << 0) | (0 << 1))) {
mbed_official 103:9b881da47c92 79 timeout ++;
mbed_official 103:9b881da47c92 80 if (timeout > 100000) return 1;
mbed_official 103:9b881da47c92 81 }
mbed_official 103:9b881da47c92 82
mbed_official 103:9b881da47c92 83 return 0;
mbed_official 103:9b881da47c92 84 }
mbed_official 103:9b881da47c92 85
mbed_official 103:9b881da47c92 86
mbed_official 103:9b881da47c92 87 static inline int i2c_do_write(i2c_t *obj, int value, uint8_t addr) {
mbed_official 103:9b881da47c92 88 // write the data
mbed_official 103:9b881da47c92 89 LPC_I2C0->MSTDAT = value;
mbed_official 103:9b881da47c92 90
mbed_official 103:9b881da47c92 91 if (!addr)
mbed_official 103:9b881da47c92 92 LPC_I2C0->MSTCTL = (1 << 0);
mbed_official 103:9b881da47c92 93
mbed_official 103:9b881da47c92 94 // wait and return status
mbed_official 103:9b881da47c92 95 i2c_wait_SI(obj);
mbed_official 103:9b881da47c92 96 return i2c_status(obj);
mbed_official 103:9b881da47c92 97 }
mbed_official 103:9b881da47c92 98
mbed_official 103:9b881da47c92 99 static inline int i2c_do_read(i2c_t *obj, int last) {
mbed_official 103:9b881da47c92 100 // wait for it to arrive
mbed_official 103:9b881da47c92 101 i2c_wait_SI(obj);
mbed_official 103:9b881da47c92 102 if (!last)
mbed_official 103:9b881da47c92 103 LPC_I2C0->MSTCTL = (1 << 0);
mbed_official 103:9b881da47c92 104
mbed_official 103:9b881da47c92 105 // return the data
mbed_official 103:9b881da47c92 106 return (LPC_I2C0->MSTDAT & 0xFF);
mbed_official 103:9b881da47c92 107 }
mbed_official 103:9b881da47c92 108
mbed_official 103:9b881da47c92 109 void i2c_frequency(i2c_t *obj, int hz) {
mbed_official 103:9b881da47c92 110 // No peripheral clock divider on the M0
mbed_official 103:9b881da47c92 111 uint32_t PCLK = SystemCoreClock;
mbed_official 103:9b881da47c92 112 uint32_t clkdiv = PCLK / (hz * 4) - 1;
mbed_official 103:9b881da47c92 113
mbed_official 103:9b881da47c92 114 LPC_I2C0->DIV = clkdiv;
mbed_official 103:9b881da47c92 115 LPC_I2C0->MSTTIME = 0;
mbed_official 103:9b881da47c92 116 }
mbed_official 103:9b881da47c92 117
mbed_official 103:9b881da47c92 118 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
mbed_official 103:9b881da47c92 119 int count, status;
mbed_official 103:9b881da47c92 120
mbed_official 103:9b881da47c92 121 i2c_start(obj);
mbed_official 103:9b881da47c92 122
mbed_official 103:9b881da47c92 123 LPC_I2C0->MSTDAT = (address | 0x01);
mbed_official 103:9b881da47c92 124 LPC_I2C0->MSTCTL |= 0x20;
mbed_official 117:e0a7df0a9a56 125 if (i2c_wait_SI(obj) == -1)
mbed_official 117:e0a7df0a9a56 126 return -1;
mbed_official 117:e0a7df0a9a56 127
mbed_official 103:9b881da47c92 128 status = ((LPC_I2C0->STAT >> 1) & (0x07));
mbed_official 103:9b881da47c92 129 if (status != 0x01) {
mbed_official 103:9b881da47c92 130 i2c_stop(obj);
mbed_official 103:9b881da47c92 131 return I2C_ERROR_NO_SLAVE;
mbed_official 103:9b881da47c92 132 }
mbed_official 103:9b881da47c92 133
mbed_official 103:9b881da47c92 134 // Read in all except last byte
mbed_official 103:9b881da47c92 135 for (count = 0; count < (length - 1); count++) {
mbed_official 117:e0a7df0a9a56 136 if (i2c_wait_SI(obj) == -1)
mbed_official 117:e0a7df0a9a56 137 return -1;
mbed_official 117:e0a7df0a9a56 138 LPC_I2C0->MSTCTL = (1 << 0);
mbed_official 117:e0a7df0a9a56 139 data[count] = (LPC_I2C0->MSTDAT & 0xFF);
mbed_official 117:e0a7df0a9a56 140 status = ((LPC_I2C0->STAT >> 1) & (0x07));
mbed_official 182:242346c42295 141 if (status != 0x01) {
mbed_official 103:9b881da47c92 142 i2c_stop(obj);
mbed_official 103:9b881da47c92 143 return count;
mbed_official 103:9b881da47c92 144 }
mbed_official 103:9b881da47c92 145 }
mbed_official 103:9b881da47c92 146
mbed_official 103:9b881da47c92 147 // read in last byte
mbed_official 117:e0a7df0a9a56 148 if (i2c_wait_SI(obj) == -1)
mbed_official 117:e0a7df0a9a56 149 return -1;
mbed_official 117:e0a7df0a9a56 150
mbed_official 103:9b881da47c92 151 data[count] = (LPC_I2C0->MSTDAT & 0xFF);
mbed_official 103:9b881da47c92 152 status = i2c_status(obj);
mbed_official 103:9b881da47c92 153 if (status != 0x01) {
mbed_official 103:9b881da47c92 154 i2c_stop(obj);
mbed_official 103:9b881da47c92 155 return length - 1;
mbed_official 103:9b881da47c92 156 }
mbed_official 103:9b881da47c92 157 // If not repeated start, send stop.
mbed_official 103:9b881da47c92 158 if (stop) {
mbed_official 103:9b881da47c92 159 i2c_stop(obj);
mbed_official 103:9b881da47c92 160 } else {
mbed_official 103:9b881da47c92 161 repeated_start = 1;
mbed_official 103:9b881da47c92 162 }
mbed_official 103:9b881da47c92 163
mbed_official 103:9b881da47c92 164 return length;
mbed_official 103:9b881da47c92 165 }
mbed_official 103:9b881da47c92 166
mbed_official 103:9b881da47c92 167 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
mbed_official 103:9b881da47c92 168 int i, status;
mbed_official 103:9b881da47c92 169
mbed_official 103:9b881da47c92 170 i2c_start(obj);
mbed_official 103:9b881da47c92 171
mbed_official 103:9b881da47c92 172 LPC_I2C0->MSTDAT = (address & 0xFE);
mbed_official 103:9b881da47c92 173 LPC_I2C0->MSTCTL |= 0x20;
mbed_official 117:e0a7df0a9a56 174 if (i2c_wait_SI(obj) == -1)
mbed_official 117:e0a7df0a9a56 175 return -1;
mbed_official 117:e0a7df0a9a56 176
mbed_official 103:9b881da47c92 177 status = ((LPC_I2C0->STAT >> 1) & (0x07));
mbed_official 103:9b881da47c92 178 if (status != 0x02) {
mbed_official 103:9b881da47c92 179 i2c_stop(obj);
mbed_official 103:9b881da47c92 180 return I2C_ERROR_NO_SLAVE;
mbed_official 103:9b881da47c92 181 }
mbed_official 103:9b881da47c92 182
mbed_official 103:9b881da47c92 183 for (i=0; i<length; i++) {
mbed_official 103:9b881da47c92 184 LPC_I2C0->MSTDAT = data[i];
mbed_official 103:9b881da47c92 185 LPC_I2C0->MSTCTL = (1 << 0);
mbed_official 117:e0a7df0a9a56 186 if (i2c_wait_SI(obj) == -1)
mbed_official 117:e0a7df0a9a56 187 return -1;
mbed_official 117:e0a7df0a9a56 188
mbed_official 117:e0a7df0a9a56 189 status = ((LPC_I2C0->STAT >> 1) & (0x07));
mbed_official 103:9b881da47c92 190 if (status != 0x02) {
mbed_official 103:9b881da47c92 191 i2c_stop(obj);
mbed_official 103:9b881da47c92 192 return i;
mbed_official 103:9b881da47c92 193 }
mbed_official 103:9b881da47c92 194 }
mbed_official 103:9b881da47c92 195
mbed_official 103:9b881da47c92 196 // If not repeated start, send stop.
mbed_official 103:9b881da47c92 197 if (stop) {
mbed_official 103:9b881da47c92 198 i2c_stop(obj);
mbed_official 103:9b881da47c92 199 } else {
mbed_official 103:9b881da47c92 200 repeated_start = 1;
mbed_official 103:9b881da47c92 201 }
mbed_official 103:9b881da47c92 202
mbed_official 103:9b881da47c92 203 return length;
mbed_official 103:9b881da47c92 204 }
mbed_official 103:9b881da47c92 205
mbed_official 103:9b881da47c92 206 void i2c_reset(i2c_t *obj) {
mbed_official 103:9b881da47c92 207 i2c_stop(obj);
mbed_official 103:9b881da47c92 208 }
mbed_official 103:9b881da47c92 209
mbed_official 103:9b881da47c92 210 int i2c_byte_read(i2c_t *obj, int last) {
mbed_official 103:9b881da47c92 211 return (i2c_do_read(obj, last) & 0xFF);
mbed_official 103:9b881da47c92 212 }
mbed_official 103:9b881da47c92 213
mbed_official 103:9b881da47c92 214 int i2c_byte_write(i2c_t *obj, int data) {
mbed_official 117:e0a7df0a9a56 215 if (i2c_do_write(obj, (data & 0xFF), 0) == 2) {
mbed_official 117:e0a7df0a9a56 216 return 1;
mbed_official 117:e0a7df0a9a56 217 } else {
mbed_official 117:e0a7df0a9a56 218 return 0;
mbed_official 103:9b881da47c92 219 }
mbed_official 103:9b881da47c92 220 }