Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Thu Oct 11 02:27:46 2018 +0000
Revision:
3:f3764f852aa8
Parent:
0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;

Who changed what in which revision?

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