Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Wed Oct 10 00:33:53 2018 +0000
Revision:
0:8fdf9a60065b
how to make mbed librry

Who changed what in which revision?

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