mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Thu Aug 31 17:27:04 2017 +0100
Revision:
172:7d866c31b3c5
Child:
176:447f873cad2f
This updates the lib to the mbed lib v 150

Who changed what in which revision?

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