5.2.1 - Updated I2C files

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

Committer:
jacobjohnson
Date:
Mon Feb 27 17:45:05 2017 +0000
Revision:
1:f30bdcd2b33b
Parent:
0:098463de4c5d
changed the inputscale from 1 to 7 in analogin_api.c.  This will need to be changed later, and accessed from the main level, but for now this allows the  adc to read a value from 0 to 3.7V, instead of just up to 1V.;

Who changed what in which revision?

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