mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
186:707f6e361f3e
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AnnaBridge 168:9672193075cf 1 /* mbed Microcontroller Library
Anna Bridge 186:707f6e361f3e 2 * Copyright (c) 2017-2018 ARM Limited
AnnaBridge 168:9672193075cf 3 *
AnnaBridge 168:9672193075cf 4 * Licensed under the Apache License, Version 2.0 (the "License");
AnnaBridge 168:9672193075cf 5 * you may not use this file except in compliance with the License.
AnnaBridge 168:9672193075cf 6 * You may obtain a copy of the License at
AnnaBridge 168:9672193075cf 7 *
AnnaBridge 168:9672193075cf 8 * http://www.apache.org/licenses/LICENSE-2.0
AnnaBridge 168:9672193075cf 9 *
AnnaBridge 168:9672193075cf 10 * Unless required by applicable law or agreed to in writing, software
AnnaBridge 168:9672193075cf 11 * distributed under the License is distributed on an "AS IS" BASIS,
AnnaBridge 168:9672193075cf 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
AnnaBridge 168:9672193075cf 13 * See the License for the specific language governing permissions and
AnnaBridge 168:9672193075cf 14 * limitations under the License.
AnnaBridge 168:9672193075cf 15 */
AnnaBridge 168:9672193075cf 16 #include "i2c_api.h"
AnnaBridge 168:9672193075cf 17 #include "cmsis.h"
AnnaBridge 168:9672193075cf 18 #include "mbed_error.h"
AnnaBridge 168:9672193075cf 19 #include "mbed_wait_api.h"
Anna Bridge 186:707f6e361f3e 20 #include "CM3DS.h"
AnnaBridge 168:9672193075cf 21 #include "pinmap.h"
AnnaBridge 168:9672193075cf 22
AnnaBridge 168:9672193075cf 23 /*
AnnaBridge 168:9672193075cf 24 * The ARM I2C SBCon IP (Two-wire serial bus interface) requires a
AnnaBridge 168:9672193075cf 25 * bit banging programing model.
AnnaBridge 168:9672193075cf 26 */
AnnaBridge 168:9672193075cf 27
AnnaBridge 168:9672193075cf 28 #if DEVICE_I2CSLAVE
AnnaBridge 168:9672193075cf 29 #error "I2C slave is not supported in MPS2 CM3DS board"
AnnaBridge 168:9672193075cf 30 #endif
AnnaBridge 168:9672193075cf 31
AnnaBridge 168:9672193075cf 32 #define DEFAULT_I2C_SBCON_HZ 4000000U /* 4MHz */
AnnaBridge 168:9672193075cf 33 #define STOP_REQUIRED 1
AnnaBridge 168:9672193075cf 34 #define LAST_ACK_REQUIRED 1
AnnaBridge 168:9672193075cf 35 #define LAST_ACK_NOT_REQUIRED 0
AnnaBridge 168:9672193075cf 36 #define I2C_ACK_BIT 0x1
AnnaBridge 168:9672193075cf 37
AnnaBridge 168:9672193075cf 38 #define SDA (1 << 1)
AnnaBridge 168:9672193075cf 39 #define SCL (1 << 0)
AnnaBridge 168:9672193075cf 40 #define I2C_HIGH(p_i2c, pin) (p_i2c->CONTROLS = pin)
AnnaBridge 168:9672193075cf 41 #define I2C_LOW(p_i2c, pin) (p_i2c->CONTROLC = pin)
AnnaBridge 168:9672193075cf 42 #define I2C_GET(p_i2c, pin) ((p_i2c->CONTROL >> (pin-1)) & 0x01)
AnnaBridge 168:9672193075cf 43
AnnaBridge 168:9672193075cf 44 static const PinMap PinMap_I2C_SDA[] = {
AnnaBridge 168:9672193075cf 45 {TSC_SDA , I2C_0, 0},
AnnaBridge 168:9672193075cf 46 {AUD_SDA , I2C_1, 0},
AnnaBridge 168:9672193075cf 47 {SHIELD_0_SDA , I2C_2, ALTERNATE_FUNC},
AnnaBridge 168:9672193075cf 48 {SHIELD_1_SDA , I2C_3, ALTERNATE_FUNC},
AnnaBridge 168:9672193075cf 49 {NC , NC , 0}
AnnaBridge 168:9672193075cf 50 };
AnnaBridge 168:9672193075cf 51
AnnaBridge 168:9672193075cf 52 static const PinMap PinMap_I2C_SCL[] = {
AnnaBridge 168:9672193075cf 53 {TSC_SCL , I2C_0, 0},
AnnaBridge 168:9672193075cf 54 {AUD_SCL , I2C_1, 0},
AnnaBridge 168:9672193075cf 55 {SHIELD_0_SCL , I2C_2, ALTERNATE_FUNC},
AnnaBridge 168:9672193075cf 56 {SHIELD_1_SCL , I2C_3, ALTERNATE_FUNC},
AnnaBridge 168:9672193075cf 57 {NC , NC, 0}
AnnaBridge 168:9672193075cf 58 };
AnnaBridge 168:9672193075cf 59
AnnaBridge 168:9672193075cf 60 /*
AnnaBridge 168:9672193075cf 61 * \brief Transmits a data bit.
AnnaBridge 168:9672193075cf 62 *
AnnaBridge 168:9672193075cf 63 * \param[in] obj I2C object
AnnaBridge 168:9672193075cf 64 * \param[in] bit Bit to transmit
AnnaBridge 168:9672193075cf 65 */
AnnaBridge 168:9672193075cf 66 static void i2c_tx_bit(i2c_t *obj, uint8_t bit)
AnnaBridge 168:9672193075cf 67 {
AnnaBridge 168:9672193075cf 68 if (bit != 0) {
AnnaBridge 168:9672193075cf 69 I2C_HIGH(obj->i2c, SDA);
AnnaBridge 168:9672193075cf 70 } else {
AnnaBridge 168:9672193075cf 71 I2C_LOW(obj->i2c, SDA);
AnnaBridge 168:9672193075cf 72 }
AnnaBridge 168:9672193075cf 73
AnnaBridge 168:9672193075cf 74 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 75
AnnaBridge 168:9672193075cf 76 I2C_HIGH(obj->i2c, SCL);
AnnaBridge 168:9672193075cf 77 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 78
AnnaBridge 168:9672193075cf 79 I2C_LOW(obj->i2c, SCL);
AnnaBridge 168:9672193075cf 80 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 81 }
AnnaBridge 168:9672193075cf 82
AnnaBridge 168:9672193075cf 83 /*
AnnaBridge 168:9672193075cf 84 * \brief Reads a data bit
AnnaBridge 168:9672193075cf 85 *
AnnaBridge 168:9672193075cf 86 * \param[in] obj I2C object
AnnaBridge 168:9672193075cf 87 *
AnnaBridge 168:9672193075cf 88 * \returns Bit value received.
AnnaBridge 168:9672193075cf 89 */
AnnaBridge 168:9672193075cf 90 static uint8_t i2c_rx_bit(i2c_t *obj)
AnnaBridge 168:9672193075cf 91 {
AnnaBridge 168:9672193075cf 92 uint8_t bit;
AnnaBridge 168:9672193075cf 93
AnnaBridge 168:9672193075cf 94 I2C_HIGH(obj->i2c, SDA);
AnnaBridge 168:9672193075cf 95 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 96
AnnaBridge 168:9672193075cf 97 I2C_HIGH(obj->i2c, SCL);
AnnaBridge 168:9672193075cf 98 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 99
AnnaBridge 168:9672193075cf 100 bit = I2C_GET(obj->i2c, SDA);
AnnaBridge 168:9672193075cf 101
AnnaBridge 168:9672193075cf 102 I2C_LOW(obj->i2c, SCL);
AnnaBridge 168:9672193075cf 103 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 104
AnnaBridge 168:9672193075cf 105 return bit;
AnnaBridge 168:9672193075cf 106 }
AnnaBridge 168:9672193075cf 107
AnnaBridge 168:9672193075cf 108 void i2c_init(i2c_t *obj, PinName sda, PinName scl)
AnnaBridge 168:9672193075cf 109 {
AnnaBridge 168:9672193075cf 110 I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
AnnaBridge 168:9672193075cf 111 I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
AnnaBridge 168:9672193075cf 112 obj->i2c = (MPS2_I2C_TypeDef *)pinmap_merge(i2c_sda, i2c_scl);
AnnaBridge 168:9672193075cf 113
AnnaBridge 168:9672193075cf 114 if ((int)obj->i2c == NC) {
AnnaBridge 168:9672193075cf 115 error("I2C pin mapping failed");
AnnaBridge 168:9672193075cf 116 }
AnnaBridge 168:9672193075cf 117
AnnaBridge 168:9672193075cf 118 switch ((int)obj->i2c) {
AnnaBridge 168:9672193075cf 119 case I2C_2:
AnnaBridge 168:9672193075cf 120 case I2C_3:
AnnaBridge 168:9672193075cf 121 /* Enables alt-function to use I2C SCL and SDA signals */
AnnaBridge 168:9672193075cf 122 pin_function(sda, ALTERNATE_FUNC);
AnnaBridge 168:9672193075cf 123 pin_function(scl, ALTERNATE_FUNC);
AnnaBridge 168:9672193075cf 124 break;
AnnaBridge 168:9672193075cf 125 default:
AnnaBridge 168:9672193075cf 126 break;
AnnaBridge 168:9672193075cf 127 }
AnnaBridge 168:9672193075cf 128
AnnaBridge 168:9672193075cf 129 /* Sets default I2C frequency in microseconds */
AnnaBridge 168:9672193075cf 130 obj->freq_us = (SystemCoreClock / DEFAULT_I2C_SBCON_HZ);
AnnaBridge 168:9672193075cf 131 }
AnnaBridge 168:9672193075cf 132
AnnaBridge 168:9672193075cf 133 void i2c_frequency(i2c_t *obj, int hz)
AnnaBridge 168:9672193075cf 134 {
AnnaBridge 168:9672193075cf 135 if ((hz <= 0) || ((unsigned int)hz > SystemCoreClock)) {
AnnaBridge 168:9672193075cf 136 error("Couldn't setup requested I2C frequency %dHz", hz);
AnnaBridge 168:9672193075cf 137 }
AnnaBridge 168:9672193075cf 138
AnnaBridge 168:9672193075cf 139 obj->freq_us = (SystemCoreClock / hz);
AnnaBridge 168:9672193075cf 140 }
AnnaBridge 168:9672193075cf 141
AnnaBridge 168:9672193075cf 142 int i2c_start(i2c_t *obj)
AnnaBridge 168:9672193075cf 143 {
AnnaBridge 168:9672193075cf 144 I2C_HIGH(obj->i2c, (SCL | SDA));
AnnaBridge 168:9672193075cf 145 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 146
AnnaBridge 168:9672193075cf 147 I2C_LOW(obj->i2c, SDA);
AnnaBridge 168:9672193075cf 148 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 149
AnnaBridge 168:9672193075cf 150 I2C_LOW(obj->i2c, SCL);
AnnaBridge 168:9672193075cf 151 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 152
AnnaBridge 168:9672193075cf 153 return 0;
AnnaBridge 168:9672193075cf 154 }
AnnaBridge 168:9672193075cf 155
AnnaBridge 168:9672193075cf 156 int i2c_stop(i2c_t *obj)
AnnaBridge 168:9672193075cf 157 {
AnnaBridge 168:9672193075cf 158 I2C_LOW(obj->i2c, SDA);
AnnaBridge 168:9672193075cf 159 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 160
AnnaBridge 168:9672193075cf 161 I2C_HIGH(obj->i2c, SCL);
AnnaBridge 168:9672193075cf 162 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 163
AnnaBridge 168:9672193075cf 164 I2C_HIGH(obj->i2c, SDA);
AnnaBridge 168:9672193075cf 165 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 166
AnnaBridge 168:9672193075cf 167 return 0;
AnnaBridge 168:9672193075cf 168 }
AnnaBridge 168:9672193075cf 169
AnnaBridge 168:9672193075cf 170 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
AnnaBridge 168:9672193075cf 171 {
AnnaBridge 168:9672193075cf 172 int32_t nbr_bytes_read = 0;
AnnaBridge 168:9672193075cf 173
AnnaBridge 168:9672193075cf 174 if (data == 0 || length == 0) {
AnnaBridge 168:9672193075cf 175 error("Invalid i2c_read input data");
AnnaBridge 168:9672193075cf 176 }
AnnaBridge 168:9672193075cf 177
AnnaBridge 168:9672193075cf 178 i2c_start(obj);
AnnaBridge 168:9672193075cf 179
AnnaBridge 168:9672193075cf 180 i2c_byte_write(obj, (uint8_t)(address | 0x1));
AnnaBridge 168:9672193075cf 181
AnnaBridge 168:9672193075cf 182 while(nbr_bytes_read < (length - 1)) {
AnnaBridge 168:9672193075cf 183 data[nbr_bytes_read++] = i2c_byte_read(obj, LAST_ACK_NOT_REQUIRED);
AnnaBridge 168:9672193075cf 184 }
AnnaBridge 168:9672193075cf 185
AnnaBridge 168:9672193075cf 186 data[nbr_bytes_read++] = i2c_byte_read(obj, LAST_ACK_REQUIRED);
AnnaBridge 168:9672193075cf 187
AnnaBridge 168:9672193075cf 188 if (stop == STOP_REQUIRED) {
AnnaBridge 168:9672193075cf 189 i2c_stop(obj);
AnnaBridge 168:9672193075cf 190 }
AnnaBridge 168:9672193075cf 191
AnnaBridge 168:9672193075cf 192 return nbr_bytes_read;
AnnaBridge 168:9672193075cf 193 }
AnnaBridge 168:9672193075cf 194
AnnaBridge 168:9672193075cf 195 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
AnnaBridge 168:9672193075cf 196 {
AnnaBridge 168:9672193075cf 197 int32_t nbr_bytes_write;
AnnaBridge 168:9672193075cf 198
AnnaBridge 168:9672193075cf 199 if (data == 0) {
AnnaBridge 168:9672193075cf 200 error("Invalid i2c_write input data");
AnnaBridge 168:9672193075cf 201 }
AnnaBridge 168:9672193075cf 202
AnnaBridge 168:9672193075cf 203 i2c_start(obj);
AnnaBridge 168:9672193075cf 204
AnnaBridge 168:9672193075cf 205 i2c_byte_write(obj, (uint8_t)address);
AnnaBridge 168:9672193075cf 206
AnnaBridge 168:9672193075cf 207 for (nbr_bytes_write = 0; nbr_bytes_write < length; nbr_bytes_write++) {
AnnaBridge 168:9672193075cf 208 i2c_byte_write(obj, data[nbr_bytes_write]);
AnnaBridge 168:9672193075cf 209 }
AnnaBridge 168:9672193075cf 210
AnnaBridge 168:9672193075cf 211 if (stop == STOP_REQUIRED) {
AnnaBridge 168:9672193075cf 212 i2c_stop(obj);
AnnaBridge 168:9672193075cf 213 }
AnnaBridge 168:9672193075cf 214
AnnaBridge 168:9672193075cf 215 return nbr_bytes_write;
AnnaBridge 168:9672193075cf 216 }
AnnaBridge 168:9672193075cf 217
AnnaBridge 168:9672193075cf 218 void i2c_reset(i2c_t *obj)
AnnaBridge 168:9672193075cf 219 {
AnnaBridge 168:9672193075cf 220 uint32_t iter;
AnnaBridge 168:9672193075cf 221
AnnaBridge 168:9672193075cf 222 /*
AnnaBridge 168:9672193075cf 223 * The reset sequence is:
AnnaBridge 168:9672193075cf 224 * - SDA line low
AnnaBridge 168:9672193075cf 225 * - 9 clock pulses
AnnaBridge 168:9672193075cf 226 * - SDA line high
AnnaBridge 168:9672193075cf 227 */
AnnaBridge 168:9672193075cf 228 I2C_LOW(obj->i2c, SDA);
AnnaBridge 168:9672193075cf 229 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 230
AnnaBridge 168:9672193075cf 231 for(iter=0; iter < 9; iter++) {
AnnaBridge 168:9672193075cf 232 I2C_LOW(obj->i2c, SCL);
AnnaBridge 168:9672193075cf 233 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 234 I2C_HIGH(obj->i2c, SCL);
AnnaBridge 168:9672193075cf 235 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 236 }
AnnaBridge 168:9672193075cf 237
AnnaBridge 168:9672193075cf 238 I2C_HIGH(obj->i2c, SDA);
AnnaBridge 168:9672193075cf 239 wait_us(obj->freq_us);
AnnaBridge 168:9672193075cf 240 }
AnnaBridge 168:9672193075cf 241
AnnaBridge 168:9672193075cf 242 int i2c_byte_read(i2c_t *obj, int last)
AnnaBridge 168:9672193075cf 243 {
AnnaBridge 168:9672193075cf 244 uint8_t nbr_bits;
AnnaBridge 168:9672193075cf 245 uint8_t data = 0;
AnnaBridge 168:9672193075cf 246
AnnaBridge 168:9672193075cf 247 data = i2c_rx_bit(obj);
AnnaBridge 168:9672193075cf 248 for (nbr_bits = 1; nbr_bits < 8; nbr_bits++) {
AnnaBridge 168:9672193075cf 249 data <<= 1;
AnnaBridge 168:9672193075cf 250 data |= i2c_rx_bit(obj);
AnnaBridge 168:9672193075cf 251 }
AnnaBridge 168:9672193075cf 252
AnnaBridge 168:9672193075cf 253 i2c_tx_bit(obj, last);
AnnaBridge 168:9672193075cf 254
AnnaBridge 168:9672193075cf 255 return data;
AnnaBridge 168:9672193075cf 256 }
AnnaBridge 168:9672193075cf 257
AnnaBridge 168:9672193075cf 258 int i2c_byte_write(i2c_t *obj, int data)
AnnaBridge 168:9672193075cf 259 {
AnnaBridge 168:9672193075cf 260 uint8_t nbr_bits;
AnnaBridge 168:9672193075cf 261 uint8_t ack;
AnnaBridge 168:9672193075cf 262
AnnaBridge 168:9672193075cf 263 for(nbr_bits=0; nbr_bits < 7; nbr_bits++) {
AnnaBridge 168:9672193075cf 264 i2c_tx_bit(obj, data & 0x80);
AnnaBridge 168:9672193075cf 265 data <<= 1;
AnnaBridge 168:9672193075cf 266 }
AnnaBridge 168:9672193075cf 267
AnnaBridge 168:9672193075cf 268 i2c_tx_bit(obj, data & 0x80);
AnnaBridge 168:9672193075cf 269
AnnaBridge 168:9672193075cf 270 ack = i2c_rx_bit(obj);
AnnaBridge 168:9672193075cf 271
AnnaBridge 168:9672193075cf 272 return ack;
AnnaBridge 168:9672193075cf 273 }