Maintool / mbed-src-v4

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Tue Apr 28 11:45:12 2015 +0100
Revision:
525:c320967f86b9
Child:
526:7c4bdfe6a168
Synchronized with git revision 299385b8331142b9dc524da7a986536f60b14553

Full URL: https://github.com/mbedmicro/mbed/commit/299385b8331142b9dc524da7a986536f60b14553/

Add in Silicon Labs targets with asynchronous API support

Who changed what in which revision?

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