mbed library sources. Supersedes mbed-src.

Fork of mbed-dev by mbed official

Committer:
fwndz
Date:
Thu Dec 22 05:12:40 2016 +0000
Revision:
153:9398a535854b
Parent:
149:156823d33999
device target maximize

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"
<> 144:ef7eb2e8f9f7 31 #include "i2c_api.h"
<> 144:ef7eb2e8f9f7 32 #include "PeripheralPins.h"
<> 144:ef7eb2e8f9f7 33 #include "pinmap_function.h"
<> 144:ef7eb2e8f9f7 34 #include "sleepmodes.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);
<> 144:ef7eb2e8f9f7 102 MBED_ASSERT(((int) obj->i2c.i2c) != NC);
<> 144:ef7eb2e8f9f7 103
<> 144:ef7eb2e8f9f7 104 /* You need both SDA and SCL for I2C, so configuring one of them to NC is illegal */
<> 144:ef7eb2e8f9f7 105 MBED_ASSERT((uint32_t)sda != (uint32_t)NC);
<> 144:ef7eb2e8f9f7 106 MBED_ASSERT((uint32_t)scl != (uint32_t)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 */
<> 144:ef7eb2e8f9f7 119 int loc_sda = pin_location(sda, PinMap_I2C_SDA);
<> 144:ef7eb2e8f9f7 120 int loc_scl = pin_location(scl, PinMap_I2C_SCL);
<> 144:ef7eb2e8f9f7 121 int loc = pinmap_merge(loc_sda, loc_scl);
<> 144:ef7eb2e8f9f7 122 MBED_ASSERT(loc != NC);
<> 144:ef7eb2e8f9f7 123 /* Set location */
<> 144:ef7eb2e8f9f7 124 obj->i2c.i2c->ROUTE = I2C_ROUTE_SDAPEN | I2C_ROUTE_SCLPEN | (loc << _I2C_ROUTE_LOCATION_SHIFT);
<> 144:ef7eb2e8f9f7 125 #else
<> 144:ef7eb2e8f9f7 126 obj->i2c.i2c->ROUTEPEN = I2C_ROUTEPEN_SDAPEN | I2C_ROUTEPEN_SCLPEN;
<> 144:ef7eb2e8f9f7 127 obj->i2c.i2c->ROUTELOC0 = (pin_location(sda, PinMap_I2C_SDA) << _I2C_ROUTELOC0_SDALOC_SHIFT) |
<> 144:ef7eb2e8f9f7 128 (pin_location(scl, PinMap_I2C_SCL) << _I2C_ROUTELOC0_SCLLOC_SHIFT);
<> 144:ef7eb2e8f9f7 129 #endif
<> 144:ef7eb2e8f9f7 130
<> 144:ef7eb2e8f9f7 131 /* Set up the pins for I2C use */
<> 144:ef7eb2e8f9f7 132 /* Note: Set up pins in higher drive strength to reduce slew rate */
<> 144:ef7eb2e8f9f7 133 /* Though this requires user knowledge, since drive strength is controlled per port, not pin */
<> 144:ef7eb2e8f9f7 134 pin_mode(scl, WiredAndPullUp);
<> 144:ef7eb2e8f9f7 135 pin_mode(sda, WiredAndPullUp);
<> 144:ef7eb2e8f9f7 136
<> 144:ef7eb2e8f9f7 137 /* Enable General Call Address Mode. That is; we respond to the general address (0x0) */
<> 144:ef7eb2e8f9f7 138 obj->i2c.i2c->CTRL |= _I2C_CTRL_GCAMEN_MASK;
<> 144:ef7eb2e8f9f7 139
<> 144:ef7eb2e8f9f7 140 /* We are assuming that there is only one master. So disable automatic arbitration */
<> 144:ef7eb2e8f9f7 141 obj->i2c.i2c->CTRL |= _I2C_CTRL_ARBDIS_MASK;
<> 144:ef7eb2e8f9f7 142
<> 144:ef7eb2e8f9f7 143 /* Set to master (needed if this I2C block was used previously as slave) */
<> 144:ef7eb2e8f9f7 144 i2c_slave_mode(obj, false);
<> 144:ef7eb2e8f9f7 145
<> 144:ef7eb2e8f9f7 146 /* Enable i2c */
<> 144:ef7eb2e8f9f7 147 i2c_enable(obj, true);
<> 144:ef7eb2e8f9f7 148 }
<> 144:ef7eb2e8f9f7 149
<> 144:ef7eb2e8f9f7 150 void i2c_enable(i2c_t *obj, uint8_t enable)
<> 144:ef7eb2e8f9f7 151 {
<> 144:ef7eb2e8f9f7 152 I2C_Enable(obj->i2c.i2c, enable);
<> 144:ef7eb2e8f9f7 153 if (!enable) {
<> 144:ef7eb2e8f9f7 154 /* After a reset BUSY is usually set. We assume that we are the only master and call abort,
<> 144:ef7eb2e8f9f7 155 * which sends nothing on the bus, it just allows us to assume that the bus is idle */
<> 144:ef7eb2e8f9f7 156 if (obj->i2c.i2c->STATE & I2C_STATE_BUSY) {
<> 144:ef7eb2e8f9f7 157 obj->i2c.i2c->CMD = I2C_CMD_ABORT;
<> 144:ef7eb2e8f9f7 158 }
<> 144:ef7eb2e8f9f7 159 }
<> 144:ef7eb2e8f9f7 160 }
<> 144:ef7eb2e8f9f7 161
<> 144:ef7eb2e8f9f7 162 void i2c_enable_interrupt(i2c_t *obj, uint32_t address, uint8_t enable)
<> 144:ef7eb2e8f9f7 163 {
<> 144:ef7eb2e8f9f7 164 IRQn_Type irq_number;
<> 144:ef7eb2e8f9f7 165
<> 144:ef7eb2e8f9f7 166 switch (i2c_get_index(obj)) {
<> 144:ef7eb2e8f9f7 167 #ifdef I2C0
<> 144:ef7eb2e8f9f7 168 case 0:
<> 144:ef7eb2e8f9f7 169 irq_number = I2C0_IRQn;
<> 144:ef7eb2e8f9f7 170 break;
<> 144:ef7eb2e8f9f7 171 #endif
<> 144:ef7eb2e8f9f7 172 #ifdef I2C1
<> 144:ef7eb2e8f9f7 173 case 1:
<> 144:ef7eb2e8f9f7 174 irq_number = I2C1_IRQn;
<> 144:ef7eb2e8f9f7 175 break;
<> 144:ef7eb2e8f9f7 176 #endif
<> 144:ef7eb2e8f9f7 177 }
<> 144:ef7eb2e8f9f7 178
<> 144:ef7eb2e8f9f7 179 NVIC_SetVector(irq_number, address);
<> 144:ef7eb2e8f9f7 180 /* Lower IRQ priority to avoid messing with asynch RX on UART */
<> 144:ef7eb2e8f9f7 181 NVIC_SetPriority(irq_number, 1);
<> 144:ef7eb2e8f9f7 182 if (enable) {
<> 144:ef7eb2e8f9f7 183 NVIC_EnableIRQ(irq_number);
<> 144:ef7eb2e8f9f7 184 } else {
<> 144:ef7eb2e8f9f7 185 NVIC_DisableIRQ(irq_number);
<> 144:ef7eb2e8f9f7 186 }
<> 144:ef7eb2e8f9f7 187 }
<> 144:ef7eb2e8f9f7 188
<> 144:ef7eb2e8f9f7 189 /* Set the frequency of the I2C interface */
<> 144:ef7eb2e8f9f7 190 void i2c_frequency(i2c_t *obj, int hz)
<> 144:ef7eb2e8f9f7 191 {
<> 144:ef7eb2e8f9f7 192 /* Set frequency. As the second argument is 0,
<> 144:ef7eb2e8f9f7 193 * HFPER clock frequency is used as reference freq */
<> 144:ef7eb2e8f9f7 194 if (hz <= 0) return;
<> 144:ef7eb2e8f9f7 195 /* In I2C Normal mode (50% duty), we can go up to 100kHz */
<> 144:ef7eb2e8f9f7 196 if (hz <= 100000) {
<> 144:ef7eb2e8f9f7 197 I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRStandard);
<> 144:ef7eb2e8f9f7 198 }
<> 144:ef7eb2e8f9f7 199 /* In I2C Fast mode (6:3 ratio), we can go up to 400kHz */
<> 144:ef7eb2e8f9f7 200 else if (hz <= 400000) {
<> 144:ef7eb2e8f9f7 201 I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRAsymetric);
<> 144:ef7eb2e8f9f7 202 }
<> 144:ef7eb2e8f9f7 203 /* In I2C Fast+ mode (11:6 ratio), we can go up to 1 MHz */
<> 144:ef7eb2e8f9f7 204 else if (hz <= 1000000) {
<> 144:ef7eb2e8f9f7 205 I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRFast);
<> 144:ef7eb2e8f9f7 206 }
<> 144:ef7eb2e8f9f7 207 /* Cap requested frequency at 1MHz */
<> 144:ef7eb2e8f9f7 208 else {
<> 144:ef7eb2e8f9f7 209 I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, 1000000, i2cClockHLRFast);
<> 144:ef7eb2e8f9f7 210 }
<> 144:ef7eb2e8f9f7 211 }
<> 144:ef7eb2e8f9f7 212
<> 144:ef7eb2e8f9f7 213 /* Creates a start condition on the I2C bus */
<> 144:ef7eb2e8f9f7 214 int i2c_start(i2c_t *obj)
<> 144:ef7eb2e8f9f7 215 {
<> 144:ef7eb2e8f9f7 216 I2C_TypeDef *i2c = obj->i2c.i2c;
<> 144:ef7eb2e8f9f7 217
<> 144:ef7eb2e8f9f7 218 /* Ensure buffers are empty */
<> 144:ef7eb2e8f9f7 219 i2c->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;
<> 144:ef7eb2e8f9f7 220 if (i2c->IF & I2C_IF_RXDATAV) {
<> 144:ef7eb2e8f9f7 221 (void) i2c->RXDATA;
<> 144:ef7eb2e8f9f7 222 }
<> 144:ef7eb2e8f9f7 223
<> 144:ef7eb2e8f9f7 224 /* Clear all pending interrupts prior to starting transfer. */
<> 144:ef7eb2e8f9f7 225 i2c->IFC = _I2C_IFC_MASK;
<> 144:ef7eb2e8f9f7 226
<> 144:ef7eb2e8f9f7 227 /* Send start */
<> 144:ef7eb2e8f9f7 228 obj->i2c.i2c->CMD = I2C_CMD_START;
<> 144:ef7eb2e8f9f7 229 return 0;
<> 144:ef7eb2e8f9f7 230 }
<> 144:ef7eb2e8f9f7 231
<> 144:ef7eb2e8f9f7 232 /* Creates a stop condition on the I2C bus */
<> 144:ef7eb2e8f9f7 233 int i2c_stop(i2c_t *obj)
<> 144:ef7eb2e8f9f7 234 {
<> 144:ef7eb2e8f9f7 235 obj->i2c.i2c->CMD = I2C_CMD_STOP;
<> 144:ef7eb2e8f9f7 236
<> 144:ef7eb2e8f9f7 237 /* Wait for the stop to be sent */
<> 144:ef7eb2e8f9f7 238 int timeout = I2C_TIMEOUT;
<> 144:ef7eb2e8f9f7 239 while (!(obj->i2c.i2c->IF & I2C_IF_MSTOP) && !timeout--);
<> 144:ef7eb2e8f9f7 240
<> 144:ef7eb2e8f9f7 241 return 0;
<> 144:ef7eb2e8f9f7 242 }
<> 144:ef7eb2e8f9f7 243
<> 144:ef7eb2e8f9f7 244 /* Returns number of bytes read */
<> 144:ef7eb2e8f9f7 245 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
<> 144:ef7eb2e8f9f7 246 {
<> 144:ef7eb2e8f9f7 247 int retval;
<> 144:ef7eb2e8f9f7 248
<> 144:ef7eb2e8f9f7 249 i2c_start(obj);
<> 144:ef7eb2e8f9f7 250
<> 144:ef7eb2e8f9f7 251 retval = i2c_byte_write(obj, (address | 1));
<> 144:ef7eb2e8f9f7 252 if ((!retval) || (length == 0)) { //Write address with W flag (last bit 1)
<> 144:ef7eb2e8f9f7 253 obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
<> 144:ef7eb2e8f9f7 254 while(obj->i2c.i2c->STATE & I2C_STATE_BUSY); // Wait until the bus is done
<> 144:ef7eb2e8f9f7 255 return (retval == 0 ? I2C_ERROR_NO_SLAVE : 0); //NACK or error when writing adress. Return 0 as 0 bytes were read
<> 144:ef7eb2e8f9f7 256 }
<> 144:ef7eb2e8f9f7 257 int i = 0;
<> 144:ef7eb2e8f9f7 258 while (i < length) {
<> 144:ef7eb2e8f9f7 259 uint8_t last = (i == length - 1);
<> 144:ef7eb2e8f9f7 260 data[i++] = i2c_byte_read(obj, last);
<> 144:ef7eb2e8f9f7 261 }
<> 144:ef7eb2e8f9f7 262
<> 144:ef7eb2e8f9f7 263 if (stop) {
<> 144:ef7eb2e8f9f7 264 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 265 }
<> 144:ef7eb2e8f9f7 266
<> 144:ef7eb2e8f9f7 267 return length;
<> 144:ef7eb2e8f9f7 268 }
<> 144:ef7eb2e8f9f7 269
<> 144:ef7eb2e8f9f7 270 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
<> 144:ef7eb2e8f9f7 271 {
<> 144:ef7eb2e8f9f7 272 i2c_start(obj);
<> 144:ef7eb2e8f9f7 273
<> 144:ef7eb2e8f9f7 274 if (!i2c_byte_write(obj, (address & 0xFE))) {
<> 144:ef7eb2e8f9f7 275 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 276 return I2C_ERROR_NO_SLAVE; //NACK or error when writing adress. Return 0 as 0 bytes were written
<> 144:ef7eb2e8f9f7 277 }
<> 144:ef7eb2e8f9f7 278 int i;
<> 144:ef7eb2e8f9f7 279 for (i = 0; i < length; i++) {
<> 144:ef7eb2e8f9f7 280 if (!i2c_byte_write(obj, data[i])) {
<> 144:ef7eb2e8f9f7 281 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 282 return i;
<> 144:ef7eb2e8f9f7 283 }
<> 144:ef7eb2e8f9f7 284 }
<> 144:ef7eb2e8f9f7 285
<> 144:ef7eb2e8f9f7 286 if (stop) {
<> 144:ef7eb2e8f9f7 287 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 288 }
<> 144:ef7eb2e8f9f7 289
<> 144:ef7eb2e8f9f7 290 return length;
<> 144:ef7eb2e8f9f7 291 }
<> 144:ef7eb2e8f9f7 292
<> 144:ef7eb2e8f9f7 293 void i2c_reset(i2c_t *obj)
<> 144:ef7eb2e8f9f7 294 {
<> 144:ef7eb2e8f9f7 295 /* EMLib function */
<> 144:ef7eb2e8f9f7 296 I2C_Reset(obj->i2c.i2c);
<> 144:ef7eb2e8f9f7 297 }
<> 144:ef7eb2e8f9f7 298
<> 144:ef7eb2e8f9f7 299 int i2c_byte_read(i2c_t *obj, int last)
<> 144:ef7eb2e8f9f7 300 {
<> 144:ef7eb2e8f9f7 301 int timeout = I2C_TIMEOUT;
<> 144:ef7eb2e8f9f7 302 /* Wait for data */
<> 144:ef7eb2e8f9f7 303 while (!(obj->i2c.i2c->STATUS & I2C_STATUS_RXDATAV) && timeout--);
<> 144:ef7eb2e8f9f7 304
<> 144:ef7eb2e8f9f7 305 if (timeout <= 0) {
<> 144:ef7eb2e8f9f7 306 return 0; //TODO Is this the correct way to handle this?
<> 144:ef7eb2e8f9f7 307 }
<> 144:ef7eb2e8f9f7 308 char data = obj->i2c.i2c->RXDATA;
<> 144:ef7eb2e8f9f7 309
<> 144:ef7eb2e8f9f7 310 if (last) {
<> 144:ef7eb2e8f9f7 311 obj->i2c.i2c->CMD = I2C_CMD_NACK;
<> 144:ef7eb2e8f9f7 312 } else {
<> 144:ef7eb2e8f9f7 313 obj->i2c.i2c->CMD = I2C_CMD_ACK;
<> 144:ef7eb2e8f9f7 314 }
<> 144:ef7eb2e8f9f7 315 return data;
<> 144:ef7eb2e8f9f7 316 }
<> 144:ef7eb2e8f9f7 317
<> 144:ef7eb2e8f9f7 318 int i2c_byte_write(i2c_t *obj, int data)
<> 144:ef7eb2e8f9f7 319 {
<> 144:ef7eb2e8f9f7 320 obj->i2c.i2c->TXDATA = data;
<> 144:ef7eb2e8f9f7 321 return block_and_wait_for_ack(obj->i2c.i2c);
<> 144:ef7eb2e8f9f7 322 }
<> 144:ef7eb2e8f9f7 323
<> 144:ef7eb2e8f9f7 324 /*
<> 144:ef7eb2e8f9f7 325 * Returns 1 for ACK. 0 for NACK, timeout or error.
<> 144:ef7eb2e8f9f7 326 */
<> 144:ef7eb2e8f9f7 327 int block_and_wait_for_ack(I2C_TypeDef *i2c)
<> 144:ef7eb2e8f9f7 328 {
<> 144:ef7eb2e8f9f7 329 uint32_t pending;
<> 144:ef7eb2e8f9f7 330 uint32_t timeout = I2C_TIMEOUT;
<> 144:ef7eb2e8f9f7 331 while (timeout > 0) {
<> 144:ef7eb2e8f9f7 332 timeout -= 1;
<> 144:ef7eb2e8f9f7 333 pending = i2c->IF;
<> 144:ef7eb2e8f9f7 334 /* If some sort of fault, abort transfer. */
<> 144:ef7eb2e8f9f7 335 if (pending & I2C_IF_ERRORS) {
<> 144:ef7eb2e8f9f7 336 if (pending & I2C_IF_ARBLOST) {
<> 144:ef7eb2e8f9f7 337 /* If arbitration fault, it indicates either a slave device */
<> 144:ef7eb2e8f9f7 338 /* not responding as expected, or other master which is not */
<> 144:ef7eb2e8f9f7 339 /* supported by this SW. */
<> 144:ef7eb2e8f9f7 340 return 0;
<> 144:ef7eb2e8f9f7 341 } else if (pending & I2C_IF_BUSERR) {
<> 144:ef7eb2e8f9f7 342 /* A bus error indicates a misplaced start or stop, which should */
<> 144:ef7eb2e8f9f7 343 /* not occur in master mode controlled by this SW. */
<> 144:ef7eb2e8f9f7 344 return 0;
<> 144:ef7eb2e8f9f7 345 }
<> 144:ef7eb2e8f9f7 346 }
<> 144:ef7eb2e8f9f7 347
<> 144:ef7eb2e8f9f7 348 if (pending & I2C_IF_NACK) {
<> 144:ef7eb2e8f9f7 349 i2c->IFC = I2C_IFC_NACK;
<> 144:ef7eb2e8f9f7 350 return 0; //Received NACK
<> 144:ef7eb2e8f9f7 351 } else if (pending & I2C_IF_ACK) {
<> 144:ef7eb2e8f9f7 352 i2c->IFC = I2C_IFC_ACK;
<> 144:ef7eb2e8f9f7 353 return 1; //Got ACK
<> 144:ef7eb2e8f9f7 354 }
<> 144:ef7eb2e8f9f7 355 }
<> 144:ef7eb2e8f9f7 356 return 0; //Timeout
<> 144:ef7eb2e8f9f7 357 }
<> 144:ef7eb2e8f9f7 358
<> 144:ef7eb2e8f9f7 359 #if DEVICE_I2CSLAVE
<> 144:ef7eb2e8f9f7 360
<> 144:ef7eb2e8f9f7 361 #define NoData 0
<> 144:ef7eb2e8f9f7 362 #define ReadAddressed 1
<> 144:ef7eb2e8f9f7 363 #define WriteGeneral 2
<> 144:ef7eb2e8f9f7 364 #define WriteAddressed 3
<> 144:ef7eb2e8f9f7 365
<> 144:ef7eb2e8f9f7 366
<> 144:ef7eb2e8f9f7 367 void i2c_slave_mode(i2c_t *obj, int enable_slave)
<> 144:ef7eb2e8f9f7 368 {
<> 144:ef7eb2e8f9f7 369 if(enable_slave) {
<> 144:ef7eb2e8f9f7 370 /* Reference manual note: DIV must be set to 1 during slave operation */
<> 144:ef7eb2e8f9f7 371 obj->i2c.i2c->CLKDIV = 1;
<> 144:ef7eb2e8f9f7 372 obj->i2c.i2c->CTRL |= _I2C_CTRL_SLAVE_MASK;
<> 144:ef7eb2e8f9f7 373 obj->i2c.i2c->CTRL |= _I2C_CTRL_AUTOACK_MASK; //Slave implementation assumes auto acking
<> 144:ef7eb2e8f9f7 374 } else {
<> 144:ef7eb2e8f9f7 375 obj->i2c.i2c->CTRL &= ~_I2C_CTRL_SLAVE_MASK;
<> 144:ef7eb2e8f9f7 376 obj->i2c.i2c->CTRL &= ~_I2C_CTRL_AUTOACK_MASK; //Master implementation ACKs manually
<> 144:ef7eb2e8f9f7 377 /* function is only called with enable_slave = false through i2c_init(..), so frequency is
<> 144:ef7eb2e8f9f7 378 already guaranteed to be set */
<> 144:ef7eb2e8f9f7 379 }
<> 144:ef7eb2e8f9f7 380 }
<> 144:ef7eb2e8f9f7 381
<> 144:ef7eb2e8f9f7 382 int i2c_slave_receive(i2c_t *obj)
<> 144:ef7eb2e8f9f7 383 {
<> 144:ef7eb2e8f9f7 384
<> 144:ef7eb2e8f9f7 385 if(obj->i2c.i2c->IF & I2C_IF_ADDR) {
<> 144:ef7eb2e8f9f7 386 obj->i2c.i2c->IFC = I2C_IF_ADDR; //Clear interrupt
<> 144:ef7eb2e8f9f7 387 /*0x00 is the address for general write.
<> 144:ef7eb2e8f9f7 388 The address the master wrote is in RXDATA now
<> 144:ef7eb2e8f9f7 389 and reading it also frees the buffer for the next
<> 144:ef7eb2e8f9f7 390 write which can then be acked. */
<> 144:ef7eb2e8f9f7 391 if(obj->i2c.i2c->RXDATA == 0x00) {
<> 144:ef7eb2e8f9f7 392 return WriteGeneral; //Read the address;
<> 144:ef7eb2e8f9f7 393 }
<> 144:ef7eb2e8f9f7 394
<> 144:ef7eb2e8f9f7 395 if(obj->i2c.i2c->STATE & I2C_STATE_TRANSMITTER) {
<> 144:ef7eb2e8f9f7 396 return ReadAddressed;
<> 144:ef7eb2e8f9f7 397 } else {
<> 144:ef7eb2e8f9f7 398 return WriteAddressed;
<> 144:ef7eb2e8f9f7 399 }
<> 144:ef7eb2e8f9f7 400 }
<> 144:ef7eb2e8f9f7 401
<> 144:ef7eb2e8f9f7 402 return NoData;
<> 144:ef7eb2e8f9f7 403
<> 144:ef7eb2e8f9f7 404 }
<> 144:ef7eb2e8f9f7 405
<> 144:ef7eb2e8f9f7 406 int i2c_slave_read(i2c_t *obj, char *data, int length)
<> 144:ef7eb2e8f9f7 407 {
<> 144:ef7eb2e8f9f7 408 int count;
<> 144:ef7eb2e8f9f7 409 for (count = 0; count < length; count++) {
<> 144:ef7eb2e8f9f7 410 data[count] = i2c_byte_read(obj, 0);
<> 144:ef7eb2e8f9f7 411 }
<> 144:ef7eb2e8f9f7 412
<> 144:ef7eb2e8f9f7 413
<> 144:ef7eb2e8f9f7 414 return count;
<> 144:ef7eb2e8f9f7 415
<> 144:ef7eb2e8f9f7 416 }
<> 144:ef7eb2e8f9f7 417
<> 144:ef7eb2e8f9f7 418 int i2c_slave_write(i2c_t *obj, const char *data, int length)
<> 144:ef7eb2e8f9f7 419 {
<> 144:ef7eb2e8f9f7 420 int count;
<> 144:ef7eb2e8f9f7 421 for (count = 0; count < length; count++) {
<> 144:ef7eb2e8f9f7 422 i2c_byte_write(obj, data[count]);
<> 144:ef7eb2e8f9f7 423 }
<> 144:ef7eb2e8f9f7 424
<> 144:ef7eb2e8f9f7 425 return count;
<> 144:ef7eb2e8f9f7 426 }
<> 144:ef7eb2e8f9f7 427
<> 144:ef7eb2e8f9f7 428 void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask)
<> 144:ef7eb2e8f9f7 429 {
<> 144:ef7eb2e8f9f7 430 obj->i2c.i2c->SADDR = address;
<> 144:ef7eb2e8f9f7 431 obj->i2c.i2c->SADDRMASK = 0xFE;//mask;
<> 144:ef7eb2e8f9f7 432 }
<> 144:ef7eb2e8f9f7 433
<> 144:ef7eb2e8f9f7 434 #endif //DEVICE_I2CSLAVE
<> 144:ef7eb2e8f9f7 435
<> 144:ef7eb2e8f9f7 436 #ifdef DEVICE_I2C_ASYNCH
<> 144:ef7eb2e8f9f7 437
<> 144:ef7eb2e8f9f7 438 #include "em_dma.h"
<> 144:ef7eb2e8f9f7 439 #include "dma_api_HAL.h"
<> 144:ef7eb2e8f9f7 440 #include "dma_api.h"
<> 144:ef7eb2e8f9f7 441 #include "sleep_api.h"
<> 144:ef7eb2e8f9f7 442 #include "buffer.h"
<> 144:ef7eb2e8f9f7 443
<> 144:ef7eb2e8f9f7 444 /** Start i2c asynchronous transfer.
<> 144:ef7eb2e8f9f7 445 * @param obj The I2C object
<> 144:ef7eb2e8f9f7 446 * @param tx The buffer to send
<> 144:ef7eb2e8f9f7 447 * @param tx_length The number of words to transmit
<> 144:ef7eb2e8f9f7 448 * @param rx The buffer to receive
<> 144:ef7eb2e8f9f7 449 * @param rx_length The number of words to receive
<> 144:ef7eb2e8f9f7 450 * @param address The address to be set - 7bit or 9 bit
<> 144:ef7eb2e8f9f7 451 * @param stop If true, stop will be generated after the transfer is done
<> 144:ef7eb2e8f9f7 452 * @param handler The I2C IRQ handler to be set
<> 144:ef7eb2e8f9f7 453 * @param hint DMA hint usage
<> 144:ef7eb2e8f9f7 454 */
<> 144:ef7eb2e8f9f7 455 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 456 {
<> 144:ef7eb2e8f9f7 457 I2C_TransferReturn_TypeDef retval;
<> 144:ef7eb2e8f9f7 458 if(i2c_active(obj)) return;
<> 144:ef7eb2e8f9f7 459 if((tx_length == 0) && (rx_length == 0)) return;
<> 144:ef7eb2e8f9f7 460 // For now, we are assuming a solely interrupt-driven implementation.
<> 144:ef7eb2e8f9f7 461
<> 144:ef7eb2e8f9f7 462 // Store transfer config
<> 144:ef7eb2e8f9f7 463 obj->i2c.xfer.addr = address;
<> 144:ef7eb2e8f9f7 464
<> 144:ef7eb2e8f9f7 465 // Some combination of tx_length and rx_length will tell us what to do
<> 144:ef7eb2e8f9f7 466 if((tx_length > 0) && (rx_length == 0)) {
<> 144:ef7eb2e8f9f7 467 obj->i2c.xfer.flags = I2C_FLAG_WRITE;
<> 144:ef7eb2e8f9f7 468 //Store buffer info
<> 144:ef7eb2e8f9f7 469 obj->i2c.xfer.buf[0].data = (void *)tx;
<> 144:ef7eb2e8f9f7 470 obj->i2c.xfer.buf[0].len = (uint16_t) tx_length;
<> 144:ef7eb2e8f9f7 471 } else if ((tx_length == 0) && (rx_length > 0)) {
<> 144:ef7eb2e8f9f7 472 obj->i2c.xfer.flags = I2C_FLAG_READ;
<> 144:ef7eb2e8f9f7 473 //Store buffer info
<> 144:ef7eb2e8f9f7 474 obj->i2c.xfer.buf[0].data = rx;
<> 144:ef7eb2e8f9f7 475 obj->i2c.xfer.buf[0].len = (uint16_t) rx_length;
<> 144:ef7eb2e8f9f7 476 } else if ((tx_length > 0) && (rx_length > 0)) {
<> 144:ef7eb2e8f9f7 477 obj->i2c.xfer.flags = I2C_FLAG_WRITE_READ;
<> 144:ef7eb2e8f9f7 478 //Store buffer info
<> 144:ef7eb2e8f9f7 479 obj->i2c.xfer.buf[0].data = (void *)tx;
<> 144:ef7eb2e8f9f7 480 obj->i2c.xfer.buf[0].len = (uint16_t) tx_length;
<> 144:ef7eb2e8f9f7 481 obj->i2c.xfer.buf[1].data = rx;
<> 144:ef7eb2e8f9f7 482 obj->i2c.xfer.buf[1].len = (uint16_t) rx_length;
<> 144:ef7eb2e8f9f7 483 }
<> 144:ef7eb2e8f9f7 484
<> 144:ef7eb2e8f9f7 485 if(address > 255) obj->i2c.xfer.flags |= I2C_FLAG_10BIT_ADDR;
<> 144:ef7eb2e8f9f7 486
<> 144:ef7eb2e8f9f7 487 // Store event flags
<> 144:ef7eb2e8f9f7 488 obj->i2c.events = event;
<> 144:ef7eb2e8f9f7 489
<> 144:ef7eb2e8f9f7 490 // Enable interrupt
<> 144:ef7eb2e8f9f7 491 i2c_enable_interrupt(obj, handler, true);
<> 144:ef7eb2e8f9f7 492
<> 144:ef7eb2e8f9f7 493 // Kick off the transfer
<> 144:ef7eb2e8f9f7 494 retval = I2C_TransferInit(obj->i2c.i2c, &(obj->i2c.xfer));
<> 144:ef7eb2e8f9f7 495
<> 144:ef7eb2e8f9f7 496 if(retval == i2cTransferInProgress) {
<> 144:ef7eb2e8f9f7 497 blockSleepMode(EM1);
<> 144:ef7eb2e8f9f7 498 } else {
<> 144:ef7eb2e8f9f7 499 // something happened, and the transfer did not go through
<> 144:ef7eb2e8f9f7 500 // So, we need to clean up
<> 144:ef7eb2e8f9f7 501
<> 144:ef7eb2e8f9f7 502 // Disable interrupt
<> 144:ef7eb2e8f9f7 503 i2c_enable_interrupt(obj, 0, false);
<> 144:ef7eb2e8f9f7 504
<> 144:ef7eb2e8f9f7 505 // Block until free
<> 144:ef7eb2e8f9f7 506 while(i2c_active(obj));
<> 144:ef7eb2e8f9f7 507 }
<> 144:ef7eb2e8f9f7 508 }
<> 144:ef7eb2e8f9f7 509
<> 144:ef7eb2e8f9f7 510 /** The asynchronous IRQ handler
<> 144:ef7eb2e8f9f7 511 * @param obj The I2C object which holds the transfer information
<> 144:ef7eb2e8f9f7 512 * @return Returns event flags if a transfer termination condition was met or 0 otherwise.
<> 144:ef7eb2e8f9f7 513 */
<> 144:ef7eb2e8f9f7 514 uint32_t i2c_irq_handler_asynch(i2c_t *obj)
<> 144:ef7eb2e8f9f7 515 {
<> 144:ef7eb2e8f9f7 516
<> 144:ef7eb2e8f9f7 517 // For now, we are assuming a solely interrupt-driven implementation.
<> 144:ef7eb2e8f9f7 518
<> 144:ef7eb2e8f9f7 519 I2C_TransferReturn_TypeDef status = I2C_Transfer(obj->i2c.i2c);
<> 144:ef7eb2e8f9f7 520 switch(status) {
<> 144:ef7eb2e8f9f7 521 case i2cTransferInProgress:
<> 144:ef7eb2e8f9f7 522 // Still busy transferring, so let it.
<> 144:ef7eb2e8f9f7 523 return 0;
<> 144:ef7eb2e8f9f7 524 case i2cTransferDone:
<> 144:ef7eb2e8f9f7 525 // Transfer has completed
<> 144:ef7eb2e8f9f7 526
<> 144:ef7eb2e8f9f7 527 // Disable interrupt
<> 144:ef7eb2e8f9f7 528 i2c_enable_interrupt(obj, 0, false);
<> 144:ef7eb2e8f9f7 529
<> 144:ef7eb2e8f9f7 530 unblockSleepMode(EM1);
<> 144:ef7eb2e8f9f7 531
<> 144:ef7eb2e8f9f7 532 return I2C_EVENT_TRANSFER_COMPLETE & obj->i2c.events;
<> 144:ef7eb2e8f9f7 533 case i2cTransferNack:
<> 144:ef7eb2e8f9f7 534 // A NACK has been received while an ACK was expected. This is usually because the slave did not respond to the address.
<> 144:ef7eb2e8f9f7 535 // Disable interrupt
<> 144:ef7eb2e8f9f7 536 i2c_enable_interrupt(obj, 0, false);
<> 144:ef7eb2e8f9f7 537
<> 144:ef7eb2e8f9f7 538 unblockSleepMode(EM1);
<> 144:ef7eb2e8f9f7 539
<> 144:ef7eb2e8f9f7 540 return I2C_EVENT_ERROR_NO_SLAVE & obj->i2c.events;
<> 144:ef7eb2e8f9f7 541 default:
<> 144:ef7eb2e8f9f7 542 // An error situation has arisen.
<> 144:ef7eb2e8f9f7 543 // Disable interrupt
<> 144:ef7eb2e8f9f7 544 i2c_enable_interrupt(obj, 0, false);
<> 144:ef7eb2e8f9f7 545
<> 144:ef7eb2e8f9f7 546 unblockSleepMode(EM1);
<> 144:ef7eb2e8f9f7 547
<> 144:ef7eb2e8f9f7 548 // return error
<> 144:ef7eb2e8f9f7 549 return I2C_EVENT_ERROR & obj->i2c.events;
<> 144:ef7eb2e8f9f7 550 }
<> 144:ef7eb2e8f9f7 551 }
<> 144:ef7eb2e8f9f7 552
<> 144:ef7eb2e8f9f7 553 /** Attempts to determine if I2C peripheral is already in use.
<> 144:ef7eb2e8f9f7 554 * @param obj The I2C object
<> 144:ef7eb2e8f9f7 555 * @return non-zero if the I2C module is active or zero if it is not
<> 144:ef7eb2e8f9f7 556 */
<> 144:ef7eb2e8f9f7 557 uint8_t i2c_active(i2c_t *obj)
<> 144:ef7eb2e8f9f7 558 {
<> 144:ef7eb2e8f9f7 559 return (obj->i2c.i2c->STATE & I2C_STATE_BUSY);
<> 144:ef7eb2e8f9f7 560 }
<> 144:ef7eb2e8f9f7 561
<> 144:ef7eb2e8f9f7 562 /** Abort ongoing asynchronous transaction.
<> 144:ef7eb2e8f9f7 563 * @param obj The I2C object
<> 144:ef7eb2e8f9f7 564 */
<> 144:ef7eb2e8f9f7 565 void i2c_abort_asynch(i2c_t *obj)
<> 144:ef7eb2e8f9f7 566 {
<> 144:ef7eb2e8f9f7 567 // Do not deactivate I2C twice
<> 144:ef7eb2e8f9f7 568 if (!i2c_active(obj)) return;
<> 144:ef7eb2e8f9f7 569
<> 144:ef7eb2e8f9f7 570 // Disable interrupt
<> 144:ef7eb2e8f9f7 571 i2c_enable_interrupt(obj, 0, false);
<> 144:ef7eb2e8f9f7 572
<> 144:ef7eb2e8f9f7 573 // Abort
<> 144:ef7eb2e8f9f7 574 obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
<> 144:ef7eb2e8f9f7 575
<> 144:ef7eb2e8f9f7 576 // Block until free
<> 144:ef7eb2e8f9f7 577 while(i2c_active(obj));
<> 144:ef7eb2e8f9f7 578
<> 144:ef7eb2e8f9f7 579 unblockSleepMode(EM1);
<> 144:ef7eb2e8f9f7 580 }
<> 144:ef7eb2e8f9f7 581
<> 144:ef7eb2e8f9f7 582 #endif //DEVICE_I2C ASYNCH
<> 144:ef7eb2e8f9f7 583 #endif //DEVICE_I2C