added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
JojoS
Date:
Sat Sep 10 15:32:04 2016 +0000
Revision:
147:ba84b7dc41a7
Parent:
144:ef7eb2e8f9f7
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time

Who changed what in which revision?

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