mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

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:
Tue Jul 29 19:00:07 2014 +0100
Revision:
268:402bcc0c870b
Parent:
251:de9a1e4ffd79
Child:
285:31249416b6f9
Synchronized with git revision 490d1a6606b3138f165c5edf2f2370ca616587c0

Full URL: https://github.com/mbedmicro/mbed/commit/490d1a6606b3138f165c5edf2f2370ca616587c0/

[LPC1114] Sleep fix + some device.h settings

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 20:4263a77256ae 1 /* mbed Microcontroller Library
bogdanm 20:4263a77256ae 2 * Copyright (c) 2006-2013 ARM Limited
bogdanm 20:4263a77256ae 3 *
bogdanm 20:4263a77256ae 4 * Licensed under the Apache License, Version 2.0 (the "License");
bogdanm 20:4263a77256ae 5 * you may not use this file except in compliance with the License.
bogdanm 20:4263a77256ae 6 * You may obtain a copy of the License at
bogdanm 20:4263a77256ae 7 *
bogdanm 20:4263a77256ae 8 * http://www.apache.org/licenses/LICENSE-2.0
bogdanm 20:4263a77256ae 9 *
bogdanm 20:4263a77256ae 10 * Unless required by applicable law or agreed to in writing, software
bogdanm 20:4263a77256ae 11 * distributed under the License is distributed on an "AS IS" BASIS,
bogdanm 20:4263a77256ae 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bogdanm 20:4263a77256ae 13 * See the License for the specific language governing permissions and
bogdanm 20:4263a77256ae 14 * limitations under the License.
bogdanm 20:4263a77256ae 15 */
mbed_official 227:7bd0639b8911 16 #include "mbed_assert.h"
bogdanm 20:4263a77256ae 17 #include "i2c_api.h"
bogdanm 20:4263a77256ae 18
bogdanm 20:4263a77256ae 19 #if DEVICE_I2C
bogdanm 20:4263a77256ae 20
bogdanm 20:4263a77256ae 21 #include "cmsis.h"
bogdanm 20:4263a77256ae 22 #include "pinmap.h"
mbed_official 251:de9a1e4ffd79 23 #include "error.h"
bogdanm 20:4263a77256ae 24
bogdanm 20:4263a77256ae 25 static const PinMap PinMap_I2C_SDA[] = {
bogdanm 20:4263a77256ae 26 {PB_7, I2C_1, STM_PIN_DATA(2, 4)},
bogdanm 20:4263a77256ae 27 {PB_9, I2C_1, STM_PIN_DATA(2, 4)},
bogdanm 20:4263a77256ae 28 {PB_11, I2C_2, STM_PIN_DATA(2, 4)},
bogdanm 20:4263a77256ae 29 {PC_9, I2C_3, STM_PIN_DATA(2, 4)},
bogdanm 20:4263a77256ae 30 {PF_0, I2C_2, STM_PIN_DATA(2, 4)},
bogdanm 20:4263a77256ae 31 {PH_5, I2C_2, STM_PIN_DATA(2, 4)},
bogdanm 20:4263a77256ae 32 {PH_8, I2C_3, STM_PIN_DATA(2, 4)},
bogdanm 20:4263a77256ae 33 {NC, NC, 0}
bogdanm 20:4263a77256ae 34 };
bogdanm 20:4263a77256ae 35
bogdanm 20:4263a77256ae 36 static const PinMap PinMap_I2C_SCL[] = {
bogdanm 20:4263a77256ae 37 {PA_8, I2C_3, STM_PIN_DATA(2, 4)},
bogdanm 20:4263a77256ae 38 {PB_6, I2C_1, STM_PIN_DATA(2, 4)},
bogdanm 20:4263a77256ae 39 {PB_8, I2C_1, STM_PIN_DATA(2, 4)},
bogdanm 20:4263a77256ae 40 {PB_10, I2C_2, STM_PIN_DATA(2, 4)},
bogdanm 20:4263a77256ae 41 {PF_1, I2C_2, STM_PIN_DATA(2, 4)},
bogdanm 20:4263a77256ae 42 {PH_4, I2C_2, STM_PIN_DATA(2, 4)},
bogdanm 20:4263a77256ae 43 {PH_7, I2C_3, STM_PIN_DATA(2, 4)},
bogdanm 20:4263a77256ae 44 {NC, NC, 0}
bogdanm 20:4263a77256ae 45 };
bogdanm 20:4263a77256ae 46
bogdanm 20:4263a77256ae 47 static const uint32_t I2C_addr_offset[2][4] = {
bogdanm 20:4263a77256ae 48 {0x0C, 0x20, 0x24, 0x28},
bogdanm 20:4263a77256ae 49 {0x30, 0x34, 0x38, 0x3C}
bogdanm 20:4263a77256ae 50 };
bogdanm 20:4263a77256ae 51
bogdanm 20:4263a77256ae 52
bogdanm 20:4263a77256ae 53 static inline void i2c_interface_enable(i2c_t *obj) {
bogdanm 20:4263a77256ae 54 obj->i2c->CR1 |= I2C_CR1_PE;
bogdanm 20:4263a77256ae 55 }
bogdanm 20:4263a77256ae 56
bogdanm 20:4263a77256ae 57 static inline void i2c_interface_disable(i2c_t *obj) {
bogdanm 20:4263a77256ae 58 obj->i2c->CR1 &= ~I2C_CR1_PE;
bogdanm 20:4263a77256ae 59 }
bogdanm 20:4263a77256ae 60
bogdanm 20:4263a77256ae 61
bogdanm 20:4263a77256ae 62 static inline void i2c_power_enable(i2c_t *obj) {
bogdanm 20:4263a77256ae 63 switch ((int)obj->i2c) {
bogdanm 20:4263a77256ae 64 case I2C_1:
bogdanm 20:4263a77256ae 65 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
bogdanm 20:4263a77256ae 66 RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
bogdanm 20:4263a77256ae 67 break;
bogdanm 20:4263a77256ae 68 case I2C_2:
bogdanm 20:4263a77256ae 69 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOFEN |
bogdanm 20:4263a77256ae 70 RCC_AHB1ENR_GPIOHEN;
bogdanm 20:4263a77256ae 71 RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;
bogdanm 20:4263a77256ae 72 break;
bogdanm 20:4263a77256ae 73 case I2C_3:
bogdanm 20:4263a77256ae 74 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOCEN |
bogdanm 20:4263a77256ae 75 RCC_AHB1ENR_GPIOHEN;
bogdanm 20:4263a77256ae 76 RCC->APB1ENR |= RCC_APB1ENR_I2C3EN;
bogdanm 20:4263a77256ae 77 break;
bogdanm 20:4263a77256ae 78 }
bogdanm 20:4263a77256ae 79 }
bogdanm 20:4263a77256ae 80
bogdanm 20:4263a77256ae 81 static inline void i2c_wait_status(i2c_t *obj, uint32_t sr1_mask,
bogdanm 20:4263a77256ae 82 uint32_t sr2_mask) {
bogdanm 20:4263a77256ae 83 while (!(((obj->i2c->SR1 & sr1_mask) >= sr1_mask) &&
bogdanm 20:4263a77256ae 84 ((obj->i2c->SR2 & sr2_mask) == sr2_mask)));
bogdanm 20:4263a77256ae 85 }
bogdanm 20:4263a77256ae 86
bogdanm 20:4263a77256ae 87 // Wait until the slave address has been acknowledged
bogdanm 20:4263a77256ae 88 static inline void i2c_wait_addr_tx(i2c_t *obj) {
bogdanm 20:4263a77256ae 89 uint32_t sr1_mask = I2C_SR1_ADDR | I2C_SR1_TXE;
bogdanm 20:4263a77256ae 90 uint32_t sr2_mask = I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA;
bogdanm 20:4263a77256ae 91 i2c_wait_status(obj, sr1_mask, sr2_mask);
bogdanm 20:4263a77256ae 92 }
bogdanm 20:4263a77256ae 93
bogdanm 20:4263a77256ae 94 // Wait until the slave address has been acknowledged
bogdanm 20:4263a77256ae 95 static inline void i2c_wait_addr_rx(i2c_t *obj) {
bogdanm 20:4263a77256ae 96 uint32_t sr1_mask = I2C_SR1_ADDR;
bogdanm 20:4263a77256ae 97 uint32_t sr2_mask = I2C_SR2_MSL | I2C_SR2_BUSY;
bogdanm 20:4263a77256ae 98 i2c_wait_status(obj, sr1_mask, sr2_mask);
bogdanm 20:4263a77256ae 99 }
bogdanm 20:4263a77256ae 100
bogdanm 20:4263a77256ae 101
bogdanm 20:4263a77256ae 102 // Wait until a byte has been sent
bogdanm 20:4263a77256ae 103 static inline void i2c_wait_send(i2c_t *obj) {
bogdanm 20:4263a77256ae 104 uint32_t sr1_mask = I2C_SR1_BTF | I2C_SR1_TXE;
bogdanm 20:4263a77256ae 105 uint32_t sr2_mask = I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA;
bogdanm 20:4263a77256ae 106 i2c_wait_status(obj, sr1_mask, sr2_mask);
bogdanm 20:4263a77256ae 107 }
bogdanm 20:4263a77256ae 108
bogdanm 20:4263a77256ae 109 // Wait until a byte has been received
bogdanm 20:4263a77256ae 110 static inline void i2c_wait_receive(i2c_t *obj) {
bogdanm 20:4263a77256ae 111 uint32_t sr1_mask = I2C_SR1_RXNE;
bogdanm 20:4263a77256ae 112 uint32_t sr2_mask = I2C_SR2_MSL | I2C_SR2_BUSY;
bogdanm 20:4263a77256ae 113 i2c_wait_status(obj, sr1_mask, sr2_mask);
bogdanm 20:4263a77256ae 114 }
bogdanm 20:4263a77256ae 115
bogdanm 20:4263a77256ae 116 // Wait until the start condition has been accepted
bogdanm 20:4263a77256ae 117 static inline void i2c_wait_start(i2c_t *obj) {
bogdanm 20:4263a77256ae 118 uint32_t sr1_mask = I2C_SR1_SB;
bogdanm 20:4263a77256ae 119 uint32_t sr2_mask = I2C_SR2_MSL | I2C_SR2_BUSY;
bogdanm 20:4263a77256ae 120 i2c_wait_status(obj, sr1_mask, sr2_mask);
bogdanm 20:4263a77256ae 121 }
bogdanm 20:4263a77256ae 122
bogdanm 20:4263a77256ae 123 void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
bogdanm 20:4263a77256ae 124 // determine the SPI to use
bogdanm 20:4263a77256ae 125 I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
bogdanm 20:4263a77256ae 126 I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
bogdanm 20:4263a77256ae 127 obj->i2c = (I2C_TypeDef *)pinmap_merge(i2c_sda, i2c_scl);
mbed_official 227:7bd0639b8911 128 MBED_ASSERT((int)obj->i2c != NC);
bogdanm 20:4263a77256ae 129
bogdanm 20:4263a77256ae 130 // enable power
bogdanm 20:4263a77256ae 131 i2c_power_enable(obj);
bogdanm 20:4263a77256ae 132
bogdanm 20:4263a77256ae 133 pinmap_pinout(sda, PinMap_I2C_SDA);
bogdanm 20:4263a77256ae 134 pinmap_pinout(scl, PinMap_I2C_SCL);
bogdanm 20:4263a77256ae 135
bogdanm 20:4263a77256ae 136 pin_mode(sda, OpenDrain);
bogdanm 20:4263a77256ae 137 pin_mode(scl, OpenDrain);
bogdanm 20:4263a77256ae 138
bogdanm 20:4263a77256ae 139 // Force reset if the bus is stuck in the BUSY state
bogdanm 20:4263a77256ae 140 if (obj->i2c->SR2 & I2C_SR2_BUSY) {
bogdanm 20:4263a77256ae 141 obj->i2c->CR1 |= I2C_CR1_SWRST;
bogdanm 20:4263a77256ae 142 obj->i2c->CR1 &= ~I2C_CR1_SWRST;
bogdanm 20:4263a77256ae 143 }
bogdanm 20:4263a77256ae 144
bogdanm 20:4263a77256ae 145 // Set the peripheral clock frequency
bogdanm 20:4263a77256ae 146 obj->i2c->CR2 |= 42;
bogdanm 20:4263a77256ae 147
bogdanm 20:4263a77256ae 148 // set default frequency at 100k
bogdanm 20:4263a77256ae 149 i2c_frequency(obj, 100000);
bogdanm 20:4263a77256ae 150 i2c_interface_enable(obj);
bogdanm 20:4263a77256ae 151 }
bogdanm 20:4263a77256ae 152
bogdanm 20:4263a77256ae 153 inline int i2c_start(i2c_t *obj) {
bogdanm 20:4263a77256ae 154 // Wait until we are not busy any more
bogdanm 20:4263a77256ae 155 while (obj->i2c->SR2 & I2C_SR2_BUSY);
bogdanm 20:4263a77256ae 156
bogdanm 20:4263a77256ae 157 // Generate the start condition
bogdanm 20:4263a77256ae 158 obj->i2c->CR1 |= I2C_CR1_START;
bogdanm 20:4263a77256ae 159 i2c_wait_start(obj);
bogdanm 20:4263a77256ae 160
bogdanm 20:4263a77256ae 161 return 0;
bogdanm 20:4263a77256ae 162 }
bogdanm 20:4263a77256ae 163
bogdanm 20:4263a77256ae 164 inline int i2c_stop(i2c_t *obj) {
bogdanm 20:4263a77256ae 165 // Generate the stop condition
bogdanm 20:4263a77256ae 166 obj->i2c->CR1 |= I2C_CR1_STOP;
bogdanm 20:4263a77256ae 167 return 0;
bogdanm 20:4263a77256ae 168 }
bogdanm 20:4263a77256ae 169
bogdanm 20:4263a77256ae 170
bogdanm 20:4263a77256ae 171 static inline int i2c_do_write(i2c_t *obj, int value, uint8_t addr) {
bogdanm 20:4263a77256ae 172 obj->i2c->DR = value;
bogdanm 20:4263a77256ae 173 return 0;
bogdanm 20:4263a77256ae 174 }
bogdanm 20:4263a77256ae 175
bogdanm 20:4263a77256ae 176 static inline int i2c_do_read(i2c_t *obj, int last) {
bogdanm 20:4263a77256ae 177 if(last) {
bogdanm 20:4263a77256ae 178 // Don't acknowledge the byte
bogdanm 20:4263a77256ae 179 obj->i2c->CR1 &= ~(I2C_CR1_ACK);
bogdanm 20:4263a77256ae 180 } else {
bogdanm 20:4263a77256ae 181 // Acknowledge the byte
bogdanm 20:4263a77256ae 182 obj->i2c->CR1 |= I2C_CR1_ACK;
bogdanm 20:4263a77256ae 183 }
bogdanm 20:4263a77256ae 184
bogdanm 20:4263a77256ae 185 // Wait until we receive the byte
bogdanm 20:4263a77256ae 186 i2c_wait_receive(obj);
bogdanm 20:4263a77256ae 187
bogdanm 20:4263a77256ae 188 int data = obj->i2c->DR;
bogdanm 20:4263a77256ae 189 return data;
bogdanm 20:4263a77256ae 190 }
bogdanm 20:4263a77256ae 191
bogdanm 20:4263a77256ae 192 void i2c_frequency(i2c_t *obj, int hz) {
bogdanm 20:4263a77256ae 193 i2c_interface_disable(obj);
bogdanm 20:4263a77256ae 194 obj->i2c->CCR &= ~(I2C_CCR_CCR | I2C_CCR_FS);
bogdanm 20:4263a77256ae 195 if (hz > 100000) {
bogdanm 20:4263a77256ae 196 // Fast Mode
bogdanm 20:4263a77256ae 197 obj->i2c->CCR |= I2C_CCR_FS;
bogdanm 20:4263a77256ae 198 int result = 42000000 / (hz * 3);
bogdanm 20:4263a77256ae 199 obj->i2c->CCR |= result & I2C_CCR_CCR;
bogdanm 20:4263a77256ae 200 obj->i2c->TRISE = ((42 * 300) / 1000) + 1;
bogdanm 20:4263a77256ae 201 }
bogdanm 20:4263a77256ae 202 else {
bogdanm 20:4263a77256ae 203 // Standard mode
bogdanm 20:4263a77256ae 204 obj->i2c->CCR &= ~I2C_CCR_FS;
bogdanm 20:4263a77256ae 205 int result = 42000000 / (hz << 1);
bogdanm 20:4263a77256ae 206 result = result < 0x4 ? 0x4 : result;
bogdanm 20:4263a77256ae 207 obj->i2c->CCR |= result & I2C_CCR_CCR;
bogdanm 20:4263a77256ae 208 obj->i2c->TRISE = 42 + 1;
bogdanm 20:4263a77256ae 209 }
bogdanm 20:4263a77256ae 210 i2c_interface_enable(obj);
bogdanm 20:4263a77256ae 211 }
bogdanm 20:4263a77256ae 212
bogdanm 20:4263a77256ae 213 // The I2C does a read or a write as a whole operation
bogdanm 20:4263a77256ae 214 // There are two types of error conditions it can encounter
bogdanm 20:4263a77256ae 215 // 1) it can not obtain the bus
bogdanm 20:4263a77256ae 216 // 2) it gets error responses at part of the transmission
bogdanm 20:4263a77256ae 217 //
bogdanm 20:4263a77256ae 218 // We tackle them as follows:
bogdanm 20:4263a77256ae 219 // 1) we retry until we get the bus. we could have a "timeout" if we can not get it
bogdanm 20:4263a77256ae 220 // which basically turns it in to a 2)
bogdanm 20:4263a77256ae 221 // 2) on error, we use the standard error mechanisms to report/debug
bogdanm 20:4263a77256ae 222 //
bogdanm 20:4263a77256ae 223 // Therefore an I2C transaction should always complete. If it doesn't it is usually
bogdanm 20:4263a77256ae 224 // because something is setup wrong (e.g. wiring), and we don't need to programatically
bogdanm 20:4263a77256ae 225 // check for that
bogdanm 20:4263a77256ae 226
bogdanm 20:4263a77256ae 227 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
bogdanm 20:4263a77256ae 228 int count;
bogdanm 20:4263a77256ae 229
bogdanm 20:4263a77256ae 230 i2c_start(obj);
bogdanm 20:4263a77256ae 231
bogdanm 20:4263a77256ae 232 // Send the slave address
bogdanm 20:4263a77256ae 233 i2c_do_write(obj, (address | 0x01), 1);
bogdanm 20:4263a77256ae 234
bogdanm 20:4263a77256ae 235 // Wait until we have transmitted and the ADDR byte is set
bogdanm 20:4263a77256ae 236 i2c_wait_addr_rx(obj);
bogdanm 20:4263a77256ae 237
bogdanm 20:4263a77256ae 238 // Read in all except last byte
bogdanm 20:4263a77256ae 239 for (count = 0; count < (length - 1); count++) {
bogdanm 20:4263a77256ae 240 int value = i2c_do_read(obj, 0);
bogdanm 20:4263a77256ae 241 data[count] = (char) value;
bogdanm 20:4263a77256ae 242 }
bogdanm 20:4263a77256ae 243
bogdanm 20:4263a77256ae 244 // read in last byte
bogdanm 20:4263a77256ae 245 int value = i2c_do_read(obj, 1);
bogdanm 20:4263a77256ae 246 data[count] = (char) value;
bogdanm 20:4263a77256ae 247
bogdanm 20:4263a77256ae 248 // If not repeated start, send stop.
bogdanm 20:4263a77256ae 249 if (stop) {
bogdanm 20:4263a77256ae 250 i2c_stop(obj);
bogdanm 20:4263a77256ae 251 }
bogdanm 20:4263a77256ae 252
bogdanm 20:4263a77256ae 253 return length;
bogdanm 20:4263a77256ae 254 }
bogdanm 20:4263a77256ae 255
bogdanm 20:4263a77256ae 256 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
bogdanm 20:4263a77256ae 257 int i;
bogdanm 20:4263a77256ae 258
bogdanm 20:4263a77256ae 259 i2c_start(obj);
bogdanm 20:4263a77256ae 260
bogdanm 20:4263a77256ae 261 // Send the slave address
bogdanm 20:4263a77256ae 262 i2c_do_write(obj, (address & 0xFE), 1);
bogdanm 20:4263a77256ae 263 i2c_wait_addr_tx(obj);
bogdanm 20:4263a77256ae 264
bogdanm 20:4263a77256ae 265 for (i=0; i<length; i++) {
bogdanm 20:4263a77256ae 266 i2c_do_write(obj, data[i], 0);
bogdanm 20:4263a77256ae 267 i2c_wait_send(obj);
bogdanm 20:4263a77256ae 268 }
bogdanm 20:4263a77256ae 269
bogdanm 20:4263a77256ae 270 // If not repeated start, send stop.
bogdanm 20:4263a77256ae 271 if (stop) {
bogdanm 20:4263a77256ae 272 i2c_stop(obj);
bogdanm 20:4263a77256ae 273 }
bogdanm 20:4263a77256ae 274
bogdanm 20:4263a77256ae 275 return length;
bogdanm 20:4263a77256ae 276 }
bogdanm 20:4263a77256ae 277
bogdanm 20:4263a77256ae 278 void i2c_reset(i2c_t *obj) {
bogdanm 20:4263a77256ae 279 i2c_stop(obj);
bogdanm 20:4263a77256ae 280 }
bogdanm 20:4263a77256ae 281
bogdanm 20:4263a77256ae 282 int i2c_byte_read(i2c_t *obj, int last) {
bogdanm 20:4263a77256ae 283 return (i2c_do_read(obj, last) & 0xFF);
bogdanm 20:4263a77256ae 284 }
bogdanm 20:4263a77256ae 285
bogdanm 20:4263a77256ae 286 int i2c_byte_write(i2c_t *obj, int data) {
bogdanm 20:4263a77256ae 287 i2c_do_write(obj, (data & 0xFF), 0);
bogdanm 20:4263a77256ae 288 i2c_wait_send(obj);
bogdanm 20:4263a77256ae 289
bogdanm 20:4263a77256ae 290 // TODO: Should return whether write has been acknowledged
bogdanm 20:4263a77256ae 291 return 1;
bogdanm 20:4263a77256ae 292 }
bogdanm 20:4263a77256ae 293
bogdanm 20:4263a77256ae 294 #endif