/* mbed Microcontroller Library * Copyright (c) 2006-2013 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "mbed_assert.h" #include "dma_api.h" #include "i2c_api.h" #include "cmsis.h" #include "PeripheralPins.h" #include "r_typedefs.h" #include "iodefine.h" #include "RZ_A1_Init.h" volatile struct st_riic *RIIC[] = RIIC_ADDRESS_LIST; #define REG(N) \ RIIC[obj->i2c.i2c]->RIICn##N /* RIICnCR1 */ #define CR1_RST (1 << 6) #define CR1_ICE (1 << 7) /* RIICnCR2 */ #define CR2_ST (1 << 1) #define CR2_RS (1 << 2) #define CR2_SP (1 << 3) #define CR2_TRS (1 << 5) #define CR2_BBSY (1 << 7) /* RIICnMR3 */ #define MR3_ACKBT (1 << 3) #define MR3_ACKWP (1 << 4) #define MR3_WAIT (1 << 6) /* RIICnSER */ #define SER_SAR0E (1 << 0) /* RIICnSR1 */ #define SR1_AAS0 (1 << 0) /* RIICnSR2 */ #define SR2_START (1 << 2) #define SR2_STOP (1 << 3) #define SR2_NACKF (1 << 4) #define SR2_RDRF (1 << 5) #define SR2_TEND (1 << 6) #define SR2_TDRE (1 << 7) #define WAIT_TIMEOUT (3600000) /* Loop counter : Time-out is about 1s. By 3600000 loops, measured value is 969ms. */ static inline int i2c_status(i2c_t *obj) { return REG(SR2.UINT8[0]); } static void i2c_reg_reset(i2c_t *obj) { /* full reset */ REG(CR1.UINT8[0]) &= ~CR1_ICE; // CR1.ICE off REG(CR1.UINT8[0]) |= CR1_RST; // CR1.IICRST on REG(CR1.UINT8[0]) |= CR1_ICE; // CR1.ICE on REG(MR1.UINT8[0]) = 0x08; // P_phi /x 9bit (including Ack) REG(SER.UINT8[0]) = 0x00; // no slave addr enabled /* set frequency */ REG(MR1.UINT8[0]) |= obj->i2c.pclk_bit; REG(BRL.UINT8[0]) = obj->i2c.width_low; REG(BRH.UINT8[0]) = obj->i2c.width_hi; REG(MR2.UINT8[0]) = 0x07; REG(MR3.UINT8[0]) = 0x00; REG(FER.UINT8[0]) = 0x72; // SCLE, NFE enabled, TMOT REG(IER.UINT8[0]) = 0x00; // no interrupt REG(CR1.UINT32) &= ~CR1_RST; // CR1.IICRST negate reset } static inline int i2c_wait_RDRF(i2c_t *obj) { int timeout = 0; /* There is no timeout, but the upper limit value is set to avoid an infinite loop. */ while ((i2c_status(obj) & SR2_RDRF) == 0) { timeout ++; if (timeout >= WAIT_TIMEOUT) { return -1; } } return 0; } static int i2c_wait_TDRE(i2c_t *obj) { int timeout = 0; /* There is no timeout, but the upper limit value is set to avoid an infinite loop. */ while ((i2c_status(obj) & SR2_TDRE) == 0) { timeout ++; if (timeout >= WAIT_TIMEOUT) { return -1; } } return 0; } static int i2c_wait_TEND(i2c_t *obj) { int timeout = 0; /* There is no timeout, but the upper limit value is set to avoid an infinite loop. */ while ((i2c_status(obj) & SR2_TEND) == 0) { timeout ++; if (timeout >= WAIT_TIMEOUT) { return -1; } } return 0; } static int i2c_wait_START(i2c_t *obj) { int timeout = 0; /* There is no timeout, but the upper limit value is set to avoid an infinite loop. */ while ((i2c_status(obj) & SR2_START) == 0) { timeout ++; if (timeout >= WAIT_TIMEOUT) { return -1; } } return 0; } static int i2c_wait_STOP(i2c_t *obj) { int timeout = 0; /* There is no timeout, but the upper limit value is set to avoid an infinite loop. */ while ((i2c_status(obj) & SR2_STOP) == 0) { timeout ++; if (timeout >= WAIT_TIMEOUT) { return -1; } } return 0; } static int i2c_set_STOP(i2c_t *obj) { /* SR2.STOP = 0 */ REG(SR2.UINT32) &= ~SR2_STOP; /* Stop condition */ REG(CR2.UINT32) |= CR2_SP; return 0; } static void i2c_set_SR2_NACKF_STOP(i2c_t *obj) { /* SR2.NACKF = 0 */ REG(SR2.UINT32) &= ~SR2_NACKF; /* SR2.STOP = 0 */ REG(SR2.UINT32) &= ~SR2_STOP; } static void i2c_set_MR3_NACK(i2c_t *obj) { /* send a NOT ACK */ REG(MR3.UINT32) |= MR3_ACKWP; REG(MR3.UINT32) |= MR3_ACKBT; REG(MR3.UINT32) &= ~MR3_ACKWP; } static void i2c_set_MR3_ACK(i2c_t *obj) { /* send a ACK */ REG(MR3.UINT32) |= MR3_ACKWP; REG(MR3.UINT32) &= ~MR3_ACKBT; REG(MR3.UINT32) &= ~MR3_ACKWP; } static inline void i2c_power_enable(i2c_t *obj) { volatile uint8_t dummy; switch ((int)obj->i2c.i2c) { case I2C_0: CPGSTBCR9 &= ~(0x80); break; case I2C_1: CPGSTBCR9 &= ~(0x40); break; case I2C_2: CPGSTBCR9 &= ~(0x20); break; case I2C_3: CPGSTBCR9 &= ~(0x10); break; } dummy = CPGSTBCR9; (void)dummy; } void i2c_init(i2c_t *obj, PinName sda, PinName scl) { /* determine the I2C to use */ I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA); I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL); obj->i2c.i2c = pinmap_merge(i2c_sda, i2c_scl); MBED_ASSERT((int)obj->i2c.i2c != NC); /* enable power */ i2c_power_enable(obj); /* set default frequency at 100k */ i2c_frequency(obj, 100000); pinmap_pinout(sda, PinMap_I2C_SDA); pinmap_pinout(scl, PinMap_I2C_SCL); obj->i2c.last_stop_flag = 1; } inline int i2c_start(i2c_t *obj) { int timeout = 0; while ((REG(CR2.UINT32) & CR2_BBSY) != 0) { timeout ++; if (timeout >= obj->i2c.bbsy_wait_cnt) { break; } } /* Start Condition */ REG(CR2.UINT8[0]) |= CR2_ST; return 0; } static inline int i2c_restart(i2c_t *obj) { /* SR2.START = 0 */ REG(SR2.UINT32) &= ~SR2_START; /* ReStart condition */ REG(CR2.UINT32) |= CR2_RS; return 0; } inline int i2c_stop(i2c_t *obj) { (void)i2c_set_STOP(obj); (void)i2c_wait_STOP(obj); i2c_set_SR2_NACKF_STOP(obj); return 0; } static void i2c_set_err_noslave(i2c_t *obj) { (void)i2c_set_STOP(obj); (void)i2c_wait_STOP(obj); i2c_set_SR2_NACKF_STOP(obj); obj->i2c.last_stop_flag = 1; } static inline int i2c_do_write(i2c_t *obj, int value) { int timeout = 0; /* There is no timeout, but the upper limit value is set to avoid an infinite loop. */ while ((i2c_status(obj) & SR2_TDRE) == 0) { timeout ++; if (timeout >= WAIT_TIMEOUT) { return -1; } } /* write the data */ REG(DRT.UINT32) = value; return 0; } static inline int i2c_read_address_write(i2c_t *obj, int value) { int status; status = i2c_wait_TDRE(obj); if (status == 0) { /* write the data */ REG(DRT.UINT32) = value; } return status; } static inline int i2c_do_read(i2c_t *obj, int last) { if (last == 2) { /* this time is befor last byte read */ /* Set MR3 WAIT bit is 1 */; REG(MR3.UINT32) |= MR3_WAIT; } else if (last == 1) { i2c_set_MR3_NACK(obj); } else { i2c_set_MR3_ACK(obj); } /* return the data */ return (REG(DRR.UINT32) & 0xFF); } void i2c_frequency(i2c_t *obj, int hz) { float64_t pclk_val; float64_t wait_utime; volatile float64_t bps; volatile float64_t L_time; /* H Width period */ volatile float64_t H_time; /* L Width period */ uint32_t tmp_L_width; uint32_t tmp_H_width; uint32_t remainder; uint32_t wk_cks = 0; /* set PCLK */ if (false == RZ_A1_IsClockMode0()) { pclk_val = (float64_t)CM1_RENESAS_RZ_A1_P0_CLK; } else { pclk_val = (float64_t)CM0_RENESAS_RZ_A1_P0_CLK; } /* Min 10kHz, Max 400kHz */ if (hz < 10000) { bps = 10000; } else if (hz > 400000) { bps = 400000; } else { bps = (float64_t)hz; } /* Calculation L width time */ L_time = (1 / (2 * bps)); /* Harf period of frequency */ H_time = L_time; /* Check I2C mode of Speed */ if (bps > 100000) { /* Fast-mode */ L_time -= 102E-9; /* Falling time of SCL clock. */ H_time -= 138E-9; /* Rising time of SCL clock. */ /* Check L wideth */ if (L_time < 1.3E-6) { /* Wnen L width less than 1.3us */ /* Subtract Rise up and down time for SCL from H/L width */ L_time = 1.3E-6; H_time = (1 / bps) - L_time - 138E-9 - 102E-9; } } tmp_L_width = (uint32_t)(L_time * pclk_val * 10); tmp_L_width >>= 1; wk_cks++; while (tmp_L_width >= 341) { tmp_L_width >>= 1; wk_cks++; } remainder = tmp_L_width % 10; tmp_L_width = ((tmp_L_width + 9) / 10) - 3; /* carry */ tmp_H_width = (uint32_t)(H_time * pclk_val * 10); tmp_H_width >>= wk_cks; if (remainder == 0) { tmp_H_width = ((tmp_H_width + 9) / 10) - 3; /* carry */ } else { remainder += tmp_H_width % 10; tmp_H_width = (tmp_H_width / 10) - 3; if (remainder > 10) { tmp_H_width += 1; /* fine adjustment */ } } /* timeout of BBSY bit is minimum low width by frequency */ /* so timeout calculates "(low width) * 2" by frequency */ wait_utime = (L_time * 2) * 1000000; /* 1 wait of BBSY bit is about 0.3us. if it's below 0.3us, wait count is set as 1. */ if (wait_utime <= 0.3) { obj->i2c.bbsy_wait_cnt = 1; } else { obj->i2c.bbsy_wait_cnt = (int)(wait_utime / 0.3); } /* I2C Rate */ obj->i2c.pclk_bit = (uint8_t)(0x10 * wk_cks); /* P_phi / xx */ obj->i2c.width_low = (uint8_t)(tmp_L_width | 0x000000E0); obj->i2c.width_hi = (uint8_t)(tmp_H_width | 0x000000E0); /* full reset */ i2c_reg_reset(obj); } int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { int count = 0; int status; int value; i2c_set_MR3_ACK(obj); /* There is a STOP condition for last processing */ if (obj->i2c.last_stop_flag != 0) { status = i2c_start(obj); if (status != 0) { i2c_set_err_noslave(obj); return I2C_ERROR_BUS_BUSY; } } obj->i2c.last_stop_flag = stop; /* Send Slave address */ status = i2c_read_address_write(obj, (address | 0x01)); if (status != 0) { i2c_set_err_noslave(obj); return I2C_ERROR_NO_SLAVE; } /* wait RDRF */ status = i2c_wait_RDRF(obj); /* check ACK/NACK */ if ((status != 0) || ((REG(SR2.UINT32) & SR2_NACKF) != 0)) { /* Slave sends NACK */ (void)i2c_set_STOP(obj); /* dummy read */ value = REG(DRR.UINT32); (void)i2c_wait_STOP(obj); i2c_set_SR2_NACKF_STOP(obj); obj->i2c.last_stop_flag = 1; return I2C_ERROR_NO_SLAVE; } if (length != 0) { /* Read in all except last byte */ if (length > 2) { /* dummy read */ value = REG(DRR.UINT32); for (count = 0; count < (length - 1); count++) { /* wait for it to arrive */ status = i2c_wait_RDRF(obj); if (status != 0) { i2c_set_err_noslave(obj); return I2C_ERROR_NO_SLAVE; } /* Recieve the data */ if (count == (length - 2)) { value = i2c_do_read(obj, 1); } else if ((length >= 3) && (count == (length - 3))) { value = i2c_do_read(obj, 2); } else { value = i2c_do_read(obj, 0); } data[count] = (char)value; } } else if (length == 2) { /* Set MR3 WAIT bit is 1 */ REG(MR3.UINT32) |= MR3_WAIT; /* dummy read */ value = REG(DRR.UINT32); /* wait for it to arrive */ status = i2c_wait_RDRF(obj); if (status != 0) { i2c_set_err_noslave(obj); return I2C_ERROR_NO_SLAVE; } i2c_set_MR3_NACK(obj); data[count] = (char)REG(DRR.UINT32); count++; } else { /* length == 1 */ /* Set MR3 WAIT bit is 1 */; REG(MR3.UINT32) |= MR3_WAIT; i2c_set_MR3_NACK(obj); /* dummy read */ value = REG(DRR.UINT32); } /* wait for it to arrive */ status = i2c_wait_RDRF(obj); if (status != 0) { i2c_set_err_noslave(obj); return I2C_ERROR_NO_SLAVE; } /* If not repeated start, send stop. */ if (stop) { (void)i2c_set_STOP(obj); /* RIICnDRR read */ value = (REG(DRR.UINT32) & 0xFF); data[count] = (char)value; /* RIICnMR3.WAIT = 0 */ REG(MR3.UINT32) &= ~MR3_WAIT; (void)i2c_wait_STOP(obj); i2c_set_SR2_NACKF_STOP(obj); } else { (void)i2c_restart(obj); /* RIICnDRR read */ value = (REG(DRR.UINT32) & 0xFF); data[count] = (char)value; /* RIICnMR3.WAIT = 0 */ REG(MR3.UINT32) &= ~MR3_WAIT; (void)i2c_wait_START(obj); /* SR2.START = 0 */ REG(SR2.UINT32) &= ~SR2_START; } } else { /* If not repeated start, send stop. */ if (stop) { (void)i2c_set_STOP(obj); (void)i2c_wait_STOP(obj); i2c_set_SR2_NACKF_STOP(obj); } else { (void)i2c_restart(obj); (void)i2c_wait_START(obj); /* SR2.START = 0 */ REG(SR2.UINT32) &= ~SR2_START; } } return length; } int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { int cnt; int status; /* There is a STOP condition for last processing */ if (obj->i2c.last_stop_flag != 0) { status = i2c_start(obj); if (status != 0) { i2c_set_err_noslave(obj); return I2C_ERROR_BUS_BUSY; } } obj->i2c.last_stop_flag = stop; /* Send Slave address */ status = i2c_do_write(obj, address); if (status != 0) { i2c_set_err_noslave(obj); return I2C_ERROR_NO_SLAVE; } /* Wait send end */ status = i2c_wait_TEND(obj); if ((status != 0) || ((REG(SR2.UINT32) & SR2_NACKF) != 0)) { /* Slave sends NACK */ i2c_set_err_noslave(obj); return I2C_ERROR_NO_SLAVE; } /* Send Write data */ for (cnt=0; cnt= WAIT_TIMEOUT) { return ack; } } /* check ACK/NACK */ if ((REG(SR2.UINT32) & SR2_NACKF) != 0) { /* NACK */ i2c_set_SR2_NACKF_STOP(obj); } else { ack = 1; } } return ack; } void i2c_slave_mode(i2c_t *obj, int enable_slave) { if (enable_slave != 0) { REG(SER.UINT32) |= SER_SAR0E; // only slave addr 0 is enabled } else { REG(SER.UINT32) &= ~SER_SAR0E; // no slave addr enabled } } int i2c_slave_receive(i2c_t *obj) { int status; int retval; status = (REG(SR1.UINT8[0]) & SR1_AAS0); status |= (REG(CR2.UINT8[0]) & CR2_TRS) >> 4; switch(status) { case 0x01: /* the master is writing to this slave */ retval = 3; break; case 0x02: /* the master is writing to all slave */ retval = 2; break; case 0x03: /* the master has requested a read from this slave */ retval = 1; break; default : /* no data */ retval = 0; break; } return retval; } int i2c_slave_read(i2c_t *obj, char *data, int length) { int timeout = 0; int count; int break_flg = 0; if(length <= 0) { return 0; } for (count = 0; ((count < (length + 1)) && (break_flg == 0)); count++) { /* There is no timeout, but the upper limit value is set to avoid an infinite loop. */ while (((i2c_status(obj) & SR2_STOP) != 0) || ((i2c_status(obj) & SR2_RDRF) == 0)) { if ((i2c_status(obj) & SR2_STOP) != 0) { break_flg = 1; break; } timeout ++; if (timeout >= WAIT_TIMEOUT) { return -1; } } if (break_flg == 0) { if (count == 0) { /* dummy read */ (void)REG(DRR.UINT32); } else { data[count - 1] = (char)(REG(DRR.UINT32) & 0xFF); } } } if (break_flg == 0) { (void)i2c_wait_STOP(obj); } else { if ((i2c_status(obj) & SR2_RDRF) != 0) { if (count <= 1) { /* fail safe */ /* dummy read */ (void)REG(DRR.UINT32); } else { data[count - 2] = (char)(REG(DRR.UINT32) & 0xFF); } } } /* SR2.STOP = 0 */ REG(SR2.UINT32) &= ~SR2_STOP; return (count - 1); } int i2c_slave_write(i2c_t *obj, const char *data, int length) { int count = 0; int status = 0; if(length <= 0) { return 0; } while ((count < length) && (status == 0)) { status = i2c_do_write(obj, data[count]); if(status == 0) { /* Wait send end */ status = i2c_wait_TEND(obj); if ((status != 0) || ((count < (length - 1)) && ((REG(SR2.UINT32) & SR2_NACKF) != 0))) { /* NACK */ break; } } count++; } /* dummy read */ (void)REG(DRR.UINT32); (void)i2c_wait_STOP(obj); i2c_set_SR2_NACKF_STOP(obj); return count; } void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) { REG(SAR0.UINT32) = (address & 0xfffffffe); } #if DEVICE_I2C_ASYNCH #define IRQ_NUM 4 #define IRQ_TX 0 #define IRQ_RX 1 #define IRQ_ERR1 2 #define IRQ_ERR2 3 static void i2c_irqs_set(i2c_t *obj, uint32_t enable); static void i2c0_tx_irq(void); static void i2c1_tx_irq(void); static void i2c2_tx_irq(void); static void i2c3_tx_irq(void); static void i2c0_rx_irq(void); static void i2c1_rx_irq(void); static void i2c2_rx_irq(void); static void i2c3_rx_irq(void); static void i2c0_al_irq(void); static void i2c1_al_irq(void); static void i2c2_al_irq(void); static void i2c3_al_irq(void); static void i2c0_to_irq(void); static void i2c1_to_irq(void); static void i2c2_to_irq(void); static void i2c3_to_irq(void); static const IRQn_Type irq_set_tbl[RIIC_COUNT][IRQ_NUM] = { {INTIICTEI0_IRQn, INTIICRI0_IRQn, INTIICALI0_IRQn, INTIICTMOI0_IRQn}, {INTIICTEI1_IRQn, INTIICRI1_IRQn, INTIICALI1_IRQn, INTIICTMOI1_IRQn}, {INTIICTEI2_IRQn, INTIICRI2_IRQn, INTIICALI2_IRQn, INTIICTMOI2_IRQn}, {INTIICTEI3_IRQn, INTIICRI3_IRQn, INTIICALI3_IRQn, INTIICTMOI3_IRQn}, }; static const IRQHandler hander_set_tbl[RIIC_COUNT][IRQ_NUM] = { {i2c0_tx_irq, i2c0_rx_irq, i2c0_al_irq, i2c0_to_irq}, {i2c1_tx_irq, i2c1_rx_irq, i2c1_al_irq, i2c1_to_irq}, {i2c2_tx_irq, i2c2_rx_irq, i2c2_al_irq, i2c2_to_irq}, {i2c3_tx_irq, i2c3_rx_irq, i2c3_al_irq, i2c3_to_irq}, }; struct i2c_global_data_s { i2c_t *async_obj; uint32_t async_callback, event, shouldStop, address; }; static struct i2c_global_data_s i2c_data[RIIC_COUNT]; static void i2c_transfer_finished(i2c_t *obj) { i2c_irqs_set(obj, 0); uint32_t index = obj->i2c.i2c; i2c_data[index].event = I2C_EVENT_TRANSFER_COMPLETE; i2c_data[index].async_obj = NULL; ((void (*)())i2c_data[index].async_callback)(); } static void i2c_tx_irq(IRQn_Type irq_num, uint32_t index) { i2c_t *obj = i2c_data[index].async_obj; if ((REG(SR2.UINT32) & SR2_NACKF)) { /* Slave sends NACK */ i2c_set_err_noslave(obj); i2c_data[index].event = I2C_EVENT_ERROR | I2C_EVENT_TRANSFER_EARLY_NACK; i2c_abort_asynch(obj); ((void (*)())i2c_data[index].async_callback)(); return; } if (obj->tx_buff.pos == obj->tx_buff.length) { /* All datas have tranferred */ /* Clear TEND */ REG(SR2.UINT32) &= ~(SR2_TEND); /* If not repeated start, send stop. */ if (i2c_data[index].shouldStop && obj->rx_buff.length == 0) { (void)i2c_set_STOP(obj); (void)i2c_wait_STOP(obj); i2c_set_SR2_NACKF_STOP(obj); i2c_transfer_finished(obj); } else { (void)i2c_restart(obj); (void)i2c_wait_START(obj); /* SR2.START = 0 */ REG(SR2.UINT32) &= ~SR2_START; if (obj->rx_buff.length) { /* Ready to read */ i2c_set_MR3_ACK(obj); /* Disable INTRIICTEI */ REG(IER.UINT8[0]) &= ~(1 << 6); /* Send Slave address */ if (i2c_read_address_write(obj, (i2c_data[index].address | 0x01)) != 0) { i2c_set_err_noslave(obj); i2c_data[index].event = I2C_EVENT_ERROR | I2C_EVENT_ERROR_NO_SLAVE; i2c_abort_asynch(obj); ((void (*)())i2c_data[index].async_callback)(); return; } } else { i2c_transfer_finished(obj); } } } else { /* Send next 1 byte */ if (i2c_do_write(obj, *(uint8_t *)obj->tx_buff.buffer) != 0) { i2c_set_err_noslave(obj); i2c_data[index].event = I2C_EVENT_ERROR | I2C_EVENT_ERROR_NO_SLAVE; i2c_abort_asynch(obj); ((void (*)())i2c_data[index].async_callback)(); return; } obj->tx_buff.buffer = (uint8_t *)obj->tx_buff.buffer + 1; ++obj->tx_buff.pos; } } static void i2c_rx_irq(IRQn_Type irq_num, uint32_t index) { i2c_t *obj = i2c_data[index].async_obj; if (obj->rx_buff.pos == SIZE_MAX) { if ((REG(SR2.UINT32) & SR2_NACKF) != 0) { /* Slave sends NACK */ (void)i2c_set_STOP(obj); /* dummy read */ if (REG(DRR.UINT32)) {} (void)i2c_wait_STOP(obj); i2c_set_SR2_NACKF_STOP(obj); obj->i2c.last_stop_flag = 1; i2c_data[index].event = I2C_EVENT_ERROR | I2C_EVENT_TRANSFER_EARLY_NACK; i2c_abort_asynch(obj); ((void (*)())i2c_data[index].async_callback)(); return; } if (obj->rx_buff.length == 1) { /* length == 1 */ /* Set MR3 WAIT bit is 1 */; REG(MR3.UINT32) |= MR3_WAIT; i2c_set_MR3_NACK(obj); } else if (obj->rx_buff.length == 2) { /* Set MR3 WAIT bit is 1 */ REG(MR3.UINT32) |= MR3_WAIT; } /* dummy read */ if (REG(DRR.UINT32)) {} obj->rx_buff.pos = 0; return; } if ((REG(SR2.UINT32) & SR2_NACKF) != 0) { /* Slave sends NACK */ i2c_set_err_noslave(obj); i2c_data[index].event = I2C_EVENT_ERROR | I2C_EVENT_TRANSFER_EARLY_NACK; i2c_abort_asynch(obj); ((void (*)())i2c_data[index].async_callback)(); return; } else { switch (obj->rx_buff.length - obj->rx_buff.pos) { case 1: /* Finished */ /* If not repeated start, send stop. */ if (i2c_data[index].shouldStop) { (void)i2c_set_STOP(obj); /* RIICnDRR read */ *(uint8_t *)obj->rx_buff.buffer = REG(DRR.UINT32) & 0xFF; /* RIICnMR3.WAIT = 0 */ REG(MR3.UINT32) &= ~MR3_WAIT; (void)i2c_wait_STOP(obj); i2c_set_SR2_NACKF_STOP(obj); } else { (void)i2c_restart(obj); /* RIICnDRR read */ *(uint8_t *)obj->rx_buff.buffer = REG(DRR.UINT32) & 0xFF; /* RIICnMR3.WAIT = 0 */ REG(MR3.UINT32) &= ~MR3_WAIT; (void)i2c_wait_START(obj); /* SR2.START = 0 */ REG(SR2.UINT32) &= ~SR2_START; } i2c_transfer_finished(obj); return; case 2: i2c_set_MR3_NACK(obj); break; case 3: /* this time is befor last byte read */ /* Set MR3 WAIT bit is 1 */ REG(MR3.UINT32) |= MR3_WAIT; break; default: i2c_set_MR3_ACK(obj); break; } *(uint8_t *)obj->rx_buff.buffer = REG(DRR.UINT32) & 0xFF; obj->rx_buff.buffer = (uint8_t *)obj->rx_buff.buffer + 1; ++obj->rx_buff.pos; } } static void i2c_err_irq(IRQn_Type irq_num, uint32_t index) { i2c_t *obj = i2c_data[index].async_obj; i2c_abort_asynch(obj); i2c_data[index].event = I2C_EVENT_ERROR; ((void (*)())i2c_data[index].async_callback)(); } /* TX handler */ static void i2c0_tx_irq(void) { i2c_tx_irq(INTIICTEI0_IRQn, 0); } static void i2c1_tx_irq(void) { i2c_tx_irq(INTIICTEI1_IRQn, 1); } static void i2c2_tx_irq(void) { i2c_tx_irq(INTIICTEI2_IRQn, 2); } static void i2c3_tx_irq(void) { i2c_tx_irq(INTIICTEI3_IRQn, 3); } /* RX handler */ static void i2c0_rx_irq(void) { i2c_rx_irq(INTIICRI0_IRQn, 0); } static void i2c1_rx_irq(void) { i2c_rx_irq(INTIICRI1_IRQn, 1); } static void i2c2_rx_irq(void) { i2c_rx_irq(INTIICRI2_IRQn, 2); } static void i2c3_rx_irq(void) { i2c_rx_irq(INTIICRI3_IRQn, 3); } /* Arbitration Lost handler */ static void i2c0_al_irq(void) { i2c_err_irq(INTIICALI0_IRQn, 0); } static void i2c1_al_irq(void) { i2c_err_irq(INTIICALI1_IRQn, 1); } static void i2c2_al_irq(void) { i2c_err_irq(INTIICALI2_IRQn, 2); } static void i2c3_al_irq(void) { i2c_err_irq(INTIICALI3_IRQn, 3); } /* Timeout handler */ static void i2c0_to_irq(void) { i2c_err_irq(INTIICTMOI0_IRQn, 0); } static void i2c1_to_irq(void) { i2c_err_irq(INTIICTMOI1_IRQn, 1); } static void i2c2_to_irq(void) { i2c_err_irq(INTIICTMOI2_IRQn, 2); } static void i2c3_to_irq(void) { i2c_err_irq(INTIICTMOI3_IRQn, 3); } static void i2c_irqs_set(i2c_t *obj, uint32_t enable) { int i; const IRQn_Type *irqTable = irq_set_tbl[obj->i2c.i2c]; const IRQHandler *handlerTable = hander_set_tbl[obj->i2c.i2c]; for (i = 0; i < IRQ_NUM; ++i) { if (enable) { InterruptHandlerRegister(irqTable[i], handlerTable[i]); GIC_SetPriority(irqTable[i], 5); if (i == 1) { GIC_SetConfiguration(irqTable[i], 3); } else { GIC_SetConfiguration(irqTable[i], 1); } GIC_EnableIRQ(irqTable[i]); } else { GIC_DisableIRQ(irqTable[i]); } } REG(IER.UINT8[0]) = enable ? 0x63 : 0x00; } /****************************************************************************** * ASYNCHRONOUS HAL ******************************************************************************/ 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) { MBED_ASSERT(obj); MBED_ASSERT(tx ? tx_length : 1); MBED_ASSERT(rx ? rx_length : 1); MBED_ASSERT((REG(SER.UINT32) & SER_SAR0E) == 0); /* Slave mode */ obj->tx_buff.buffer = (void *)tx; obj->tx_buff.length = tx_length; obj->tx_buff.pos = 0; obj->tx_buff.width = 8; obj->rx_buff.buffer = rx; obj->rx_buff.length = rx_length; obj->rx_buff.pos = SIZE_MAX; obj->rx_buff.width = 8; i2c_data[obj->i2c.i2c].async_obj = obj; i2c_data[obj->i2c.i2c].async_callback = handler; i2c_data[obj->i2c.i2c].event = 0; i2c_data[obj->i2c.i2c].shouldStop = stop; i2c_data[obj->i2c.i2c].address = address; i2c_irqs_set(obj, 1); /* There is a STOP condition for last processing */ if (obj->i2c.last_stop_flag != 0) { if (i2c_start(obj) != 0) { i2c_set_err_noslave(obj); i2c_data[obj->i2c.i2c].event = I2C_EVENT_ERROR | I2C_EVENT_ERROR_NO_SLAVE; i2c_abort_asynch(obj); ((void (*)())handler)(); return; } } obj->i2c.last_stop_flag = stop; if (rx_length && tx_length == 0) { /* Ready to read */ i2c_set_MR3_ACK(obj); /* Disable INTRIICTEI */ REG(IER.UINT8[0]) &= ~(1 << 6); address |= 0x01; } /* Send Slave address */ if (i2c_do_write(obj, address) != 0) { i2c_set_err_noslave(obj); i2c_data[obj->i2c.i2c].event = I2C_EVENT_ERROR | I2C_EVENT_ERROR_NO_SLAVE; i2c_abort_asynch(obj); ((void (*)())handler)(); return; } } uint32_t i2c_irq_handler_asynch(i2c_t *obj) { return i2c_data[obj->i2c.i2c].event; } uint8_t i2c_active(i2c_t *obj) { return i2c_data[obj->i2c.i2c].async_obj != NULL; } void i2c_abort_asynch(i2c_t *obj) { i2c_data[obj->i2c.i2c].async_obj = NULL; i2c_irqs_set(obj, 0); i2c_reg_reset(obj); } #endif