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:
184:08ed48f1de7f
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 144:ef7eb2e8f9f7 1 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 2 * @file i2c_api.c
<> 144:ef7eb2e8f9f7 3 *******************************************************************************
<> 144:ef7eb2e8f9f7 4 * @section License
<> 144:ef7eb2e8f9f7 5 * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
<> 144:ef7eb2e8f9f7 6 *******************************************************************************
<> 144:ef7eb2e8f9f7 7 *
<> 144:ef7eb2e8f9f7 8 * SPDX-License-Identifier: Apache-2.0
<> 144:ef7eb2e8f9f7 9 *
<> 144:ef7eb2e8f9f7 10 * Licensed under the Apache License, Version 2.0 (the "License"); you may
<> 144:ef7eb2e8f9f7 11 * not use this file except in compliance with the License.
<> 144:ef7eb2e8f9f7 12 * You may obtain a copy of the License at
<> 144:ef7eb2e8f9f7 13 *
<> 144:ef7eb2e8f9f7 14 * http://www.apache.org/licenses/LICENSE-2.0
<> 144:ef7eb2e8f9f7 15 *
<> 144:ef7eb2e8f9f7 16 * Unless required by applicable law or agreed to in writing, software
<> 144:ef7eb2e8f9f7 17 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
<> 144:ef7eb2e8f9f7 18 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<> 144:ef7eb2e8f9f7 19 * See the License for the specific language governing permissions and
<> 144:ef7eb2e8f9f7 20 * limitations under the License.
<> 144:ef7eb2e8f9f7 21 *
<> 144:ef7eb2e8f9f7 22 ******************************************************************************/
<> 144:ef7eb2e8f9f7 23
<> 144:ef7eb2e8f9f7 24 #include "device.h"
<> 144:ef7eb2e8f9f7 25 #include "clocking.h"
<> 144:ef7eb2e8f9f7 26 #include <stdio.h>
<> 144:ef7eb2e8f9f7 27
<> 144:ef7eb2e8f9f7 28 #if DEVICE_I2C
<> 144:ef7eb2e8f9f7 29
<> 144:ef7eb2e8f9f7 30 #include "mbed_assert.h"
AnnaBridge 184:08ed48f1de7f 31 #include "mbed_power_mgmt.h"
<> 144:ef7eb2e8f9f7 32 #include "i2c_api.h"
<> 144:ef7eb2e8f9f7 33 #include "PeripheralPins.h"
<> 144:ef7eb2e8f9f7 34 #include "pinmap_function.h"
<> 144:ef7eb2e8f9f7 35
<> 144:ef7eb2e8f9f7 36 #include "em_i2c.h"
<> 144:ef7eb2e8f9f7 37 #include "em_cmu.h"
<> 144:ef7eb2e8f9f7 38
<> 144:ef7eb2e8f9f7 39 /** Error flags indicating I2C transfer has failed somehow. */
<> 144:ef7eb2e8f9f7 40 /* Notice that I2C_IF_TXOF (transmit overflow) is not really possible with */
<> 144:ef7eb2e8f9f7 41 /* this SW supporting master mode. Likewise for I2C_IF_RXUF (receive underflow) */
<> 144:ef7eb2e8f9f7 42 /* RXUF is only likely to occur with this SW if using a debugger peeking into */
<> 144:ef7eb2e8f9f7 43 /* RXDATA register. Thus, we ignore those types of fault. */
<> 144:ef7eb2e8f9f7 44 #define I2C_IF_ERRORS (I2C_IF_BUSERR | I2C_IF_ARBLOST)
<> 144:ef7eb2e8f9f7 45 #define I2C_TIMEOUT 100000
<> 144:ef7eb2e8f9f7 46
<> 144:ef7eb2e8f9f7 47 /* Prototypes */
<> 144:ef7eb2e8f9f7 48 int block_and_wait_for_ack(I2C_TypeDef *i2c);
<> 144:ef7eb2e8f9f7 49 void i2c_enable(i2c_t *obj, uint8_t enable);
<> 144:ef7eb2e8f9f7 50 void i2c_enable_pins(i2c_t *obj, uint8_t enable);
<> 144:ef7eb2e8f9f7 51 void i2c_enable_interrupt(i2c_t *obj, uint32_t address, uint8_t enable);
<> 144:ef7eb2e8f9f7 52
<> 144:ef7eb2e8f9f7 53 static uint8_t i2c_get_index(i2c_t *obj)
<> 144:ef7eb2e8f9f7 54 {
<> 144:ef7eb2e8f9f7 55 uint8_t index = 0;
<> 144:ef7eb2e8f9f7 56 switch ((int)obj->i2c.i2c) {
<> 144:ef7eb2e8f9f7 57 #ifdef I2C0
<> 144:ef7eb2e8f9f7 58 case I2C_0:
<> 144:ef7eb2e8f9f7 59 index = 0;
<> 144:ef7eb2e8f9f7 60 break;
<> 144:ef7eb2e8f9f7 61 #endif
<> 144:ef7eb2e8f9f7 62 #ifdef I2C1
<> 144:ef7eb2e8f9f7 63 case I2C_1:
<> 144:ef7eb2e8f9f7 64 index = 1;
<> 144:ef7eb2e8f9f7 65 break;
<> 144:ef7eb2e8f9f7 66 #endif
<> 144:ef7eb2e8f9f7 67 default:
<> 144:ef7eb2e8f9f7 68 printf("I2C module not available.. Out of bound access.");
<> 144:ef7eb2e8f9f7 69 break;
<> 144:ef7eb2e8f9f7 70 }
<> 144:ef7eb2e8f9f7 71 return index;
<> 144:ef7eb2e8f9f7 72 }
<> 144:ef7eb2e8f9f7 73
<> 144:ef7eb2e8f9f7 74 static CMU_Clock_TypeDef i2c_get_clock(i2c_t *obj)
<> 144:ef7eb2e8f9f7 75 {
<> 144:ef7eb2e8f9f7 76 CMU_Clock_TypeDef clock;
<> 144:ef7eb2e8f9f7 77 switch ((int)obj->i2c.i2c) {
<> 144:ef7eb2e8f9f7 78 #ifdef I2C0
<> 144:ef7eb2e8f9f7 79 case I2C_0:
<> 144:ef7eb2e8f9f7 80 clock = cmuClock_I2C0;
<> 144:ef7eb2e8f9f7 81 break;
<> 144:ef7eb2e8f9f7 82 #endif
<> 144:ef7eb2e8f9f7 83 #ifdef I2C1
<> 144:ef7eb2e8f9f7 84 case I2C_1:
<> 144:ef7eb2e8f9f7 85 clock = cmuClock_I2C1;
<> 144:ef7eb2e8f9f7 86 break;
<> 144:ef7eb2e8f9f7 87 #endif
<> 144:ef7eb2e8f9f7 88 default:
<> 144:ef7eb2e8f9f7 89 printf("I2C module not available.. Out of bound access. (clock)");
<> 144:ef7eb2e8f9f7 90 clock = cmuClock_HFPER;
<> 144:ef7eb2e8f9f7 91 break;
<> 144:ef7eb2e8f9f7 92 }
<> 144:ef7eb2e8f9f7 93 return clock;
<> 144:ef7eb2e8f9f7 94 }
<> 144:ef7eb2e8f9f7 95
<> 144:ef7eb2e8f9f7 96 void i2c_init(i2c_t *obj, PinName sda, PinName scl)
<> 144:ef7eb2e8f9f7 97 {
<> 144:ef7eb2e8f9f7 98 /* Find out which I2C peripheral we're asked to use */
<> 144:ef7eb2e8f9f7 99 I2CName i2c_sda = (I2CName) pinmap_peripheral(sda, PinMap_I2C_SDA);
<> 144:ef7eb2e8f9f7 100 I2CName i2c_scl = (I2CName) pinmap_peripheral(scl, PinMap_I2C_SCL);
<> 144:ef7eb2e8f9f7 101 obj->i2c.i2c = (I2C_TypeDef*) pinmap_merge(i2c_sda, i2c_scl);
AnnaBridge 179:b0033dcd6934 102 MBED_ASSERT(((unsigned int) obj->i2c.i2c) != NC);
AnnaBridge 179:b0033dcd6934 103
<> 144:ef7eb2e8f9f7 104 /* You need both SDA and SCL for I2C, so configuring one of them to NC is illegal */
AnnaBridge 179:b0033dcd6934 105 MBED_ASSERT((unsigned int)sda != NC);
AnnaBridge 179:b0033dcd6934 106 MBED_ASSERT((unsigned int)scl != NC);
<> 144:ef7eb2e8f9f7 107
<> 144:ef7eb2e8f9f7 108 /* Enable clock for the peripheral */
<> 144:ef7eb2e8f9f7 109 CMU_ClockEnable(i2c_get_clock(obj), true);
<> 144:ef7eb2e8f9f7 110
<> 144:ef7eb2e8f9f7 111 /* Initializing the I2C */
<> 144:ef7eb2e8f9f7 112 /* Using default settings */
<> 144:ef7eb2e8f9f7 113 I2C_Init_TypeDef i2cInit = I2C_INIT_DEFAULT;
<> 144:ef7eb2e8f9f7 114 I2C_Init(obj->i2c.i2c, &i2cInit);
<> 144:ef7eb2e8f9f7 115
<> 144:ef7eb2e8f9f7 116 /* Enable pins at correct location */
<> 144:ef7eb2e8f9f7 117 #ifdef I2C_ROUTE_SDAPEN
<> 144:ef7eb2e8f9f7 118 /* Find common location in pinmap */
AnnaBridge 179:b0033dcd6934 119 unsigned int loc_sda = pin_location(sda, PinMap_I2C_SDA);
AnnaBridge 179:b0033dcd6934 120 unsigned int loc_scl = pin_location(scl, PinMap_I2C_SCL);
AnnaBridge 179:b0033dcd6934 121 unsigned int loc = pinmap_merge(loc_sda, loc_scl);
<> 144:ef7eb2e8f9f7 122 MBED_ASSERT(loc != NC);
<> 144:ef7eb2e8f9f7 123 /* Set location */
Anna Bridge 163:74e0ce7f98e8 124 obj->i2c.location = I2C_ROUTE_SDAPEN | I2C_ROUTE_SCLPEN | (loc << _I2C_ROUTE_LOCATION_SHIFT);
<> 144:ef7eb2e8f9f7 125 obj->i2c.i2c->ROUTE = I2C_ROUTE_SDAPEN | I2C_ROUTE_SCLPEN | (loc << _I2C_ROUTE_LOCATION_SHIFT);
<> 144:ef7eb2e8f9f7 126 #else
<> 144:ef7eb2e8f9f7 127 obj->i2c.i2c->ROUTEPEN = I2C_ROUTEPEN_SDAPEN | I2C_ROUTEPEN_SCLPEN;
Anna Bridge 163:74e0ce7f98e8 128 obj->i2c.location = (pin_location(sda, PinMap_I2C_SDA) << _I2C_ROUTELOC0_SDALOC_SHIFT) |
Anna Bridge 163:74e0ce7f98e8 129 (pin_location(scl, PinMap_I2C_SCL) << _I2C_ROUTELOC0_SCLLOC_SHIFT);
Anna Bridge 163:74e0ce7f98e8 130 obj->i2c.i2c->ROUTELOC0 = obj->i2c.location;
<> 144:ef7eb2e8f9f7 131 #endif
<> 144:ef7eb2e8f9f7 132
<> 144:ef7eb2e8f9f7 133 /* Set up the pins for I2C use */
<> 144:ef7eb2e8f9f7 134 /* Note: Set up pins in higher drive strength to reduce slew rate */
<> 144:ef7eb2e8f9f7 135 /* Though this requires user knowledge, since drive strength is controlled per port, not pin */
<> 144:ef7eb2e8f9f7 136 pin_mode(scl, WiredAndPullUp);
<> 144:ef7eb2e8f9f7 137 pin_mode(sda, WiredAndPullUp);
<> 144:ef7eb2e8f9f7 138
<> 144:ef7eb2e8f9f7 139 /* Enable General Call Address Mode. That is; we respond to the general address (0x0) */
<> 144:ef7eb2e8f9f7 140 obj->i2c.i2c->CTRL |= _I2C_CTRL_GCAMEN_MASK;
<> 144:ef7eb2e8f9f7 141
<> 144:ef7eb2e8f9f7 142 /* We are assuming that there is only one master. So disable automatic arbitration */
<> 144:ef7eb2e8f9f7 143 obj->i2c.i2c->CTRL |= _I2C_CTRL_ARBDIS_MASK;
<> 144:ef7eb2e8f9f7 144
<> 144:ef7eb2e8f9f7 145 /* Set to master (needed if this I2C block was used previously as slave) */
<> 144:ef7eb2e8f9f7 146 i2c_slave_mode(obj, false);
<> 144:ef7eb2e8f9f7 147
<> 144:ef7eb2e8f9f7 148 /* Enable i2c */
<> 144:ef7eb2e8f9f7 149 i2c_enable(obj, true);
<> 144:ef7eb2e8f9f7 150 }
<> 144:ef7eb2e8f9f7 151
<> 144:ef7eb2e8f9f7 152 void i2c_enable(i2c_t *obj, uint8_t enable)
<> 144:ef7eb2e8f9f7 153 {
<> 144:ef7eb2e8f9f7 154 I2C_Enable(obj->i2c.i2c, enable);
<> 144:ef7eb2e8f9f7 155 if (!enable) {
<> 144:ef7eb2e8f9f7 156 /* After a reset BUSY is usually set. We assume that we are the only master and call abort,
<> 144:ef7eb2e8f9f7 157 * which sends nothing on the bus, it just allows us to assume that the bus is idle */
<> 144:ef7eb2e8f9f7 158 if (obj->i2c.i2c->STATE & I2C_STATE_BUSY) {
<> 144:ef7eb2e8f9f7 159 obj->i2c.i2c->CMD = I2C_CMD_ABORT;
<> 144:ef7eb2e8f9f7 160 }
<> 144:ef7eb2e8f9f7 161 }
<> 144:ef7eb2e8f9f7 162 }
<> 144:ef7eb2e8f9f7 163
<> 144:ef7eb2e8f9f7 164 void i2c_enable_interrupt(i2c_t *obj, uint32_t address, uint8_t enable)
<> 144:ef7eb2e8f9f7 165 {
<> 144:ef7eb2e8f9f7 166 IRQn_Type irq_number;
<> 144:ef7eb2e8f9f7 167
<> 144:ef7eb2e8f9f7 168 switch (i2c_get_index(obj)) {
<> 144:ef7eb2e8f9f7 169 #ifdef I2C0
<> 144:ef7eb2e8f9f7 170 case 0:
<> 144:ef7eb2e8f9f7 171 irq_number = I2C0_IRQn;
<> 144:ef7eb2e8f9f7 172 break;
<> 144:ef7eb2e8f9f7 173 #endif
<> 144:ef7eb2e8f9f7 174 #ifdef I2C1
<> 144:ef7eb2e8f9f7 175 case 1:
<> 144:ef7eb2e8f9f7 176 irq_number = I2C1_IRQn;
<> 144:ef7eb2e8f9f7 177 break;
<> 144:ef7eb2e8f9f7 178 #endif
<> 144:ef7eb2e8f9f7 179 }
<> 144:ef7eb2e8f9f7 180
<> 144:ef7eb2e8f9f7 181 NVIC_SetVector(irq_number, address);
<> 144:ef7eb2e8f9f7 182 /* Lower IRQ priority to avoid messing with asynch RX on UART */
<> 144:ef7eb2e8f9f7 183 NVIC_SetPriority(irq_number, 1);
<> 144:ef7eb2e8f9f7 184 if (enable) {
<> 144:ef7eb2e8f9f7 185 NVIC_EnableIRQ(irq_number);
<> 144:ef7eb2e8f9f7 186 } else {
<> 144:ef7eb2e8f9f7 187 NVIC_DisableIRQ(irq_number);
<> 144:ef7eb2e8f9f7 188 }
<> 144:ef7eb2e8f9f7 189 }
<> 144:ef7eb2e8f9f7 190
<> 144:ef7eb2e8f9f7 191 /* Set the frequency of the I2C interface */
<> 144:ef7eb2e8f9f7 192 void i2c_frequency(i2c_t *obj, int hz)
<> 144:ef7eb2e8f9f7 193 {
<> 144:ef7eb2e8f9f7 194 /* Set frequency. As the second argument is 0,
<> 144:ef7eb2e8f9f7 195 * HFPER clock frequency is used as reference freq */
<> 144:ef7eb2e8f9f7 196 if (hz <= 0) return;
<> 144:ef7eb2e8f9f7 197 /* In I2C Normal mode (50% duty), we can go up to 100kHz */
<> 144:ef7eb2e8f9f7 198 if (hz <= 100000) {
<> 144:ef7eb2e8f9f7 199 I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRStandard);
<> 144:ef7eb2e8f9f7 200 }
<> 144:ef7eb2e8f9f7 201 /* In I2C Fast mode (6:3 ratio), we can go up to 400kHz */
<> 144:ef7eb2e8f9f7 202 else if (hz <= 400000) {
<> 144:ef7eb2e8f9f7 203 I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRAsymetric);
<> 144:ef7eb2e8f9f7 204 }
<> 144:ef7eb2e8f9f7 205 /* In I2C Fast+ mode (11:6 ratio), we can go up to 1 MHz */
<> 144:ef7eb2e8f9f7 206 else if (hz <= 1000000) {
<> 144:ef7eb2e8f9f7 207 I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRFast);
<> 144:ef7eb2e8f9f7 208 }
<> 144:ef7eb2e8f9f7 209 /* Cap requested frequency at 1MHz */
<> 144:ef7eb2e8f9f7 210 else {
<> 144:ef7eb2e8f9f7 211 I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, 1000000, i2cClockHLRFast);
<> 144:ef7eb2e8f9f7 212 }
<> 144:ef7eb2e8f9f7 213 }
<> 144:ef7eb2e8f9f7 214
<> 144:ef7eb2e8f9f7 215 /* Creates a start condition on the I2C bus */
<> 144:ef7eb2e8f9f7 216 int i2c_start(i2c_t *obj)
<> 144:ef7eb2e8f9f7 217 {
<> 144:ef7eb2e8f9f7 218 I2C_TypeDef *i2c = obj->i2c.i2c;
<> 144:ef7eb2e8f9f7 219
Anna Bridge 163:74e0ce7f98e8 220 /* Restore pin configuration in case we changed I2C object */
Anna Bridge 163:74e0ce7f98e8 221 #ifdef I2C_ROUTE_SDAPEN
Anna Bridge 163:74e0ce7f98e8 222 obj->i2c.i2c->ROUTE = obj->i2c.location;
Anna Bridge 163:74e0ce7f98e8 223 #else
Anna Bridge 163:74e0ce7f98e8 224 obj->i2c.i2c->ROUTELOC0 = obj->i2c.location;
Anna Bridge 163:74e0ce7f98e8 225 #endif
Anna Bridge 163:74e0ce7f98e8 226
<> 144:ef7eb2e8f9f7 227 /* Ensure buffers are empty */
<> 144:ef7eb2e8f9f7 228 i2c->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;
<> 144:ef7eb2e8f9f7 229 if (i2c->IF & I2C_IF_RXDATAV) {
<> 144:ef7eb2e8f9f7 230 (void) i2c->RXDATA;
<> 144:ef7eb2e8f9f7 231 }
<> 144:ef7eb2e8f9f7 232
<> 144:ef7eb2e8f9f7 233 /* Clear all pending interrupts prior to starting transfer. */
<> 144:ef7eb2e8f9f7 234 i2c->IFC = _I2C_IFC_MASK;
<> 144:ef7eb2e8f9f7 235
<> 144:ef7eb2e8f9f7 236 /* Send start */
<> 144:ef7eb2e8f9f7 237 obj->i2c.i2c->CMD = I2C_CMD_START;
<> 144:ef7eb2e8f9f7 238 return 0;
<> 144:ef7eb2e8f9f7 239 }
<> 144:ef7eb2e8f9f7 240
<> 144:ef7eb2e8f9f7 241 /* Creates a stop condition on the I2C bus */
<> 144:ef7eb2e8f9f7 242 int i2c_stop(i2c_t *obj)
<> 144:ef7eb2e8f9f7 243 {
<> 144:ef7eb2e8f9f7 244 obj->i2c.i2c->CMD = I2C_CMD_STOP;
<> 144:ef7eb2e8f9f7 245
<> 144:ef7eb2e8f9f7 246 /* Wait for the stop to be sent */
<> 144:ef7eb2e8f9f7 247 int timeout = I2C_TIMEOUT;
<> 144:ef7eb2e8f9f7 248 while (!(obj->i2c.i2c->IF & I2C_IF_MSTOP) && !timeout--);
<> 144:ef7eb2e8f9f7 249
<> 144:ef7eb2e8f9f7 250 return 0;
<> 144:ef7eb2e8f9f7 251 }
<> 144:ef7eb2e8f9f7 252
<> 144:ef7eb2e8f9f7 253 /* Returns number of bytes read */
<> 144:ef7eb2e8f9f7 254 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
<> 144:ef7eb2e8f9f7 255 {
<> 144:ef7eb2e8f9f7 256 int retval;
<> 144:ef7eb2e8f9f7 257
<> 144:ef7eb2e8f9f7 258 i2c_start(obj);
<> 144:ef7eb2e8f9f7 259
<> 144:ef7eb2e8f9f7 260 retval = i2c_byte_write(obj, (address | 1));
<> 144:ef7eb2e8f9f7 261 if ((!retval) || (length == 0)) { //Write address with W flag (last bit 1)
<> 144:ef7eb2e8f9f7 262 obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
<> 144:ef7eb2e8f9f7 263 while(obj->i2c.i2c->STATE & I2C_STATE_BUSY); // Wait until the bus is done
<> 144:ef7eb2e8f9f7 264 return (retval == 0 ? I2C_ERROR_NO_SLAVE : 0); //NACK or error when writing adress. Return 0 as 0 bytes were read
<> 144:ef7eb2e8f9f7 265 }
<> 144:ef7eb2e8f9f7 266 int i = 0;
<> 144:ef7eb2e8f9f7 267 while (i < length) {
<> 144:ef7eb2e8f9f7 268 uint8_t last = (i == length - 1);
<> 144:ef7eb2e8f9f7 269 data[i++] = i2c_byte_read(obj, last);
<> 144:ef7eb2e8f9f7 270 }
<> 144:ef7eb2e8f9f7 271
<> 144:ef7eb2e8f9f7 272 if (stop) {
<> 144:ef7eb2e8f9f7 273 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 274 }
<> 144:ef7eb2e8f9f7 275
<> 144:ef7eb2e8f9f7 276 return length;
<> 144:ef7eb2e8f9f7 277 }
<> 144:ef7eb2e8f9f7 278
<> 144:ef7eb2e8f9f7 279 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
<> 144:ef7eb2e8f9f7 280 {
<> 144:ef7eb2e8f9f7 281 i2c_start(obj);
<> 144:ef7eb2e8f9f7 282
<> 144:ef7eb2e8f9f7 283 if (!i2c_byte_write(obj, (address & 0xFE))) {
<> 144:ef7eb2e8f9f7 284 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 285 return I2C_ERROR_NO_SLAVE; //NACK or error when writing adress. Return 0 as 0 bytes were written
<> 144:ef7eb2e8f9f7 286 }
<> 144:ef7eb2e8f9f7 287 int i;
<> 144:ef7eb2e8f9f7 288 for (i = 0; i < length; i++) {
<> 144:ef7eb2e8f9f7 289 if (!i2c_byte_write(obj, data[i])) {
<> 144:ef7eb2e8f9f7 290 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 291 return i;
<> 144:ef7eb2e8f9f7 292 }
<> 144:ef7eb2e8f9f7 293 }
<> 144:ef7eb2e8f9f7 294
<> 144:ef7eb2e8f9f7 295 if (stop) {
<> 144:ef7eb2e8f9f7 296 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 297 }
<> 144:ef7eb2e8f9f7 298
<> 144:ef7eb2e8f9f7 299 return length;
<> 144:ef7eb2e8f9f7 300 }
<> 144:ef7eb2e8f9f7 301
<> 144:ef7eb2e8f9f7 302 void i2c_reset(i2c_t *obj)
<> 144:ef7eb2e8f9f7 303 {
<> 144:ef7eb2e8f9f7 304 /* EMLib function */
<> 144:ef7eb2e8f9f7 305 I2C_Reset(obj->i2c.i2c);
<> 144:ef7eb2e8f9f7 306 }
<> 144:ef7eb2e8f9f7 307
<> 144:ef7eb2e8f9f7 308 int i2c_byte_read(i2c_t *obj, int last)
<> 144:ef7eb2e8f9f7 309 {
<> 144:ef7eb2e8f9f7 310 int timeout = I2C_TIMEOUT;
<> 144:ef7eb2e8f9f7 311 /* Wait for data */
<> 144:ef7eb2e8f9f7 312 while (!(obj->i2c.i2c->STATUS & I2C_STATUS_RXDATAV) && timeout--);
<> 144:ef7eb2e8f9f7 313
<> 144:ef7eb2e8f9f7 314 if (timeout <= 0) {
<> 144:ef7eb2e8f9f7 315 return 0; //TODO Is this the correct way to handle this?
<> 144:ef7eb2e8f9f7 316 }
<> 144:ef7eb2e8f9f7 317 char data = obj->i2c.i2c->RXDATA;
<> 144:ef7eb2e8f9f7 318
<> 144:ef7eb2e8f9f7 319 if (last) {
<> 144:ef7eb2e8f9f7 320 obj->i2c.i2c->CMD = I2C_CMD_NACK;
<> 144:ef7eb2e8f9f7 321 } else {
<> 144:ef7eb2e8f9f7 322 obj->i2c.i2c->CMD = I2C_CMD_ACK;
<> 144:ef7eb2e8f9f7 323 }
<> 144:ef7eb2e8f9f7 324 return data;
<> 144:ef7eb2e8f9f7 325 }
<> 144:ef7eb2e8f9f7 326
<> 144:ef7eb2e8f9f7 327 int i2c_byte_write(i2c_t *obj, int data)
<> 144:ef7eb2e8f9f7 328 {
<> 144:ef7eb2e8f9f7 329 obj->i2c.i2c->TXDATA = data;
<> 144:ef7eb2e8f9f7 330 return block_and_wait_for_ack(obj->i2c.i2c);
<> 144:ef7eb2e8f9f7 331 }
<> 144:ef7eb2e8f9f7 332
<> 144:ef7eb2e8f9f7 333 /*
<> 144:ef7eb2e8f9f7 334 * Returns 1 for ACK. 0 for NACK, timeout or error.
<> 144:ef7eb2e8f9f7 335 */
<> 144:ef7eb2e8f9f7 336 int block_and_wait_for_ack(I2C_TypeDef *i2c)
<> 144:ef7eb2e8f9f7 337 {
<> 144:ef7eb2e8f9f7 338 uint32_t pending;
<> 144:ef7eb2e8f9f7 339 uint32_t timeout = I2C_TIMEOUT;
<> 144:ef7eb2e8f9f7 340 while (timeout > 0) {
<> 144:ef7eb2e8f9f7 341 timeout -= 1;
<> 144:ef7eb2e8f9f7 342 pending = i2c->IF;
<> 144:ef7eb2e8f9f7 343 /* If some sort of fault, abort transfer. */
<> 144:ef7eb2e8f9f7 344 if (pending & I2C_IF_ERRORS) {
<> 144:ef7eb2e8f9f7 345 if (pending & I2C_IF_ARBLOST) {
<> 144:ef7eb2e8f9f7 346 /* If arbitration fault, it indicates either a slave device */
<> 144:ef7eb2e8f9f7 347 /* not responding as expected, or other master which is not */
<> 144:ef7eb2e8f9f7 348 /* supported by this SW. */
<> 144:ef7eb2e8f9f7 349 return 0;
<> 144:ef7eb2e8f9f7 350 } else if (pending & I2C_IF_BUSERR) {
<> 144:ef7eb2e8f9f7 351 /* A bus error indicates a misplaced start or stop, which should */
<> 144:ef7eb2e8f9f7 352 /* not occur in master mode controlled by this SW. */
<> 144:ef7eb2e8f9f7 353 return 0;
<> 144:ef7eb2e8f9f7 354 }
<> 144:ef7eb2e8f9f7 355 }
<> 144:ef7eb2e8f9f7 356
<> 144:ef7eb2e8f9f7 357 if (pending & I2C_IF_NACK) {
<> 144:ef7eb2e8f9f7 358 i2c->IFC = I2C_IFC_NACK;
<> 144:ef7eb2e8f9f7 359 return 0; //Received NACK
<> 144:ef7eb2e8f9f7 360 } else if (pending & I2C_IF_ACK) {
<> 144:ef7eb2e8f9f7 361 i2c->IFC = I2C_IFC_ACK;
<> 144:ef7eb2e8f9f7 362 return 1; //Got ACK
<> 144:ef7eb2e8f9f7 363 }
<> 144:ef7eb2e8f9f7 364 }
<> 144:ef7eb2e8f9f7 365 return 0; //Timeout
<> 144:ef7eb2e8f9f7 366 }
<> 144:ef7eb2e8f9f7 367
<> 144:ef7eb2e8f9f7 368 #if DEVICE_I2CSLAVE
<> 144:ef7eb2e8f9f7 369
<> 144:ef7eb2e8f9f7 370 #define NoData 0
<> 144:ef7eb2e8f9f7 371 #define ReadAddressed 1
<> 144:ef7eb2e8f9f7 372 #define WriteGeneral 2
<> 144:ef7eb2e8f9f7 373 #define WriteAddressed 3
<> 144:ef7eb2e8f9f7 374
<> 144:ef7eb2e8f9f7 375
<> 144:ef7eb2e8f9f7 376 void i2c_slave_mode(i2c_t *obj, int enable_slave)
<> 144:ef7eb2e8f9f7 377 {
<> 144:ef7eb2e8f9f7 378 if(enable_slave) {
<> 144:ef7eb2e8f9f7 379 /* Reference manual note: DIV must be set to 1 during slave operation */
<> 144:ef7eb2e8f9f7 380 obj->i2c.i2c->CLKDIV = 1;
<> 144:ef7eb2e8f9f7 381 obj->i2c.i2c->CTRL |= _I2C_CTRL_SLAVE_MASK;
<> 144:ef7eb2e8f9f7 382 obj->i2c.i2c->CTRL |= _I2C_CTRL_AUTOACK_MASK; //Slave implementation assumes auto acking
<> 144:ef7eb2e8f9f7 383 } else {
<> 144:ef7eb2e8f9f7 384 obj->i2c.i2c->CTRL &= ~_I2C_CTRL_SLAVE_MASK;
<> 144:ef7eb2e8f9f7 385 obj->i2c.i2c->CTRL &= ~_I2C_CTRL_AUTOACK_MASK; //Master implementation ACKs manually
<> 144:ef7eb2e8f9f7 386 /* function is only called with enable_slave = false through i2c_init(..), so frequency is
<> 144:ef7eb2e8f9f7 387 already guaranteed to be set */
<> 144:ef7eb2e8f9f7 388 }
<> 144:ef7eb2e8f9f7 389 }
<> 144:ef7eb2e8f9f7 390
<> 144:ef7eb2e8f9f7 391 int i2c_slave_receive(i2c_t *obj)
<> 144:ef7eb2e8f9f7 392 {
<> 144:ef7eb2e8f9f7 393
<> 144:ef7eb2e8f9f7 394 if(obj->i2c.i2c->IF & I2C_IF_ADDR) {
<> 144:ef7eb2e8f9f7 395 obj->i2c.i2c->IFC = I2C_IF_ADDR; //Clear interrupt
<> 144:ef7eb2e8f9f7 396 /*0x00 is the address for general write.
<> 144:ef7eb2e8f9f7 397 The address the master wrote is in RXDATA now
<> 144:ef7eb2e8f9f7 398 and reading it also frees the buffer for the next
<> 144:ef7eb2e8f9f7 399 write which can then be acked. */
<> 144:ef7eb2e8f9f7 400 if(obj->i2c.i2c->RXDATA == 0x00) {
<> 144:ef7eb2e8f9f7 401 return WriteGeneral; //Read the address;
<> 144:ef7eb2e8f9f7 402 }
<> 144:ef7eb2e8f9f7 403
<> 144:ef7eb2e8f9f7 404 if(obj->i2c.i2c->STATE & I2C_STATE_TRANSMITTER) {
<> 144:ef7eb2e8f9f7 405 return ReadAddressed;
<> 144:ef7eb2e8f9f7 406 } else {
<> 144:ef7eb2e8f9f7 407 return WriteAddressed;
<> 144:ef7eb2e8f9f7 408 }
<> 144:ef7eb2e8f9f7 409 }
<> 144:ef7eb2e8f9f7 410
<> 144:ef7eb2e8f9f7 411 return NoData;
<> 144:ef7eb2e8f9f7 412
<> 144:ef7eb2e8f9f7 413 }
<> 144:ef7eb2e8f9f7 414
<> 144:ef7eb2e8f9f7 415 int i2c_slave_read(i2c_t *obj, char *data, int length)
<> 144:ef7eb2e8f9f7 416 {
<> 144:ef7eb2e8f9f7 417 int count;
<> 144:ef7eb2e8f9f7 418 for (count = 0; count < length; count++) {
<> 144:ef7eb2e8f9f7 419 data[count] = i2c_byte_read(obj, 0);
<> 144:ef7eb2e8f9f7 420 }
<> 144:ef7eb2e8f9f7 421
<> 144:ef7eb2e8f9f7 422 return count;
<> 144:ef7eb2e8f9f7 423
<> 144:ef7eb2e8f9f7 424 }
<> 144:ef7eb2e8f9f7 425
<> 144:ef7eb2e8f9f7 426 int i2c_slave_write(i2c_t *obj, const char *data, int length)
<> 144:ef7eb2e8f9f7 427 {
<> 144:ef7eb2e8f9f7 428 int count;
<> 144:ef7eb2e8f9f7 429 for (count = 0; count < length; count++) {
<> 144:ef7eb2e8f9f7 430 i2c_byte_write(obj, data[count]);
<> 144:ef7eb2e8f9f7 431 }
<> 144:ef7eb2e8f9f7 432
<> 144:ef7eb2e8f9f7 433 return count;
<> 144:ef7eb2e8f9f7 434 }
<> 144:ef7eb2e8f9f7 435
<> 144:ef7eb2e8f9f7 436 void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask)
<> 144:ef7eb2e8f9f7 437 {
<> 144:ef7eb2e8f9f7 438 obj->i2c.i2c->SADDR = address;
<> 144:ef7eb2e8f9f7 439 obj->i2c.i2c->SADDRMASK = 0xFE;//mask;
<> 144:ef7eb2e8f9f7 440 }
<> 144:ef7eb2e8f9f7 441
<> 144:ef7eb2e8f9f7 442 #endif //DEVICE_I2CSLAVE
<> 144:ef7eb2e8f9f7 443
AnnaBridge 189:f392fc9709a3 444 #if DEVICE_I2C_ASYNCH
<> 144:ef7eb2e8f9f7 445
<> 144:ef7eb2e8f9f7 446 #include "em_dma.h"
<> 144:ef7eb2e8f9f7 447 #include "dma_api_HAL.h"
<> 144:ef7eb2e8f9f7 448 #include "dma_api.h"
<> 144:ef7eb2e8f9f7 449 #include "sleep_api.h"
<> 144:ef7eb2e8f9f7 450 #include "buffer.h"
<> 144:ef7eb2e8f9f7 451
<> 144:ef7eb2e8f9f7 452 /** Start i2c asynchronous transfer.
<> 144:ef7eb2e8f9f7 453 * @param obj The I2C object
<> 144:ef7eb2e8f9f7 454 * @param tx The buffer to send
<> 144:ef7eb2e8f9f7 455 * @param tx_length The number of words to transmit
<> 144:ef7eb2e8f9f7 456 * @param rx The buffer to receive
<> 144:ef7eb2e8f9f7 457 * @param rx_length The number of words to receive
<> 144:ef7eb2e8f9f7 458 * @param address The address to be set - 7bit or 9 bit
<> 144:ef7eb2e8f9f7 459 * @param stop If true, stop will be generated after the transfer is done
<> 144:ef7eb2e8f9f7 460 * @param handler The I2C IRQ handler to be set
<> 144:ef7eb2e8f9f7 461 * @param hint DMA hint usage
<> 144:ef7eb2e8f9f7 462 */
<> 144:ef7eb2e8f9f7 463 void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t address, uint32_t stop, uint32_t handler, uint32_t event, DMAUsage hint)
<> 144:ef7eb2e8f9f7 464 {
<> 144:ef7eb2e8f9f7 465 I2C_TransferReturn_TypeDef retval;
<> 144:ef7eb2e8f9f7 466 if(i2c_active(obj)) return;
<> 144:ef7eb2e8f9f7 467 if((tx_length == 0) && (rx_length == 0)) return;
<> 144:ef7eb2e8f9f7 468 // For now, we are assuming a solely interrupt-driven implementation.
<> 144:ef7eb2e8f9f7 469
Anna Bridge 163:74e0ce7f98e8 470 #ifdef I2C_ROUTE_SDAPEN
Anna Bridge 163:74e0ce7f98e8 471 obj->i2c.i2c->ROUTE = obj->i2c.location;
Anna Bridge 163:74e0ce7f98e8 472 #else
Anna Bridge 163:74e0ce7f98e8 473 obj->i2c.i2c->ROUTELOC0 = obj->i2c.location;
Anna Bridge 163:74e0ce7f98e8 474 #endif
Anna Bridge 163:74e0ce7f98e8 475
<> 144:ef7eb2e8f9f7 476 // Store transfer config
<> 144:ef7eb2e8f9f7 477 obj->i2c.xfer.addr = address;
<> 144:ef7eb2e8f9f7 478
<> 144:ef7eb2e8f9f7 479 // Some combination of tx_length and rx_length will tell us what to do
<> 144:ef7eb2e8f9f7 480 if((tx_length > 0) && (rx_length == 0)) {
<> 144:ef7eb2e8f9f7 481 obj->i2c.xfer.flags = I2C_FLAG_WRITE;
<> 144:ef7eb2e8f9f7 482 //Store buffer info
<> 144:ef7eb2e8f9f7 483 obj->i2c.xfer.buf[0].data = (void *)tx;
<> 144:ef7eb2e8f9f7 484 obj->i2c.xfer.buf[0].len = (uint16_t) tx_length;
<> 144:ef7eb2e8f9f7 485 } else if ((tx_length == 0) && (rx_length > 0)) {
<> 144:ef7eb2e8f9f7 486 obj->i2c.xfer.flags = I2C_FLAG_READ;
<> 144:ef7eb2e8f9f7 487 //Store buffer info
<> 144:ef7eb2e8f9f7 488 obj->i2c.xfer.buf[0].data = rx;
<> 144:ef7eb2e8f9f7 489 obj->i2c.xfer.buf[0].len = (uint16_t) rx_length;
<> 144:ef7eb2e8f9f7 490 } else if ((tx_length > 0) && (rx_length > 0)) {
<> 144:ef7eb2e8f9f7 491 obj->i2c.xfer.flags = I2C_FLAG_WRITE_READ;
<> 144:ef7eb2e8f9f7 492 //Store buffer info
<> 144:ef7eb2e8f9f7 493 obj->i2c.xfer.buf[0].data = (void *)tx;
<> 144:ef7eb2e8f9f7 494 obj->i2c.xfer.buf[0].len = (uint16_t) tx_length;
<> 144:ef7eb2e8f9f7 495 obj->i2c.xfer.buf[1].data = rx;
<> 144:ef7eb2e8f9f7 496 obj->i2c.xfer.buf[1].len = (uint16_t) rx_length;
<> 144:ef7eb2e8f9f7 497 }
<> 144:ef7eb2e8f9f7 498
<> 144:ef7eb2e8f9f7 499 if(address > 255) obj->i2c.xfer.flags |= I2C_FLAG_10BIT_ADDR;
<> 144:ef7eb2e8f9f7 500
<> 144:ef7eb2e8f9f7 501 // Store event flags
<> 144:ef7eb2e8f9f7 502 obj->i2c.events = event;
<> 144:ef7eb2e8f9f7 503
<> 144:ef7eb2e8f9f7 504 // Enable interrupt
<> 144:ef7eb2e8f9f7 505 i2c_enable_interrupt(obj, handler, true);
<> 144:ef7eb2e8f9f7 506
<> 144:ef7eb2e8f9f7 507 // Kick off the transfer
<> 144:ef7eb2e8f9f7 508 retval = I2C_TransferInit(obj->i2c.i2c, &(obj->i2c.xfer));
<> 144:ef7eb2e8f9f7 509
<> 144:ef7eb2e8f9f7 510 if(retval == i2cTransferInProgress) {
Anna Bridge 180:96ed750bd169 511 sleep_manager_lock_deep_sleep();
<> 144:ef7eb2e8f9f7 512 } else {
<> 144:ef7eb2e8f9f7 513 // something happened, and the transfer did not go through
<> 144:ef7eb2e8f9f7 514 // So, we need to clean up
<> 144:ef7eb2e8f9f7 515
<> 144:ef7eb2e8f9f7 516 // Disable interrupt
<> 144:ef7eb2e8f9f7 517 i2c_enable_interrupt(obj, 0, false);
<> 144:ef7eb2e8f9f7 518
<> 144:ef7eb2e8f9f7 519 // Block until free
<> 144:ef7eb2e8f9f7 520 while(i2c_active(obj));
<> 144:ef7eb2e8f9f7 521 }
<> 144:ef7eb2e8f9f7 522 }
<> 144:ef7eb2e8f9f7 523
<> 144:ef7eb2e8f9f7 524 /** The asynchronous IRQ handler
<> 144:ef7eb2e8f9f7 525 * @param obj The I2C object which holds the transfer information
<> 144:ef7eb2e8f9f7 526 * @return Returns event flags if a transfer termination condition was met or 0 otherwise.
<> 144:ef7eb2e8f9f7 527 */
<> 144:ef7eb2e8f9f7 528 uint32_t i2c_irq_handler_asynch(i2c_t *obj)
<> 144:ef7eb2e8f9f7 529 {
<> 144:ef7eb2e8f9f7 530
<> 144:ef7eb2e8f9f7 531 // For now, we are assuming a solely interrupt-driven implementation.
<> 144:ef7eb2e8f9f7 532
<> 144:ef7eb2e8f9f7 533 I2C_TransferReturn_TypeDef status = I2C_Transfer(obj->i2c.i2c);
<> 144:ef7eb2e8f9f7 534 switch(status) {
<> 144:ef7eb2e8f9f7 535 case i2cTransferInProgress:
<> 144:ef7eb2e8f9f7 536 // Still busy transferring, so let it.
<> 144:ef7eb2e8f9f7 537 return 0;
<> 144:ef7eb2e8f9f7 538 case i2cTransferDone:
<> 144:ef7eb2e8f9f7 539 // Transfer has completed
<> 144:ef7eb2e8f9f7 540
<> 144:ef7eb2e8f9f7 541 // Disable interrupt
<> 144:ef7eb2e8f9f7 542 i2c_enable_interrupt(obj, 0, false);
<> 144:ef7eb2e8f9f7 543
Anna Bridge 180:96ed750bd169 544 sleep_manager_unlock_deep_sleep();
<> 144:ef7eb2e8f9f7 545
<> 144:ef7eb2e8f9f7 546 return I2C_EVENT_TRANSFER_COMPLETE & obj->i2c.events;
<> 144:ef7eb2e8f9f7 547 case i2cTransferNack:
<> 144:ef7eb2e8f9f7 548 // A NACK has been received while an ACK was expected. This is usually because the slave did not respond to the address.
<> 144:ef7eb2e8f9f7 549 // Disable interrupt
<> 144:ef7eb2e8f9f7 550 i2c_enable_interrupt(obj, 0, false);
<> 144:ef7eb2e8f9f7 551
Anna Bridge 180:96ed750bd169 552 sleep_manager_unlock_deep_sleep();
<> 144:ef7eb2e8f9f7 553
<> 144:ef7eb2e8f9f7 554 return I2C_EVENT_ERROR_NO_SLAVE & obj->i2c.events;
<> 144:ef7eb2e8f9f7 555 default:
<> 144:ef7eb2e8f9f7 556 // An error situation has arisen.
<> 144:ef7eb2e8f9f7 557 // Disable interrupt
<> 144:ef7eb2e8f9f7 558 i2c_enable_interrupt(obj, 0, false);
<> 144:ef7eb2e8f9f7 559
Anna Bridge 180:96ed750bd169 560 sleep_manager_unlock_deep_sleep();
<> 144:ef7eb2e8f9f7 561
<> 144:ef7eb2e8f9f7 562 // return error
<> 144:ef7eb2e8f9f7 563 return I2C_EVENT_ERROR & obj->i2c.events;
<> 144:ef7eb2e8f9f7 564 }
<> 144:ef7eb2e8f9f7 565 }
<> 144:ef7eb2e8f9f7 566
<> 144:ef7eb2e8f9f7 567 /** Attempts to determine if I2C peripheral is already in use.
<> 144:ef7eb2e8f9f7 568 * @param obj The I2C object
<> 144:ef7eb2e8f9f7 569 * @return non-zero if the I2C module is active or zero if it is not
<> 144:ef7eb2e8f9f7 570 */
<> 144:ef7eb2e8f9f7 571 uint8_t i2c_active(i2c_t *obj)
<> 144:ef7eb2e8f9f7 572 {
<> 144:ef7eb2e8f9f7 573 return (obj->i2c.i2c->STATE & I2C_STATE_BUSY);
<> 144:ef7eb2e8f9f7 574 }
<> 144:ef7eb2e8f9f7 575
<> 144:ef7eb2e8f9f7 576 /** Abort ongoing asynchronous transaction.
<> 144:ef7eb2e8f9f7 577 * @param obj The I2C object
<> 144:ef7eb2e8f9f7 578 */
<> 144:ef7eb2e8f9f7 579 void i2c_abort_asynch(i2c_t *obj)
<> 144:ef7eb2e8f9f7 580 {
Anna Bridge 180:96ed750bd169 581 // Disable interrupt
Anna Bridge 180:96ed750bd169 582 i2c_enable_interrupt(obj, 0, false);
Anna Bridge 180:96ed750bd169 583
<> 144:ef7eb2e8f9f7 584 // Do not deactivate I2C twice
<> 144:ef7eb2e8f9f7 585 if (!i2c_active(obj)) return;
<> 144:ef7eb2e8f9f7 586
<> 144:ef7eb2e8f9f7 587 // Abort
<> 144:ef7eb2e8f9f7 588 obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
<> 144:ef7eb2e8f9f7 589
<> 144:ef7eb2e8f9f7 590 // Block until free
<> 144:ef7eb2e8f9f7 591 while(i2c_active(obj));
<> 144:ef7eb2e8f9f7 592
Anna Bridge 180:96ed750bd169 593 sleep_manager_unlock_deep_sleep();
<> 144:ef7eb2e8f9f7 594 }
<> 144:ef7eb2e8f9f7 595
<> 144:ef7eb2e8f9f7 596 #endif //DEVICE_I2C ASYNCH
<> 144:ef7eb2e8f9f7 597 #endif //DEVICE_I2C