Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Sat Jun 03 00:22:44 2017 +0000
Revision:
46:b156ef445742
Parent:
18:6a4db94011d3
Final code for internal battlebot competition.

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