Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Sun May 14 23:18:57 2017 +0000
Revision:
18:6a4db94011d3
Publishing again

Who changed what in which revision?

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