mbed

Fork of mbed-dev by mbed official

Committer:
AnnaBridge
Date:
Wed Oct 25 14:53:38 2017 +0100
Revision:
177:447f873cad2f
Parent:
173:7d866c31b3c5
This updates the lib to the mbed lib v 154

Who changed what in which revision?

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