Watchdog Timer

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Fri Sep 25 14:15:10 2015 +0100
Revision:
628:4fa1328d9c60
Parent:
564:536c9fb088a0
Synchronized with git revision fe238a91ab7a4d1d72c4cab9da04967c619d54ad

Full URL: https://github.com/mbedmicro/mbed/commit/fe238a91ab7a4d1d72c4cab9da04967c619d54ad/

Silicon Labs - Add support for low-power async Serial

Who changed what in which revision?

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