Mateusz Kowalik / Application_danix

Fork of Application by Daniel Sygut

Committer:
Zaitsev
Date:
Tue Jan 10 20:42:26 2017 +0000
Revision:
10:41552d038a69
USB Serial bi-directional bridge

Who changed what in which revision?

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