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