test

Committer:
elijahsj
Date:
Mon Nov 09 00:02:47 2020 -0500
Revision:
1:8a094db1347f
test

Who changed what in which revision?

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