mbed library sources. Supersedes mbed-src.

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

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
187:0387e8f68319
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AnnaBridge 187:0387e8f68319 1 /* mbed Microcontroller Library
AnnaBridge 187:0387e8f68319 2 * Copyright (c) 2017-2018 Nuvoton
AnnaBridge 187:0387e8f68319 3 *
AnnaBridge 187:0387e8f68319 4 * Licensed under the Apache License, Version 2.0 (the "License");
AnnaBridge 187:0387e8f68319 5 * you may not use this file except in compliance with the License.
AnnaBridge 187:0387e8f68319 6 * You may obtain a copy of the License at
AnnaBridge 187:0387e8f68319 7 *
AnnaBridge 187:0387e8f68319 8 * http://www.apache.org/licenses/LICENSE-2.0
AnnaBridge 187:0387e8f68319 9 *
AnnaBridge 187:0387e8f68319 10 * Unless required by applicable law or agreed to in writing, software
AnnaBridge 187:0387e8f68319 11 * distributed under the License is distributed on an "AS IS" BASIS,
AnnaBridge 187:0387e8f68319 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
AnnaBridge 187:0387e8f68319 13 * See the License for the specific language governing permissions and
AnnaBridge 187:0387e8f68319 14 * limitations under the License.
AnnaBridge 187:0387e8f68319 15 */
AnnaBridge 187:0387e8f68319 16
AnnaBridge 187:0387e8f68319 17 #include "i2c_api.h"
AnnaBridge 187:0387e8f68319 18
AnnaBridge 187:0387e8f68319 19 #if DEVICE_I2C
AnnaBridge 187:0387e8f68319 20
AnnaBridge 187:0387e8f68319 21 #include "cmsis.h"
AnnaBridge 187:0387e8f68319 22 #include "pinmap.h"
AnnaBridge 187:0387e8f68319 23 #include "PeripheralPins.h"
AnnaBridge 187:0387e8f68319 24 #include "nu_modutil.h"
AnnaBridge 187:0387e8f68319 25 #include "nu_miscutil.h"
AnnaBridge 187:0387e8f68319 26 #include "nu_bitutil.h"
AnnaBridge 187:0387e8f68319 27 #include "mbed_critical.h"
AnnaBridge 187:0387e8f68319 28
AnnaBridge 187:0387e8f68319 29 struct nu_i2c_var {
AnnaBridge 187:0387e8f68319 30 i2c_t * obj;
AnnaBridge 187:0387e8f68319 31 void (*vec)(void);
AnnaBridge 187:0387e8f68319 32 };
AnnaBridge 187:0387e8f68319 33
AnnaBridge 187:0387e8f68319 34 static void i2c0_vec(void);
AnnaBridge 187:0387e8f68319 35 static void i2c1_vec(void);
AnnaBridge 187:0387e8f68319 36 static void i2c2_vec(void);
AnnaBridge 187:0387e8f68319 37 static void i2c_irq(i2c_t *obj);
AnnaBridge 187:0387e8f68319 38 static void i2c_fsm_reset(i2c_t *obj, uint32_t i2c_ctl);
AnnaBridge 187:0387e8f68319 39 static void i2c_fsm_tranfini(i2c_t *obj, int lastdatanaked);
AnnaBridge 187:0387e8f68319 40
AnnaBridge 187:0387e8f68319 41 static struct nu_i2c_var i2c0_var = {
AnnaBridge 187:0387e8f68319 42 .obj = NULL,
AnnaBridge 187:0387e8f68319 43 .vec = i2c0_vec,
AnnaBridge 187:0387e8f68319 44 };
AnnaBridge 187:0387e8f68319 45 static struct nu_i2c_var i2c1_var = {
AnnaBridge 187:0387e8f68319 46 .obj = NULL,
AnnaBridge 187:0387e8f68319 47 .vec = i2c1_vec,
AnnaBridge 187:0387e8f68319 48 };
AnnaBridge 187:0387e8f68319 49 static struct nu_i2c_var i2c2_var = {
AnnaBridge 187:0387e8f68319 50 .obj = NULL,
AnnaBridge 187:0387e8f68319 51 .vec = i2c2_vec,
AnnaBridge 187:0387e8f68319 52 };
AnnaBridge 187:0387e8f68319 53
AnnaBridge 187:0387e8f68319 54 static uint32_t i2c_modinit_mask = 0;
AnnaBridge 187:0387e8f68319 55
AnnaBridge 187:0387e8f68319 56 static const struct nu_modinit_s i2c_modinit_tab[] = {
AnnaBridge 187:0387e8f68319 57 {I2C_0, I2C0_MODULE, 0, 0, I2C0_RST, I2C0_IRQn, &i2c0_var},
AnnaBridge 187:0387e8f68319 58 {I2C_1, I2C1_MODULE, 0, 0, I2C1_RST, I2C1_IRQn, &i2c1_var},
AnnaBridge 187:0387e8f68319 59 {I2C_2, I2C2_MODULE, 0, 0, I2C2_RST, I2C2_IRQn, &i2c2_var},
AnnaBridge 187:0387e8f68319 60
AnnaBridge 187:0387e8f68319 61 {NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL}
AnnaBridge 187:0387e8f68319 62 };
AnnaBridge 187:0387e8f68319 63
AnnaBridge 187:0387e8f68319 64 static int i2c_do_tran(i2c_t *obj, char *buf, int length, int read, int naklastdata);
AnnaBridge 187:0387e8f68319 65 static int i2c_do_trsn(i2c_t *obj, uint32_t i2c_ctl, int sync);
AnnaBridge 187:0387e8f68319 66 #define NU_I2C_TIMEOUT_STAT_INT 500000
AnnaBridge 187:0387e8f68319 67 #define NU_I2C_TIMEOUT_STOP 500000
AnnaBridge 187:0387e8f68319 68 static int i2c_poll_status_timeout(i2c_t *obj, int (*is_status)(i2c_t *obj), uint32_t timeout);
AnnaBridge 187:0387e8f68319 69 static int i2c_poll_tran_heatbeat_timeout(i2c_t *obj, uint32_t timeout);
AnnaBridge 187:0387e8f68319 70 static int i2c_is_trsn_done(i2c_t *obj);
AnnaBridge 187:0387e8f68319 71 static int i2c_is_tran_started(i2c_t *obj);
AnnaBridge 187:0387e8f68319 72 static int i2c_addr2data(int address, int read);
AnnaBridge 187:0387e8f68319 73 #if DEVICE_I2CSLAVE
AnnaBridge 187:0387e8f68319 74 // Convert mbed address to BSP address.
AnnaBridge 187:0387e8f68319 75 static int i2c_addr2bspaddr(int address);
AnnaBridge 187:0387e8f68319 76 #endif // #if DEVICE_I2CSLAVE
AnnaBridge 187:0387e8f68319 77 static void i2c_enable_int(i2c_t *obj);
AnnaBridge 187:0387e8f68319 78 static void i2c_disable_int(i2c_t *obj);
AnnaBridge 187:0387e8f68319 79 static int i2c_set_int(i2c_t *obj, int inten);
AnnaBridge 187:0387e8f68319 80
AnnaBridge 187:0387e8f68319 81
AnnaBridge 187:0387e8f68319 82 #if DEVICE_I2C_ASYNCH
AnnaBridge 187:0387e8f68319 83 static void i2c_buffer_set(i2c_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length);
AnnaBridge 187:0387e8f68319 84 static void i2c_enable_vector_interrupt(i2c_t *obj, uint32_t handler, int enable);
AnnaBridge 187:0387e8f68319 85 static void i2c_rollback_vector_interrupt(i2c_t *obj);
AnnaBridge 187:0387e8f68319 86 #endif
AnnaBridge 187:0387e8f68319 87
AnnaBridge 187:0387e8f68319 88 #define TRANCTRL_STARTED (1)
AnnaBridge 187:0387e8f68319 89 #define TRANCTRL_NAKLASTDATA (1 << 1)
AnnaBridge 187:0387e8f68319 90 #define TRANCTRL_LASTDATANAKED (1 << 2)
AnnaBridge 187:0387e8f68319 91
AnnaBridge 187:0387e8f68319 92 uint32_t us_ticker_read(void);
AnnaBridge 187:0387e8f68319 93
AnnaBridge 187:0387e8f68319 94 void i2c_init(i2c_t *obj, PinName sda, PinName scl)
AnnaBridge 187:0387e8f68319 95 {
AnnaBridge 187:0387e8f68319 96 uint32_t i2c_sda = pinmap_peripheral(sda, PinMap_I2C_SDA);
AnnaBridge 187:0387e8f68319 97 uint32_t i2c_scl = pinmap_peripheral(scl, PinMap_I2C_SCL);
AnnaBridge 187:0387e8f68319 98 obj->i2c.i2c = (I2CName) pinmap_merge(i2c_sda, i2c_scl);
AnnaBridge 187:0387e8f68319 99 MBED_ASSERT((int)obj->i2c.i2c != NC);
AnnaBridge 187:0387e8f68319 100
AnnaBridge 187:0387e8f68319 101 const struct nu_modinit_s *modinit = get_modinit(obj->i2c.i2c, i2c_modinit_tab);
AnnaBridge 187:0387e8f68319 102 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 103 MBED_ASSERT(modinit->modname == (int) obj->i2c.i2c);
AnnaBridge 187:0387e8f68319 104
AnnaBridge 187:0387e8f68319 105 /* Reset module
AnnaBridge 187:0387e8f68319 106 *
AnnaBridge 187:0387e8f68319 107 * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
AnnaBridge 187:0387e8f68319 108 */
AnnaBridge 187:0387e8f68319 109 SYS_ResetModule_S(modinit->rsetidx);
AnnaBridge 187:0387e8f68319 110
AnnaBridge 187:0387e8f68319 111 /* Select IP clock source
AnnaBridge 187:0387e8f68319 112 *
AnnaBridge 187:0387e8f68319 113 * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
AnnaBridge 187:0387e8f68319 114 */
AnnaBridge 187:0387e8f68319 115 CLK_EnableModuleClock_S(modinit->clkidx);
AnnaBridge 187:0387e8f68319 116
AnnaBridge 187:0387e8f68319 117 pinmap_pinout(sda, PinMap_I2C_SDA);
AnnaBridge 187:0387e8f68319 118 pinmap_pinout(scl, PinMap_I2C_SCL);
AnnaBridge 187:0387e8f68319 119
AnnaBridge 187:0387e8f68319 120 #if DEVICE_I2C_ASYNCH
AnnaBridge 187:0387e8f68319 121 obj->i2c.dma_usage = DMA_USAGE_NEVER;
AnnaBridge 187:0387e8f68319 122 obj->i2c.event = 0;
AnnaBridge 187:0387e8f68319 123 obj->i2c.stop = 0;
AnnaBridge 187:0387e8f68319 124 obj->i2c.address = 0;
AnnaBridge 187:0387e8f68319 125 #endif
AnnaBridge 187:0387e8f68319 126
AnnaBridge 187:0387e8f68319 127 // NOTE: Setting I2C bus clock to 100 KHz is required. See I2C::I2C in common/I2C.cpp.
AnnaBridge 187:0387e8f68319 128 I2C_Open((I2C_T *) NU_MODBASE(obj->i2c.i2c), 100000);
AnnaBridge 187:0387e8f68319 129 // NOTE: INTEN bit and FSM control bits (STA, STO, SI, AA) are packed in one register CTL0. We cannot control interrupt through
AnnaBridge 187:0387e8f68319 130 // INTEN bit without impacting FSM control bits. Use NVIC_EnableIRQ/NVIC_DisableIRQ instead for interrupt control.
AnnaBridge 187:0387e8f68319 131 I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c);
AnnaBridge 187:0387e8f68319 132 i2c_base->CTL0 |= (I2C_CTL0_INTEN_Msk | I2C_CTL0_I2CEN_Msk);
AnnaBridge 187:0387e8f68319 133
AnnaBridge 187:0387e8f68319 134 // Enable sync-mode vector interrupt.
AnnaBridge 187:0387e8f68319 135 struct nu_i2c_var *var = (struct nu_i2c_var *) modinit->var;
AnnaBridge 187:0387e8f68319 136 var->obj = obj;
AnnaBridge 187:0387e8f68319 137 obj->i2c.tran_ctrl = 0;
AnnaBridge 187:0387e8f68319 138 obj->i2c.stop = 0;
AnnaBridge 187:0387e8f68319 139 i2c_enable_vector_interrupt(obj, (uint32_t) var->vec, 1);
AnnaBridge 187:0387e8f68319 140
AnnaBridge 187:0387e8f68319 141 // Mark this module to be inited.
AnnaBridge 187:0387e8f68319 142 int i = modinit - i2c_modinit_tab;
AnnaBridge 187:0387e8f68319 143 i2c_modinit_mask |= 1 << i;
AnnaBridge 187:0387e8f68319 144 }
AnnaBridge 187:0387e8f68319 145
AnnaBridge 187:0387e8f68319 146 int i2c_start(i2c_t *obj)
AnnaBridge 187:0387e8f68319 147 {
AnnaBridge 187:0387e8f68319 148 return i2c_do_trsn(obj, I2C_CTL0_STA_Msk | I2C_CTL0_SI_Msk, 1);
AnnaBridge 187:0387e8f68319 149 }
AnnaBridge 187:0387e8f68319 150
AnnaBridge 187:0387e8f68319 151 int i2c_stop(i2c_t *obj)
AnnaBridge 187:0387e8f68319 152 {
AnnaBridge 187:0387e8f68319 153 return i2c_do_trsn(obj, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk, 1);
AnnaBridge 187:0387e8f68319 154 }
AnnaBridge 187:0387e8f68319 155
AnnaBridge 187:0387e8f68319 156 void i2c_frequency(i2c_t *obj, int hz)
AnnaBridge 187:0387e8f68319 157 {
AnnaBridge 187:0387e8f68319 158 I2C_SetBusClockFreq((I2C_T *) NU_MODBASE(obj->i2c.i2c), hz);
AnnaBridge 187:0387e8f68319 159 }
AnnaBridge 187:0387e8f68319 160
AnnaBridge 187:0387e8f68319 161 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
AnnaBridge 187:0387e8f68319 162 {
AnnaBridge 187:0387e8f68319 163 if (i2c_start(obj)) {
AnnaBridge 187:0387e8f68319 164 i2c_stop(obj);
AnnaBridge 187:0387e8f68319 165 return I2C_ERROR_BUS_BUSY;
AnnaBridge 187:0387e8f68319 166 }
AnnaBridge 187:0387e8f68319 167
AnnaBridge 187:0387e8f68319 168 if (i2c_byte_write(obj, i2c_addr2data(address, 1)) != 1) {
AnnaBridge 187:0387e8f68319 169 i2c_stop(obj);
AnnaBridge 187:0387e8f68319 170 return I2C_ERROR_NO_SLAVE;
AnnaBridge 187:0387e8f68319 171 }
AnnaBridge 187:0387e8f68319 172
AnnaBridge 187:0387e8f68319 173 // Read in bytes
AnnaBridge 187:0387e8f68319 174 length = i2c_do_tran(obj, data, length, 1, 1);
AnnaBridge 187:0387e8f68319 175
AnnaBridge 187:0387e8f68319 176 // If not repeated start, send stop.
AnnaBridge 187:0387e8f68319 177 if (stop) {
AnnaBridge 187:0387e8f68319 178 i2c_stop(obj);
AnnaBridge 187:0387e8f68319 179 }
AnnaBridge 187:0387e8f68319 180
AnnaBridge 187:0387e8f68319 181 return length;
AnnaBridge 187:0387e8f68319 182 }
AnnaBridge 187:0387e8f68319 183
AnnaBridge 187:0387e8f68319 184 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
AnnaBridge 187:0387e8f68319 185 {
AnnaBridge 187:0387e8f68319 186 if (i2c_start(obj)) {
AnnaBridge 187:0387e8f68319 187 i2c_stop(obj);
AnnaBridge 187:0387e8f68319 188 return I2C_ERROR_BUS_BUSY;
AnnaBridge 187:0387e8f68319 189 }
AnnaBridge 187:0387e8f68319 190
AnnaBridge 187:0387e8f68319 191 if (i2c_byte_write(obj, i2c_addr2data(address, 0)) != 1) {
AnnaBridge 187:0387e8f68319 192 i2c_stop(obj);
AnnaBridge 187:0387e8f68319 193 return I2C_ERROR_NO_SLAVE;
AnnaBridge 187:0387e8f68319 194 }
AnnaBridge 187:0387e8f68319 195
AnnaBridge 187:0387e8f68319 196 // Write out bytes
AnnaBridge 187:0387e8f68319 197 length = i2c_do_tran(obj, (char *) data, length, 0, 1);
AnnaBridge 187:0387e8f68319 198
AnnaBridge 187:0387e8f68319 199 if (stop) {
AnnaBridge 187:0387e8f68319 200 i2c_stop(obj);
AnnaBridge 187:0387e8f68319 201 }
AnnaBridge 187:0387e8f68319 202
AnnaBridge 187:0387e8f68319 203 return length;
AnnaBridge 187:0387e8f68319 204 }
AnnaBridge 187:0387e8f68319 205
AnnaBridge 187:0387e8f68319 206 void i2c_reset(i2c_t *obj)
AnnaBridge 187:0387e8f68319 207 {
AnnaBridge 187:0387e8f68319 208 i2c_stop(obj);
AnnaBridge 187:0387e8f68319 209 }
AnnaBridge 187:0387e8f68319 210
AnnaBridge 187:0387e8f68319 211 int i2c_byte_read(i2c_t *obj, int last)
AnnaBridge 187:0387e8f68319 212 {
AnnaBridge 187:0387e8f68319 213 char data = 0;
AnnaBridge 187:0387e8f68319 214 i2c_do_tran(obj, &data, 1, 1, last);
AnnaBridge 187:0387e8f68319 215 return data;
AnnaBridge 187:0387e8f68319 216 }
AnnaBridge 187:0387e8f68319 217
AnnaBridge 187:0387e8f68319 218 int i2c_byte_write(i2c_t *obj, int data)
AnnaBridge 187:0387e8f68319 219 {
AnnaBridge 187:0387e8f68319 220 char data_[1];
AnnaBridge 187:0387e8f68319 221 data_[0] = data & 0xFF;
AnnaBridge 187:0387e8f68319 222
AnnaBridge 187:0387e8f68319 223 if (i2c_do_tran(obj, data_, 1, 0, 0) == 1 &&
AnnaBridge 187:0387e8f68319 224 ! (obj->i2c.tran_ctrl & TRANCTRL_LASTDATANAKED)) {
AnnaBridge 187:0387e8f68319 225 return 1;
AnnaBridge 187:0387e8f68319 226 } else {
AnnaBridge 187:0387e8f68319 227 return 0;
AnnaBridge 187:0387e8f68319 228 }
AnnaBridge 187:0387e8f68319 229 }
AnnaBridge 187:0387e8f68319 230
AnnaBridge 187:0387e8f68319 231 #if DEVICE_I2CSLAVE
AnnaBridge 187:0387e8f68319 232
AnnaBridge 187:0387e8f68319 233 // See I2CSlave.h
AnnaBridge 187:0387e8f68319 234 #define NoData 0 // the slave has not been addressed
AnnaBridge 187:0387e8f68319 235 #define ReadAddressed 1 // the master has requested a read from this slave (slave = transmitter)
AnnaBridge 187:0387e8f68319 236 #define WriteGeneral 2 // the master is writing to all slave
AnnaBridge 187:0387e8f68319 237 #define WriteAddressed 3 // the master is writing to this slave (slave = receiver)
AnnaBridge 187:0387e8f68319 238
AnnaBridge 187:0387e8f68319 239 void i2c_slave_mode(i2c_t *obj, int enable_slave)
AnnaBridge 187:0387e8f68319 240 {
AnnaBridge 187:0387e8f68319 241 I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c);
AnnaBridge 187:0387e8f68319 242
AnnaBridge 187:0387e8f68319 243 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 244
AnnaBridge 187:0387e8f68319 245 obj->i2c.slaveaddr_state = NoData;
AnnaBridge 187:0387e8f68319 246
AnnaBridge 187:0387e8f68319 247 // Switch to not addressed mode
AnnaBridge 187:0387e8f68319 248 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
AnnaBridge 187:0387e8f68319 249
AnnaBridge 187:0387e8f68319 250 i2c_enable_int(obj);
AnnaBridge 187:0387e8f68319 251 }
AnnaBridge 187:0387e8f68319 252
AnnaBridge 187:0387e8f68319 253 int i2c_slave_receive(i2c_t *obj)
AnnaBridge 187:0387e8f68319 254 {
AnnaBridge 187:0387e8f68319 255 int slaveaddr_state;
AnnaBridge 187:0387e8f68319 256
AnnaBridge 187:0387e8f68319 257 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 258 slaveaddr_state = obj->i2c.slaveaddr_state;
AnnaBridge 187:0387e8f68319 259 i2c_enable_int(obj);
AnnaBridge 187:0387e8f68319 260
AnnaBridge 187:0387e8f68319 261 return slaveaddr_state;
AnnaBridge 187:0387e8f68319 262 }
AnnaBridge 187:0387e8f68319 263
AnnaBridge 187:0387e8f68319 264 int i2c_slave_read(i2c_t *obj, char *data, int length)
AnnaBridge 187:0387e8f68319 265 {
AnnaBridge 187:0387e8f68319 266 return i2c_do_tran(obj, data, length, 1, 1);
AnnaBridge 187:0387e8f68319 267 }
AnnaBridge 187:0387e8f68319 268
AnnaBridge 187:0387e8f68319 269 int i2c_slave_write(i2c_t *obj, const char *data, int length)
AnnaBridge 187:0387e8f68319 270 {
AnnaBridge 187:0387e8f68319 271 return i2c_do_tran(obj, (char *) data, length, 0, 1);
AnnaBridge 187:0387e8f68319 272 }
AnnaBridge 187:0387e8f68319 273
AnnaBridge 187:0387e8f68319 274 void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask)
AnnaBridge 187:0387e8f68319 275 {
AnnaBridge 187:0387e8f68319 276 I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c);
AnnaBridge 187:0387e8f68319 277
AnnaBridge 187:0387e8f68319 278 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 279
AnnaBridge 187:0387e8f68319 280 // NOTE: On NUC472/M451, non-zero slave address can still work as GC mode is enabled.
AnnaBridge 187:0387e8f68319 281 // On M480, non-zero slave address won't work as GC mode is enabled.
AnnaBridge 187:0387e8f68319 282 I2C_SetSlaveAddr(i2c_base, 0, i2c_addr2bspaddr(address), I2C_GCMODE_DISABLE);
AnnaBridge 187:0387e8f68319 283
AnnaBridge 187:0387e8f68319 284 i2c_enable_int(obj);
AnnaBridge 187:0387e8f68319 285 }
AnnaBridge 187:0387e8f68319 286
AnnaBridge 187:0387e8f68319 287 static int i2c_addr2bspaddr(int address)
AnnaBridge 187:0387e8f68319 288 {
AnnaBridge 187:0387e8f68319 289 return (address >> 1);
AnnaBridge 187:0387e8f68319 290 }
AnnaBridge 187:0387e8f68319 291
AnnaBridge 187:0387e8f68319 292 #endif // #if DEVICE_I2CSLAVE
AnnaBridge 187:0387e8f68319 293
AnnaBridge 187:0387e8f68319 294 static void i2c_enable_int(i2c_t *obj)
AnnaBridge 187:0387e8f68319 295 {
AnnaBridge 187:0387e8f68319 296 const struct nu_modinit_s *modinit = get_modinit(obj->i2c.i2c, i2c_modinit_tab);
AnnaBridge 187:0387e8f68319 297
AnnaBridge 187:0387e8f68319 298 core_util_critical_section_enter();
AnnaBridge 187:0387e8f68319 299
AnnaBridge 187:0387e8f68319 300 // Enable I2C interrupt
AnnaBridge 187:0387e8f68319 301 NVIC_EnableIRQ(modinit->irq_n);
AnnaBridge 187:0387e8f68319 302 obj->i2c.inten = 1;
AnnaBridge 187:0387e8f68319 303
AnnaBridge 187:0387e8f68319 304 core_util_critical_section_exit();
AnnaBridge 187:0387e8f68319 305 }
AnnaBridge 187:0387e8f68319 306
AnnaBridge 187:0387e8f68319 307 static void i2c_disable_int(i2c_t *obj)
AnnaBridge 187:0387e8f68319 308 {
AnnaBridge 187:0387e8f68319 309 const struct nu_modinit_s *modinit = get_modinit(obj->i2c.i2c, i2c_modinit_tab);
AnnaBridge 187:0387e8f68319 310
AnnaBridge 187:0387e8f68319 311 core_util_critical_section_enter();
AnnaBridge 187:0387e8f68319 312
AnnaBridge 187:0387e8f68319 313 // Disable I2C interrupt
AnnaBridge 187:0387e8f68319 314 NVIC_DisableIRQ(modinit->irq_n);
AnnaBridge 187:0387e8f68319 315 obj->i2c.inten = 0;
AnnaBridge 187:0387e8f68319 316
AnnaBridge 187:0387e8f68319 317 core_util_critical_section_exit();
AnnaBridge 187:0387e8f68319 318 }
AnnaBridge 187:0387e8f68319 319
AnnaBridge 187:0387e8f68319 320 static int i2c_set_int(i2c_t *obj, int inten)
AnnaBridge 187:0387e8f68319 321 {
AnnaBridge 187:0387e8f68319 322 int inten_back;
AnnaBridge 187:0387e8f68319 323
AnnaBridge 187:0387e8f68319 324 core_util_critical_section_enter();
AnnaBridge 187:0387e8f68319 325
AnnaBridge 187:0387e8f68319 326 inten_back = obj->i2c.inten;
AnnaBridge 187:0387e8f68319 327
AnnaBridge 187:0387e8f68319 328 core_util_critical_section_exit();
AnnaBridge 187:0387e8f68319 329
AnnaBridge 187:0387e8f68319 330 if (inten) {
AnnaBridge 187:0387e8f68319 331 i2c_enable_int(obj);
AnnaBridge 187:0387e8f68319 332 } else {
AnnaBridge 187:0387e8f68319 333 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 334 }
AnnaBridge 187:0387e8f68319 335
AnnaBridge 187:0387e8f68319 336 return inten_back;
AnnaBridge 187:0387e8f68319 337 }
AnnaBridge 187:0387e8f68319 338
AnnaBridge 187:0387e8f68319 339 static int i2c_do_tran(i2c_t *obj, char *buf, int length, int read, int naklastdata)
AnnaBridge 187:0387e8f68319 340 {
AnnaBridge 187:0387e8f68319 341 if (! buf || ! length) {
AnnaBridge 187:0387e8f68319 342 return 0;
AnnaBridge 187:0387e8f68319 343 }
AnnaBridge 187:0387e8f68319 344
AnnaBridge 187:0387e8f68319 345 int tran_len = 0;
AnnaBridge 187:0387e8f68319 346
AnnaBridge 187:0387e8f68319 347 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 348 obj->i2c.tran_ctrl = naklastdata ? (TRANCTRL_STARTED | TRANCTRL_NAKLASTDATA) : TRANCTRL_STARTED;
AnnaBridge 187:0387e8f68319 349 obj->i2c.tran_beg = buf;
AnnaBridge 187:0387e8f68319 350 obj->i2c.tran_pos = buf;
AnnaBridge 187:0387e8f68319 351 obj->i2c.tran_end = buf + length;
AnnaBridge 187:0387e8f68319 352 i2c_enable_int(obj);
AnnaBridge 187:0387e8f68319 353
AnnaBridge 187:0387e8f68319 354 if (i2c_poll_tran_heatbeat_timeout(obj, NU_I2C_TIMEOUT_STAT_INT)) {
AnnaBridge 187:0387e8f68319 355 // N/A
AnnaBridge 187:0387e8f68319 356 } else {
AnnaBridge 187:0387e8f68319 357 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 358 tran_len = obj->i2c.tran_pos - obj->i2c.tran_beg;
AnnaBridge 187:0387e8f68319 359 obj->i2c.tran_beg = NULL;
AnnaBridge 187:0387e8f68319 360 obj->i2c.tran_pos = NULL;
AnnaBridge 187:0387e8f68319 361 obj->i2c.tran_end = NULL;
AnnaBridge 187:0387e8f68319 362 i2c_enable_int(obj);
AnnaBridge 187:0387e8f68319 363 }
AnnaBridge 187:0387e8f68319 364
AnnaBridge 187:0387e8f68319 365 return tran_len;
AnnaBridge 187:0387e8f68319 366 }
AnnaBridge 187:0387e8f68319 367
AnnaBridge 187:0387e8f68319 368 static int i2c_do_trsn(i2c_t *obj, uint32_t i2c_ctl, int sync)
AnnaBridge 187:0387e8f68319 369 {
AnnaBridge 187:0387e8f68319 370 I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c);
AnnaBridge 187:0387e8f68319 371 int err = 0;
AnnaBridge 187:0387e8f68319 372
AnnaBridge 187:0387e8f68319 373 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 374
AnnaBridge 187:0387e8f68319 375 if (i2c_poll_status_timeout(obj, i2c_is_trsn_done, NU_I2C_TIMEOUT_STAT_INT)) {
AnnaBridge 187:0387e8f68319 376 err = I2C_ERROR_BUS_BUSY;
AnnaBridge 187:0387e8f68319 377 } else {
AnnaBridge 187:0387e8f68319 378 // NOTE: Avoid duplicate Start/Stop. Otherwise, we may meet strange error.
AnnaBridge 187:0387e8f68319 379 uint32_t status = I2C_GET_STATUS(i2c_base);
AnnaBridge 187:0387e8f68319 380
AnnaBridge 187:0387e8f68319 381 switch (status) {
AnnaBridge 187:0387e8f68319 382 case 0x08: // Start
AnnaBridge 187:0387e8f68319 383 case 0x10: // Master Repeat Start
AnnaBridge 187:0387e8f68319 384 if (i2c_ctl & I2C_CTL0_STA_Msk) {
AnnaBridge 187:0387e8f68319 385 return 0;
AnnaBridge 187:0387e8f68319 386 } else {
AnnaBridge 187:0387e8f68319 387 break;
AnnaBridge 187:0387e8f68319 388 }
AnnaBridge 187:0387e8f68319 389 case 0xF8: // Bus Released
AnnaBridge 187:0387e8f68319 390 if ((i2c_ctl & (I2C_CTL0_STA_Msk | I2C_CTL0_STO_Msk)) == I2C_CTL0_STO_Msk) {
AnnaBridge 187:0387e8f68319 391 return 0;
AnnaBridge 187:0387e8f68319 392 } else {
AnnaBridge 187:0387e8f68319 393 break;
AnnaBridge 187:0387e8f68319 394 }
AnnaBridge 187:0387e8f68319 395 }
AnnaBridge 187:0387e8f68319 396 I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
AnnaBridge 187:0387e8f68319 397 if (sync && i2c_poll_status_timeout(obj, i2c_is_trsn_done, NU_I2C_TIMEOUT_STAT_INT)) {
AnnaBridge 187:0387e8f68319 398 err = I2C_ERROR_BUS_BUSY;
AnnaBridge 187:0387e8f68319 399 }
AnnaBridge 187:0387e8f68319 400 }
AnnaBridge 187:0387e8f68319 401
AnnaBridge 187:0387e8f68319 402 i2c_enable_int(obj);
AnnaBridge 187:0387e8f68319 403
AnnaBridge 187:0387e8f68319 404 return err;
AnnaBridge 187:0387e8f68319 405 }
AnnaBridge 187:0387e8f68319 406
AnnaBridge 187:0387e8f68319 407 static int i2c_poll_status_timeout(i2c_t *obj, int (*is_status)(i2c_t *obj), uint32_t timeout)
AnnaBridge 187:0387e8f68319 408 {
AnnaBridge 187:0387e8f68319 409 uint32_t t1, t2, elapsed = 0;
AnnaBridge 187:0387e8f68319 410 int status_assert = 0;
AnnaBridge 187:0387e8f68319 411
AnnaBridge 187:0387e8f68319 412 t1 = us_ticker_read();
AnnaBridge 187:0387e8f68319 413 while (1) {
AnnaBridge 187:0387e8f68319 414 status_assert = is_status(obj);
AnnaBridge 187:0387e8f68319 415 if (status_assert) {
AnnaBridge 187:0387e8f68319 416 break;
AnnaBridge 187:0387e8f68319 417 }
AnnaBridge 187:0387e8f68319 418
AnnaBridge 187:0387e8f68319 419 t2 = us_ticker_read();
AnnaBridge 187:0387e8f68319 420 elapsed = (t2 > t1) ? (t2 - t1) : ((uint64_t) t2 + 0xFFFFFFFF - t1 + 1);
AnnaBridge 187:0387e8f68319 421 if (elapsed >= timeout) {
AnnaBridge 187:0387e8f68319 422 break;
AnnaBridge 187:0387e8f68319 423 }
AnnaBridge 187:0387e8f68319 424 }
AnnaBridge 187:0387e8f68319 425
AnnaBridge 187:0387e8f68319 426 return (elapsed >= timeout);
AnnaBridge 187:0387e8f68319 427 }
AnnaBridge 187:0387e8f68319 428
AnnaBridge 187:0387e8f68319 429 static int i2c_poll_tran_heatbeat_timeout(i2c_t *obj, uint32_t timeout)
AnnaBridge 187:0387e8f68319 430 {
AnnaBridge 187:0387e8f68319 431 uint32_t t1, t2, elapsed = 0;
AnnaBridge 187:0387e8f68319 432 int tran_started;
AnnaBridge 187:0387e8f68319 433 char *tran_pos = NULL;
AnnaBridge 187:0387e8f68319 434 char *tran_pos2 = NULL;
AnnaBridge 187:0387e8f68319 435
AnnaBridge 187:0387e8f68319 436 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 437 tran_pos = obj->i2c.tran_pos;
AnnaBridge 187:0387e8f68319 438 i2c_enable_int(obj);
AnnaBridge 187:0387e8f68319 439 t1 = us_ticker_read();
AnnaBridge 187:0387e8f68319 440 while (1) {
AnnaBridge 187:0387e8f68319 441 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 442 tran_started = i2c_is_tran_started(obj);
AnnaBridge 187:0387e8f68319 443 i2c_enable_int(obj);
AnnaBridge 187:0387e8f68319 444 if (! tran_started) { // Transfer completed or stopped
AnnaBridge 187:0387e8f68319 445 break;
AnnaBridge 187:0387e8f68319 446 }
AnnaBridge 187:0387e8f68319 447
AnnaBridge 187:0387e8f68319 448 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 449 tran_pos2 = obj->i2c.tran_pos;
AnnaBridge 187:0387e8f68319 450 i2c_enable_int(obj);
AnnaBridge 187:0387e8f68319 451 t2 = us_ticker_read();
AnnaBridge 187:0387e8f68319 452 if (tran_pos2 != tran_pos) { // Transfer on-going
AnnaBridge 187:0387e8f68319 453 t1 = t2;
AnnaBridge 187:0387e8f68319 454 tran_pos = tran_pos2;
AnnaBridge 187:0387e8f68319 455 continue;
AnnaBridge 187:0387e8f68319 456 }
AnnaBridge 187:0387e8f68319 457
AnnaBridge 187:0387e8f68319 458 elapsed = (t2 > t1) ? (t2 - t1) : ((uint64_t) t2 + 0xFFFFFFFF - t1 + 1);
AnnaBridge 187:0387e8f68319 459 if (elapsed >= timeout) { // Transfer idle
AnnaBridge 187:0387e8f68319 460 break;
AnnaBridge 187:0387e8f68319 461 }
AnnaBridge 187:0387e8f68319 462 }
AnnaBridge 187:0387e8f68319 463
AnnaBridge 187:0387e8f68319 464 return (elapsed >= timeout);
AnnaBridge 187:0387e8f68319 465 }
AnnaBridge 187:0387e8f68319 466
AnnaBridge 187:0387e8f68319 467 #if 0
AnnaBridge 187:0387e8f68319 468 static int i2c_is_stat_int(i2c_t *obj)
AnnaBridge 187:0387e8f68319 469 {
AnnaBridge 187:0387e8f68319 470 I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c);
AnnaBridge 187:0387e8f68319 471
AnnaBridge 187:0387e8f68319 472 return !! (i2c_base->CTL0 & I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 473 }
AnnaBridge 187:0387e8f68319 474
AnnaBridge 187:0387e8f68319 475 static int i2c_is_stop_det(i2c_t *obj)
AnnaBridge 187:0387e8f68319 476 {
AnnaBridge 187:0387e8f68319 477 I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c);
AnnaBridge 187:0387e8f68319 478
AnnaBridge 187:0387e8f68319 479 return ! (i2c_base->CTL0 & I2C_CTL0_STO_Msk);
AnnaBridge 187:0387e8f68319 480 }
AnnaBridge 187:0387e8f68319 481 #endif
AnnaBridge 187:0387e8f68319 482
AnnaBridge 187:0387e8f68319 483 static int i2c_is_trsn_done(i2c_t *obj)
AnnaBridge 187:0387e8f68319 484 {
AnnaBridge 187:0387e8f68319 485 I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c);
AnnaBridge 187:0387e8f68319 486 int i2c_int;
AnnaBridge 187:0387e8f68319 487 uint32_t status;
AnnaBridge 187:0387e8f68319 488 int inten_back;
AnnaBridge 187:0387e8f68319 489
AnnaBridge 187:0387e8f68319 490 inten_back = i2c_set_int(obj, 0);
AnnaBridge 187:0387e8f68319 491 i2c_int = !! (i2c_base->CTL0 & I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 492 status = I2C_GET_STATUS(i2c_base);
AnnaBridge 187:0387e8f68319 493 i2c_set_int(obj, inten_back);
AnnaBridge 187:0387e8f68319 494
AnnaBridge 187:0387e8f68319 495 return (i2c_int || status == 0xF8);
AnnaBridge 187:0387e8f68319 496 }
AnnaBridge 187:0387e8f68319 497
AnnaBridge 187:0387e8f68319 498 static int i2c_is_tran_started(i2c_t *obj)
AnnaBridge 187:0387e8f68319 499 {
AnnaBridge 187:0387e8f68319 500 int started;
AnnaBridge 187:0387e8f68319 501 int inten_back;
AnnaBridge 187:0387e8f68319 502
AnnaBridge 187:0387e8f68319 503 inten_back = i2c_set_int(obj, 0);
AnnaBridge 187:0387e8f68319 504 started = !! (obj->i2c.tran_ctrl & TRANCTRL_STARTED);
AnnaBridge 187:0387e8f68319 505 i2c_set_int(obj, inten_back);
AnnaBridge 187:0387e8f68319 506
AnnaBridge 187:0387e8f68319 507 return started;
AnnaBridge 187:0387e8f68319 508 }
AnnaBridge 187:0387e8f68319 509
AnnaBridge 187:0387e8f68319 510 static int i2c_addr2data(int address, int read)
AnnaBridge 187:0387e8f68319 511 {
AnnaBridge 187:0387e8f68319 512 return read ? (address | 1) : (address & 0xFE);
AnnaBridge 187:0387e8f68319 513 }
AnnaBridge 187:0387e8f68319 514
AnnaBridge 187:0387e8f68319 515 static void i2c0_vec(void)
AnnaBridge 187:0387e8f68319 516 {
AnnaBridge 187:0387e8f68319 517 i2c_irq(i2c0_var.obj);
AnnaBridge 187:0387e8f68319 518 }
AnnaBridge 187:0387e8f68319 519 static void i2c1_vec(void)
AnnaBridge 187:0387e8f68319 520 {
AnnaBridge 187:0387e8f68319 521 i2c_irq(i2c1_var.obj);
AnnaBridge 187:0387e8f68319 522 }
AnnaBridge 187:0387e8f68319 523 static void i2c2_vec(void)
AnnaBridge 187:0387e8f68319 524 {
AnnaBridge 187:0387e8f68319 525 i2c_irq(i2c2_var.obj);
AnnaBridge 187:0387e8f68319 526 }
AnnaBridge 187:0387e8f68319 527
AnnaBridge 187:0387e8f68319 528 static void i2c_irq(i2c_t *obj)
AnnaBridge 187:0387e8f68319 529 {
AnnaBridge 187:0387e8f68319 530 I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c);
AnnaBridge 187:0387e8f68319 531 uint32_t status;
AnnaBridge 187:0387e8f68319 532
AnnaBridge 187:0387e8f68319 533 if (I2C_GET_TIMEOUT_FLAG(i2c_base)) {
AnnaBridge 187:0387e8f68319 534 I2C_ClearTimeoutFlag(i2c_base);
AnnaBridge 187:0387e8f68319 535 return;
AnnaBridge 187:0387e8f68319 536 }
AnnaBridge 187:0387e8f68319 537
AnnaBridge 187:0387e8f68319 538 status = I2C_GET_STATUS(i2c_base);
AnnaBridge 187:0387e8f68319 539
AnnaBridge 187:0387e8f68319 540 switch (status) {
AnnaBridge 187:0387e8f68319 541 // Master Transmit
AnnaBridge 187:0387e8f68319 542 case 0x28: // Master Transmit Data ACK
AnnaBridge 187:0387e8f68319 543 case 0x18: // Master Transmit Address ACK
AnnaBridge 187:0387e8f68319 544 case 0x08: // Start
AnnaBridge 187:0387e8f68319 545 case 0x10: // Master Repeat Start
AnnaBridge 187:0387e8f68319 546 if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
AnnaBridge 187:0387e8f68319 547 if (obj->i2c.tran_pos < obj->i2c.tran_end) {
AnnaBridge 187:0387e8f68319 548 I2C_SET_DATA(i2c_base, *obj->i2c.tran_pos ++);
AnnaBridge 187:0387e8f68319 549 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
AnnaBridge 187:0387e8f68319 550 } else {
AnnaBridge 187:0387e8f68319 551 i2c_fsm_tranfini(obj, 0);
AnnaBridge 187:0387e8f68319 552 }
AnnaBridge 187:0387e8f68319 553 } else {
AnnaBridge 187:0387e8f68319 554 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 555 }
AnnaBridge 187:0387e8f68319 556 break;
AnnaBridge 187:0387e8f68319 557
AnnaBridge 187:0387e8f68319 558 case 0x30: // Master Transmit Data NACK
AnnaBridge 187:0387e8f68319 559 i2c_fsm_tranfini(obj, 1);
AnnaBridge 187:0387e8f68319 560 break;
AnnaBridge 187:0387e8f68319 561
AnnaBridge 187:0387e8f68319 562 case 0x20: // Master Transmit Address NACK
AnnaBridge 187:0387e8f68319 563 i2c_fsm_tranfini(obj, 1);
AnnaBridge 187:0387e8f68319 564 break;
AnnaBridge 187:0387e8f68319 565
AnnaBridge 187:0387e8f68319 566 case 0x38: // Master Arbitration Lost
AnnaBridge 187:0387e8f68319 567 i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
AnnaBridge 187:0387e8f68319 568 break;
AnnaBridge 187:0387e8f68319 569
AnnaBridge 187:0387e8f68319 570 case 0x48: // Master Receive Address NACK
AnnaBridge 187:0387e8f68319 571 i2c_fsm_tranfini(obj, 1);
AnnaBridge 187:0387e8f68319 572 break;
AnnaBridge 187:0387e8f68319 573
AnnaBridge 187:0387e8f68319 574 case 0x40: // Master Receive Address ACK
AnnaBridge 187:0387e8f68319 575 case 0x50: // Master Receive Data ACK
AnnaBridge 187:0387e8f68319 576 case 0x58: // Master Receive Data NACK
AnnaBridge 187:0387e8f68319 577 if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
AnnaBridge 187:0387e8f68319 578 if (obj->i2c.tran_pos < obj->i2c.tran_end) {
AnnaBridge 187:0387e8f68319 579 if (status == 0x50 || status == 0x58) {
AnnaBridge 187:0387e8f68319 580 *obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
AnnaBridge 187:0387e8f68319 581 }
AnnaBridge 187:0387e8f68319 582
AnnaBridge 187:0387e8f68319 583 if (status == 0x58) {
AnnaBridge 187:0387e8f68319 584 i2c_fsm_tranfini(obj, 1);
AnnaBridge 187:0387e8f68319 585 } else {
AnnaBridge 187:0387e8f68319 586 uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
AnnaBridge 187:0387e8f68319 587 if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
AnnaBridge 187:0387e8f68319 588 obj->i2c.tran_ctrl & TRANCTRL_NAKLASTDATA) {
AnnaBridge 187:0387e8f68319 589 // Last data
AnnaBridge 187:0387e8f68319 590 i2c_ctl &= ~I2C_CTL0_AA_Msk;
AnnaBridge 187:0387e8f68319 591 }
AnnaBridge 187:0387e8f68319 592 I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
AnnaBridge 187:0387e8f68319 593 }
AnnaBridge 187:0387e8f68319 594 } else {
AnnaBridge 187:0387e8f68319 595 obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
AnnaBridge 187:0387e8f68319 596 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 597 break;
AnnaBridge 187:0387e8f68319 598 }
AnnaBridge 187:0387e8f68319 599 } else {
AnnaBridge 187:0387e8f68319 600 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 601 }
AnnaBridge 187:0387e8f68319 602 break;
AnnaBridge 187:0387e8f68319 603
AnnaBridge 187:0387e8f68319 604 //case 0x00: // Bus error
AnnaBridge 187:0387e8f68319 605
AnnaBridge 187:0387e8f68319 606 // Slave Transmit
AnnaBridge 187:0387e8f68319 607 case 0xB8: // Slave Transmit Data ACK
AnnaBridge 187:0387e8f68319 608 case 0xA8: // Slave Transmit Address ACK
AnnaBridge 187:0387e8f68319 609 case 0xB0: // Slave Transmit Arbitration Lost
AnnaBridge 187:0387e8f68319 610 if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
AnnaBridge 187:0387e8f68319 611 if (obj->i2c.tran_pos < obj->i2c.tran_end) {
AnnaBridge 187:0387e8f68319 612 uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
AnnaBridge 187:0387e8f68319 613
AnnaBridge 187:0387e8f68319 614 I2C_SET_DATA(i2c_base, *obj->i2c.tran_pos ++);
AnnaBridge 187:0387e8f68319 615 if (obj->i2c.tran_pos == obj->i2c.tran_end &&
AnnaBridge 187:0387e8f68319 616 obj->i2c.tran_ctrl & TRANCTRL_NAKLASTDATA) {
AnnaBridge 187:0387e8f68319 617 // Last data
AnnaBridge 187:0387e8f68319 618 i2c_ctl &= ~I2C_CTL0_AA_Msk;
AnnaBridge 187:0387e8f68319 619 }
AnnaBridge 187:0387e8f68319 620 I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
AnnaBridge 187:0387e8f68319 621 } else {
AnnaBridge 187:0387e8f68319 622 obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
AnnaBridge 187:0387e8f68319 623 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 624 break;
AnnaBridge 187:0387e8f68319 625 }
AnnaBridge 187:0387e8f68319 626 } else {
AnnaBridge 187:0387e8f68319 627 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 628 }
AnnaBridge 187:0387e8f68319 629 obj->i2c.slaveaddr_state = ReadAddressed;
AnnaBridge 187:0387e8f68319 630 break;
AnnaBridge 187:0387e8f68319 631 //case 0xA0: // Slave Transmit Repeat Start or Stop
AnnaBridge 187:0387e8f68319 632 case 0xC0: // Slave Transmit Data NACK
AnnaBridge 187:0387e8f68319 633 case 0xC8: // Slave Transmit Last Data ACK
AnnaBridge 187:0387e8f68319 634 obj->i2c.slaveaddr_state = NoData;
AnnaBridge 187:0387e8f68319 635 i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
AnnaBridge 187:0387e8f68319 636 break;
AnnaBridge 187:0387e8f68319 637
AnnaBridge 187:0387e8f68319 638 // Slave Receive
AnnaBridge 187:0387e8f68319 639 case 0x80: // Slave Receive Data ACK
AnnaBridge 187:0387e8f68319 640 case 0x88: // Slave Receive Data NACK
AnnaBridge 187:0387e8f68319 641 case 0x60: // Slave Receive Address ACK
AnnaBridge 187:0387e8f68319 642 case 0x68: // Slave Receive Arbitration Lost
AnnaBridge 187:0387e8f68319 643 obj->i2c.slaveaddr_state = WriteAddressed;
AnnaBridge 187:0387e8f68319 644 if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
AnnaBridge 187:0387e8f68319 645 if (obj->i2c.tran_pos < obj->i2c.tran_end) {
AnnaBridge 187:0387e8f68319 646 if (status == 0x80 || status == 0x88) {
AnnaBridge 187:0387e8f68319 647 *obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
AnnaBridge 187:0387e8f68319 648 }
AnnaBridge 187:0387e8f68319 649
AnnaBridge 187:0387e8f68319 650 if (status == 0x88) {
AnnaBridge 187:0387e8f68319 651 obj->i2c.slaveaddr_state = NoData;
AnnaBridge 187:0387e8f68319 652 i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
AnnaBridge 187:0387e8f68319 653 } else {
AnnaBridge 187:0387e8f68319 654 uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
AnnaBridge 187:0387e8f68319 655 if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
AnnaBridge 187:0387e8f68319 656 obj->i2c.tran_ctrl & TRANCTRL_NAKLASTDATA) {
AnnaBridge 187:0387e8f68319 657 // Last data
AnnaBridge 187:0387e8f68319 658 i2c_ctl &= ~I2C_CTL0_AA_Msk;
AnnaBridge 187:0387e8f68319 659 }
AnnaBridge 187:0387e8f68319 660 I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
AnnaBridge 187:0387e8f68319 661 }
AnnaBridge 187:0387e8f68319 662 } else {
AnnaBridge 187:0387e8f68319 663 obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
AnnaBridge 187:0387e8f68319 664 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 665 break;
AnnaBridge 187:0387e8f68319 666 }
AnnaBridge 187:0387e8f68319 667 } else {
AnnaBridge 187:0387e8f68319 668 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 669 }
AnnaBridge 187:0387e8f68319 670 break;
AnnaBridge 187:0387e8f68319 671 //case 0xA0: // Slave Receive Repeat Start or Stop
AnnaBridge 187:0387e8f68319 672
AnnaBridge 187:0387e8f68319 673 // GC mode
AnnaBridge 187:0387e8f68319 674 //case 0xA0: // GC mode Repeat Start or Stop
AnnaBridge 187:0387e8f68319 675 case 0x90: // GC mode Data ACK
AnnaBridge 187:0387e8f68319 676 case 0x98: // GC mode Data NACK
AnnaBridge 187:0387e8f68319 677 case 0x70: // GC mode Address ACK
AnnaBridge 187:0387e8f68319 678 case 0x78: // GC mode Arbitration Lost
AnnaBridge 187:0387e8f68319 679 obj->i2c.slaveaddr_state = WriteAddressed;
AnnaBridge 187:0387e8f68319 680 if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
AnnaBridge 187:0387e8f68319 681 if (obj->i2c.tran_pos < obj->i2c.tran_end) {
AnnaBridge 187:0387e8f68319 682 if (status == 0x90 || status == 0x98) {
AnnaBridge 187:0387e8f68319 683 *obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
AnnaBridge 187:0387e8f68319 684 }
AnnaBridge 187:0387e8f68319 685
AnnaBridge 187:0387e8f68319 686 if (status == 0x98) {
AnnaBridge 187:0387e8f68319 687 obj->i2c.slaveaddr_state = NoData;
AnnaBridge 187:0387e8f68319 688 i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
AnnaBridge 187:0387e8f68319 689 } else {
AnnaBridge 187:0387e8f68319 690 uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
AnnaBridge 187:0387e8f68319 691 if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
AnnaBridge 187:0387e8f68319 692 obj->i2c.tran_ctrl & TRANCTRL_NAKLASTDATA) {
AnnaBridge 187:0387e8f68319 693 // Last data
AnnaBridge 187:0387e8f68319 694 i2c_ctl &= ~I2C_CTL0_AA_Msk;
AnnaBridge 187:0387e8f68319 695 }
AnnaBridge 187:0387e8f68319 696 I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
AnnaBridge 187:0387e8f68319 697 }
AnnaBridge 187:0387e8f68319 698 } else {
AnnaBridge 187:0387e8f68319 699 obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
AnnaBridge 187:0387e8f68319 700 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 701 break;
AnnaBridge 187:0387e8f68319 702 }
AnnaBridge 187:0387e8f68319 703 } else {
AnnaBridge 187:0387e8f68319 704 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 705 }
AnnaBridge 187:0387e8f68319 706 break;
AnnaBridge 187:0387e8f68319 707
AnnaBridge 187:0387e8f68319 708 case 0xF8: // Bus Released
AnnaBridge 187:0387e8f68319 709 break;
AnnaBridge 187:0387e8f68319 710
AnnaBridge 187:0387e8f68319 711 default:
AnnaBridge 187:0387e8f68319 712 i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
AnnaBridge 187:0387e8f68319 713 }
AnnaBridge 187:0387e8f68319 714 }
AnnaBridge 187:0387e8f68319 715
AnnaBridge 187:0387e8f68319 716 static void i2c_fsm_reset(i2c_t *obj, uint32_t i2c_ctl)
AnnaBridge 187:0387e8f68319 717 {
AnnaBridge 187:0387e8f68319 718 I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c);
AnnaBridge 187:0387e8f68319 719
AnnaBridge 187:0387e8f68319 720 obj->i2c.stop = 0;
AnnaBridge 187:0387e8f68319 721
AnnaBridge 187:0387e8f68319 722 obj->i2c.tran_ctrl = 0;
AnnaBridge 187:0387e8f68319 723
AnnaBridge 187:0387e8f68319 724 I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
AnnaBridge 187:0387e8f68319 725 obj->i2c.slaveaddr_state = NoData;
AnnaBridge 187:0387e8f68319 726 }
AnnaBridge 187:0387e8f68319 727
AnnaBridge 187:0387e8f68319 728 static void i2c_fsm_tranfini(i2c_t *obj, int lastdatanaked)
AnnaBridge 187:0387e8f68319 729 {
AnnaBridge 187:0387e8f68319 730 if (lastdatanaked) {
AnnaBridge 187:0387e8f68319 731 obj->i2c.tran_ctrl |= TRANCTRL_LASTDATANAKED;
AnnaBridge 187:0387e8f68319 732 }
AnnaBridge 187:0387e8f68319 733
AnnaBridge 187:0387e8f68319 734 obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
AnnaBridge 187:0387e8f68319 735 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 736 }
AnnaBridge 187:0387e8f68319 737
AnnaBridge 187:0387e8f68319 738 #if DEVICE_I2C_ASYNCH
AnnaBridge 187:0387e8f68319 739
AnnaBridge 187:0387e8f68319 740 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)
AnnaBridge 187:0387e8f68319 741 {
AnnaBridge 187:0387e8f68319 742 // NOTE: The mbed I2C address passed in is shifted left by 1 bit (7-bit addr << 1).
AnnaBridge 187:0387e8f68319 743
AnnaBridge 187:0387e8f68319 744 // NOTE: First transmit and then receive.
AnnaBridge 187:0387e8f68319 745
AnnaBridge 187:0387e8f68319 746 (void) hint;
AnnaBridge 187:0387e8f68319 747 obj->i2c.dma_usage = DMA_USAGE_NEVER;
AnnaBridge 187:0387e8f68319 748 obj->i2c.stop = stop;
AnnaBridge 187:0387e8f68319 749 obj->i2c.address = address;
AnnaBridge 187:0387e8f68319 750 obj->i2c.event = event;
AnnaBridge 187:0387e8f68319 751 i2c_buffer_set(obj, tx, tx_length, rx, rx_length);
AnnaBridge 187:0387e8f68319 752
AnnaBridge 187:0387e8f68319 753 i2c_enable_vector_interrupt(obj, handler, 1);
AnnaBridge 187:0387e8f68319 754 i2c_start(obj);
AnnaBridge 187:0387e8f68319 755 }
AnnaBridge 187:0387e8f68319 756
AnnaBridge 187:0387e8f68319 757 uint32_t i2c_irq_handler_asynch(i2c_t *obj)
AnnaBridge 187:0387e8f68319 758 {
AnnaBridge 187:0387e8f68319 759 int event = 0;
AnnaBridge 187:0387e8f68319 760
AnnaBridge 187:0387e8f68319 761 I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c);
AnnaBridge 187:0387e8f68319 762 uint32_t status = I2C_GET_STATUS(i2c_base);
AnnaBridge 187:0387e8f68319 763 switch (status) {
AnnaBridge 187:0387e8f68319 764 case 0x08: // Start
AnnaBridge 187:0387e8f68319 765 case 0x10: {// Master Repeat Start
AnnaBridge 187:0387e8f68319 766 if (obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) {
AnnaBridge 187:0387e8f68319 767 I2C_SET_DATA(i2c_base, (i2c_addr2data(obj->i2c.address, 0)));
AnnaBridge 187:0387e8f68319 768 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 769 } else if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) {
AnnaBridge 187:0387e8f68319 770 I2C_SET_DATA(i2c_base, (i2c_addr2data(obj->i2c.address, 1)));
AnnaBridge 187:0387e8f68319 771 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 772 } else {
AnnaBridge 187:0387e8f68319 773 event = I2C_EVENT_TRANSFER_COMPLETE;
AnnaBridge 187:0387e8f68319 774 if (obj->i2c.stop) {
AnnaBridge 187:0387e8f68319 775 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 776 }
AnnaBridge 187:0387e8f68319 777 }
AnnaBridge 187:0387e8f68319 778 break;
AnnaBridge 187:0387e8f68319 779 }
AnnaBridge 187:0387e8f68319 780
AnnaBridge 187:0387e8f68319 781 case 0x18: // Master Transmit Address ACK
AnnaBridge 187:0387e8f68319 782 case 0x28: // Master Transmit Data ACK
AnnaBridge 187:0387e8f68319 783 if (obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) {
AnnaBridge 187:0387e8f68319 784 uint8_t *tx = (uint8_t *)obj->tx_buff.buffer;
AnnaBridge 187:0387e8f68319 785 I2C_SET_DATA(i2c_base, tx[obj->tx_buff.pos ++]);
AnnaBridge 187:0387e8f68319 786 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 787 } else if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) {
AnnaBridge 187:0387e8f68319 788 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STA_Msk | I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 789 } else {
AnnaBridge 187:0387e8f68319 790 event = I2C_EVENT_TRANSFER_COMPLETE;
AnnaBridge 187:0387e8f68319 791 if (obj->i2c.stop) {
AnnaBridge 187:0387e8f68319 792 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 793 }
AnnaBridge 187:0387e8f68319 794 }
AnnaBridge 187:0387e8f68319 795 break;
AnnaBridge 187:0387e8f68319 796
AnnaBridge 187:0387e8f68319 797 case 0x20: // Master Transmit Address NACK
AnnaBridge 187:0387e8f68319 798 event = I2C_EVENT_ERROR_NO_SLAVE;
AnnaBridge 187:0387e8f68319 799 if (obj->i2c.stop) {
AnnaBridge 187:0387e8f68319 800 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 801 }
AnnaBridge 187:0387e8f68319 802 break;
AnnaBridge 187:0387e8f68319 803
AnnaBridge 187:0387e8f68319 804 case 0x30: // Master Transmit Data NACK
AnnaBridge 187:0387e8f68319 805 if (obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) {
AnnaBridge 187:0387e8f68319 806 event = I2C_EVENT_TRANSFER_EARLY_NACK;
AnnaBridge 187:0387e8f68319 807 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 808 } else if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) {
AnnaBridge 187:0387e8f68319 809 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STA_Msk | I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 810 } else {
AnnaBridge 187:0387e8f68319 811 event = I2C_EVENT_TRANSFER_COMPLETE;
AnnaBridge 187:0387e8f68319 812 if (obj->i2c.stop) {
AnnaBridge 187:0387e8f68319 813 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 814 }
AnnaBridge 187:0387e8f68319 815 }
AnnaBridge 187:0387e8f68319 816 break;
AnnaBridge 187:0387e8f68319 817
AnnaBridge 187:0387e8f68319 818 case 0x38: // Master Arbitration Lost
AnnaBridge 187:0387e8f68319 819 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk); // Enter not addressed SLV mode
AnnaBridge 187:0387e8f68319 820 event = I2C_EVENT_ERROR;
AnnaBridge 187:0387e8f68319 821 break;
AnnaBridge 187:0387e8f68319 822
AnnaBridge 187:0387e8f68319 823 case 0x50: // Master Receive Data ACK
AnnaBridge 187:0387e8f68319 824 if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) {
AnnaBridge 187:0387e8f68319 825 uint8_t *rx = (uint8_t *) obj->rx_buff.buffer;
AnnaBridge 187:0387e8f68319 826 rx[obj->rx_buff.pos ++] = I2C_GET_DATA(((I2C_T *) NU_MODBASE(obj->i2c.i2c)));
AnnaBridge 187:0387e8f68319 827 }
AnnaBridge 187:0387e8f68319 828 case 0x40: // Master Receive Address ACK
AnnaBridge 187:0387e8f68319 829 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk | ((obj->rx_buff.pos != obj->rx_buff.length - 1) ? I2C_CTL0_AA_Msk : 0));
AnnaBridge 187:0387e8f68319 830 break;
AnnaBridge 187:0387e8f68319 831
AnnaBridge 187:0387e8f68319 832 case 0x48: // Master Receive Address NACK
AnnaBridge 187:0387e8f68319 833 event = I2C_EVENT_ERROR_NO_SLAVE;
AnnaBridge 187:0387e8f68319 834 if (obj->i2c.stop) {
AnnaBridge 187:0387e8f68319 835 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 836 }
AnnaBridge 187:0387e8f68319 837 break;
AnnaBridge 187:0387e8f68319 838
AnnaBridge 187:0387e8f68319 839 case 0x58: // Master Receive Data NACK
AnnaBridge 187:0387e8f68319 840 if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) {
AnnaBridge 187:0387e8f68319 841 uint8_t *rx = (uint8_t *) obj->rx_buff.buffer;
AnnaBridge 187:0387e8f68319 842 rx[obj->rx_buff.pos ++] = I2C_GET_DATA(((I2C_T *) NU_MODBASE(obj->i2c.i2c)));
AnnaBridge 187:0387e8f68319 843 }
AnnaBridge 187:0387e8f68319 844 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STA_Msk | I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 845 break;
AnnaBridge 187:0387e8f68319 846
AnnaBridge 187:0387e8f68319 847 case 0x00: // Bus error
AnnaBridge 187:0387e8f68319 848 event = I2C_EVENT_ERROR;
AnnaBridge 187:0387e8f68319 849 i2c_reset(obj);
AnnaBridge 187:0387e8f68319 850 break;
AnnaBridge 187:0387e8f68319 851
AnnaBridge 187:0387e8f68319 852 default:
AnnaBridge 187:0387e8f68319 853 event = I2C_EVENT_ERROR;
AnnaBridge 187:0387e8f68319 854 if (obj->i2c.stop) {
AnnaBridge 187:0387e8f68319 855 I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk);
AnnaBridge 187:0387e8f68319 856 }
AnnaBridge 187:0387e8f68319 857 }
AnnaBridge 187:0387e8f68319 858
AnnaBridge 187:0387e8f68319 859 if (event) {
AnnaBridge 187:0387e8f68319 860 i2c_rollback_vector_interrupt(obj);
AnnaBridge 187:0387e8f68319 861 }
AnnaBridge 187:0387e8f68319 862
AnnaBridge 187:0387e8f68319 863 return (event & obj->i2c.event);
AnnaBridge 187:0387e8f68319 864 }
AnnaBridge 187:0387e8f68319 865
AnnaBridge 187:0387e8f68319 866 uint8_t i2c_active(i2c_t *obj)
AnnaBridge 187:0387e8f68319 867 {
AnnaBridge 187:0387e8f68319 868 const struct nu_modinit_s *modinit = get_modinit(obj->i2c.i2c, i2c_modinit_tab);
AnnaBridge 187:0387e8f68319 869 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 870 MBED_ASSERT(modinit->modname == (int) obj->i2c.i2c);
AnnaBridge 187:0387e8f68319 871
AnnaBridge 187:0387e8f68319 872 // Vector will be changed for async transfer. Use it to judge if async transfer is on-going.
AnnaBridge 187:0387e8f68319 873 uint32_t vec = NVIC_GetVector(modinit->irq_n);
AnnaBridge 187:0387e8f68319 874 struct nu_i2c_var *var = (struct nu_i2c_var *) modinit->var;
AnnaBridge 187:0387e8f68319 875 return (vec && vec != (uint32_t) var->vec);
AnnaBridge 187:0387e8f68319 876 }
AnnaBridge 187:0387e8f68319 877
AnnaBridge 187:0387e8f68319 878 void i2c_abort_asynch(i2c_t *obj)
AnnaBridge 187:0387e8f68319 879 {
AnnaBridge 187:0387e8f68319 880 i2c_rollback_vector_interrupt(obj);
AnnaBridge 187:0387e8f68319 881 i2c_stop(obj);
AnnaBridge 187:0387e8f68319 882 }
AnnaBridge 187:0387e8f68319 883
AnnaBridge 187:0387e8f68319 884 static void i2c_buffer_set(i2c_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length)
AnnaBridge 187:0387e8f68319 885 {
AnnaBridge 187:0387e8f68319 886 obj->tx_buff.buffer = (void *) tx;
AnnaBridge 187:0387e8f68319 887 obj->tx_buff.length = tx_length;
AnnaBridge 187:0387e8f68319 888 obj->tx_buff.pos = 0;
AnnaBridge 187:0387e8f68319 889 obj->rx_buff.buffer = rx;
AnnaBridge 187:0387e8f68319 890 obj->rx_buff.length = rx_length;
AnnaBridge 187:0387e8f68319 891 obj->rx_buff.pos = 0;
AnnaBridge 187:0387e8f68319 892 }
AnnaBridge 187:0387e8f68319 893
AnnaBridge 187:0387e8f68319 894 static void i2c_enable_vector_interrupt(i2c_t *obj, uint32_t handler, int enable)
AnnaBridge 187:0387e8f68319 895 {
AnnaBridge 187:0387e8f68319 896 const struct nu_modinit_s *modinit = get_modinit(obj->i2c.i2c, i2c_modinit_tab);
AnnaBridge 187:0387e8f68319 897 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 898 MBED_ASSERT(modinit->modname == (int) obj->i2c.i2c);
AnnaBridge 187:0387e8f68319 899
AnnaBridge 187:0387e8f68319 900 if (enable) {
AnnaBridge 187:0387e8f68319 901 NVIC_SetVector(modinit->irq_n, handler);
AnnaBridge 187:0387e8f68319 902 i2c_enable_int(obj);
AnnaBridge 187:0387e8f68319 903 } else {
AnnaBridge 187:0387e8f68319 904 i2c_disable_int(obj);
AnnaBridge 187:0387e8f68319 905 }
AnnaBridge 187:0387e8f68319 906
AnnaBridge 187:0387e8f68319 907 }
AnnaBridge 187:0387e8f68319 908
AnnaBridge 187:0387e8f68319 909 static void i2c_rollback_vector_interrupt(i2c_t *obj)
AnnaBridge 187:0387e8f68319 910 {
AnnaBridge 187:0387e8f68319 911 const struct nu_modinit_s *modinit = get_modinit(obj->i2c.i2c, i2c_modinit_tab);
AnnaBridge 187:0387e8f68319 912 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 913 MBED_ASSERT(modinit->modname == (int) obj->i2c.i2c);
AnnaBridge 187:0387e8f68319 914
AnnaBridge 187:0387e8f68319 915 struct nu_i2c_var *var = (struct nu_i2c_var *) modinit->var;
AnnaBridge 187:0387e8f68319 916 i2c_enable_vector_interrupt(obj, (uint32_t) var->vec, 1);
AnnaBridge 187:0387e8f68319 917 }
AnnaBridge 187:0387e8f68319 918
AnnaBridge 187:0387e8f68319 919 #endif
AnnaBridge 187:0387e8f68319 920
AnnaBridge 187:0387e8f68319 921 #endif