diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/i2c_api.c b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/i2c_api.c index 7232396925..e9bbc3f69a 100644 --- a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/i2c_api.c +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/i2c_api.c @@ -34,8 +34,9 @@ volatile struct st_riic *RIIC[] = RIIC_ADDRESS_LIST; /* RIICnCR2 */ #define CR2_ST (1 << 1) +#define CR2_RS (1 << 2) #define CR2_SP (1 << 3) -#define CR2_NACKF (1 << 4) +#define CR2_TRS (1 << 5) #define CR2_BBSY (1 << 7) /* RIICnMR3 */ @@ -43,7 +44,14 @@ volatile struct st_riic *RIIC[] = RIIC_ADDRESS_LIST; #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) @@ -67,35 +75,10 @@ static const PinMap PinMap_I2C_SCL[] = { }; -/* Clear the Transmit data Empty TDRE */ -static inline int i2c_addressed(i2c_t *obj) { - volatile int sar0 = (REG(SR1.UINT8[0])&1), - trs = (REG(CR2.UINT8[0])&0x20) >> 5; - return sar0 | (trs <<1); -} - static inline int i2c_status(i2c_t *obj) { return REG(SR2.UINT8[0]); } -static inline void i2c_clear_TDRE(i2c_t *obj) { - REG(SR2.UINT32) &= ~SR2_TDRE; -} - -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)) { - timeout ++; - if (timeout >= TIMEOUT_1S) { - return -1; - } - } - - return 0; -} - static void i2c_reg_reset(i2c_t *obj) { /* full reset */ REG(CR1.UINT8[0]) &= ~CR1_ICE; // CR1.ICE off @@ -119,7 +102,20 @@ static void i2c_reg_reset(i2c_t *obj) { REG(CR1.UINT32) &= ~CR1_RST; // CR1.IICRST negate reset } -/* Wait until the Trans Data Empty (TDRE) is set */ +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)) { + timeout ++; + if (timeout >= TIMEOUT_1S) { + return -1; + } + } + + return 0; +} + static int i2c_wait_TDRE(i2c_t *obj) { int timeout = 0; @@ -149,6 +145,20 @@ static int i2c_wait_TEND(i2c_t *obj) { } +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)) { + timeout ++; + if (timeout >= TIMEOUT_1S) { + return -1; + } + } + + return 0; +} + static int i2c_wait_STOP(i2c_t *obj) { int timeout = 0; @@ -163,26 +173,42 @@ static int i2c_wait_STOP(i2c_t *obj) { return 0; } -static void i2c_set_NACKF_STOP(i2c_t *obj) { +static void i2c_set_SR2_NACKF_STOP(i2c_t *obj) { /* SR2.NACKF = 0 */ REG(SR2.UINT32) &= ~SR2_NACKF; - /* SR2.STOP = 0 */ + /* SR2.STOP = 0 */ REG(SR2.UINT32) &= ~SR2_STOP; } -static void i2c_set_err_noslave(i2c_t *obj) { - i2c_stop(obj); - (void)i2c_wait_STOP(obj); - i2c_set_NACKF_STOP(obj); +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) { - case I2C_0: CPGSTBCR9 &= ~(0x80); break; - case I2C_1: CPGSTBCR9 &= ~(0x40); break; - case I2C_2: CPGSTBCR9 &= ~(0x20); break; - case I2C_3: CPGSTBCR9 &= ~(0x10); break; + 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; } @@ -202,6 +228,8 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) { pinmap_pinout(sda, PinMap_I2C_SDA); pinmap_pinout(scl, PinMap_I2C_SCL); + + obj->last_stop_flag = 1; } inline int i2c_start(i2c_t *obj) { @@ -210,10 +238,7 @@ inline int i2c_start(i2c_t *obj) { while (REG(CR2.UINT32) & CR2_BBSY) { timeout ++; if (timeout >= obj->bbsy_wait_cnt) { - i2c_reg_reset(obj); - /* Start Condition */ - REG(CR2.UINT8[0]) |= CR2_ST; - return 0; + break; } } /* Start Condition */ @@ -222,8 +247,17 @@ inline int i2c_start(i2c_t *obj) { return 0; } +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) { - /* SR2.STOP = 0 */ + /* SR2.STOP = 0 */ REG(SR2.UINT32) &= ~SR2_STOP; /* Stop condition */ REG(CR2.UINT32) |= CR2_SP; @@ -231,6 +265,19 @@ inline int i2c_stop(i2c_t *obj) { return 0; } +static void i2c_set_err_noslave(i2c_t *obj, int stop) { + if (stop) { + (void)i2c_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; + } +} + static inline int i2c_do_write(i2c_t *obj, int value) { int timeout = 0; @@ -259,14 +306,14 @@ static inline int i2c_do_write(i2c_t *obj, int value) { 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 0; - } else { - return status; } + + return status; } @@ -276,15 +323,9 @@ static inline int i2c_do_read(i2c_t *obj, int last) { /* Set MR3 WAIT bit is 1 */; REG(MR3.UINT32) |= MR3_WAIT; } else if (last == 1) { - /* send a NOT ACK */ - REG(MR3.UINT32) |= MR3_ACKWP; - REG(MR3.UINT32) |= MR3_ACKBT; - REG(MR3.UINT32) &= ~MR3_ACKWP; + i2c_set_MR3_NACK(obj); } else { - /* send a ACK */ - REG(MR3.UINT32) |= MR3_ACKWP; - REG(MR3.UINT32) &= ~MR3_ACKBT; - REG(MR3.UINT32) &= ~MR3_ACKWP; + i2c_set_MR3_ACK(obj); } /* return the data */ @@ -383,27 +424,45 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { int value; volatile uint32_t work_reg = 0; - status = i2c_start(obj); - if (status != 0) { - i2c_set_err_noslave(obj); - return I2C_ERROR_BUS_BUSY; + if(length <= 0) { + return 0; } + i2c_set_MR3_ACK(obj); + /* There is a STOP condition for last processing */ + if (obj->last_stop_flag != 0) { + status = i2c_start(obj); + if (status != 0) { + i2c_set_err_noslave(obj, stop); + return I2C_ERROR_BUS_BUSY; + } + } + obj->last_stop_flag = stop; /* Send Slave address */ status = i2c_read_address_write(obj, (address | 0x01)); if (status != 0) { - i2c_set_err_noslave(obj); + i2c_set_err_noslave(obj, stop); return I2C_ERROR_NO_SLAVE; } - /* wati RDRF */ + /* wait RDRF */ status = i2c_wait_RDRF(obj); /* check ACK/NACK */ - if ((status != 0) || (REG(SR2.UINT32) & CR2_NACKF == 1)) { + if ((status != 0) || (REG(SR2.UINT32) & SR2_NACKF == 1)) { /* Slave sends NACK */ - i2c_stop(obj); - /* dummy read */ - value = REG(DRR.UINT32); - (void)i2c_wait_STOP(obj); - i2c_set_NACKF_STOP(obj); + /* If not repeated start, send stop. */ + if (stop) { + i2c_stop(obj); + /* dummy read */ + value = REG(DRR.UINT32); + (void)i2c_wait_STOP(obj); + i2c_set_SR2_NACKF_STOP(obj); + } else { + (void)i2c_restart(obj); + /* dummy read */ + value = REG(DRR.UINT32); + (void)i2c_wait_START(obj); + /* SR2.START = 0 */ + REG(SR2.UINT32) &= ~SR2_START; + } return I2C_ERROR_NO_SLAVE; } /* Read in all except last byte */ @@ -414,7 +473,7 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { /* wait for it to arrive */ status = i2c_wait_RDRF(obj); if (status != 0) { - i2c_set_err_noslave(obj); + i2c_set_err_noslave(obj, stop); return I2C_ERROR_NO_SLAVE; } /* Recieve the data */ @@ -428,60 +487,55 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { data[count] = (char)value; } } else if (length == 2) { - /* Set MR3 WATI bit is 1 */; + /* Set MR3 WATI 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); + i2c_set_err_noslave(obj, stop); return I2C_ERROR_NO_SLAVE; } - /* send a NOT ACK */ - REG(MR3.UINT32) |= MR3_ACKWP; - REG(MR3.UINT32) |= MR3_ACKBT; - REG(MR3.UINT32) &= ~MR3_ACKWP; + i2c_set_MR3_NACK(obj); data[count] = (char)REG(DRR.UINT32); count++; - } else if (length == 1) { + } else { + /* length == 1 */ /* Set MR3 WATI bit is 1 */; REG(MR3.UINT32) |= MR3_WAIT; - /* send a NOT ACK */ - REG(MR3.UINT32) |= MR3_ACKWP; - REG(MR3.UINT32) |= MR3_ACKBT; - REG(MR3.UINT32) &= ~MR3_ACKWP; + i2c_set_MR3_NACK(obj); /* dummy read */ value = REG(DRR.UINT32); - } else { - return I2C_ERROR_NO_SLAVE; } /* wait for it to arrive */ status = i2c_wait_RDRF(obj); if (status != 0) { - i2c_set_err_noslave(obj); + i2c_set_err_noslave(obj, stop); return I2C_ERROR_NO_SLAVE; } + /* If not repeated start, send stop. */ if (stop) { - /* RIICnSR2.STOP = 0 */ - REG(SR2.UINT32) &= ~SR2_STOP; - /* RIICnCR2.SP = 1 */ - REG(CR2.UINT32) |= CR2_SP; + (void)i2c_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; } - i2c_set_NACKF_STOP(obj); return length; } @@ -490,37 +544,51 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { int cnt; int status; - status = i2c_start(obj); - if (status != 0) { - i2c_set_err_noslave(obj); - return I2C_ERROR_BUS_BUSY; + if(length <= 0) { + return 0; } + + /* There is a STOP condition for last processing */ + if (obj->last_stop_flag != 0) { + status = i2c_start(obj); + if (status != 0) { + i2c_set_err_noslave(obj, stop); + return I2C_ERROR_BUS_BUSY; + } + } + obj->last_stop_flag = stop; /* Send Slave address */ status = i2c_do_write(obj, address); if (status != 0) { - i2c_set_err_noslave(obj); + i2c_set_err_noslave(obj, stop); return I2C_ERROR_NO_SLAVE; } /* Send Write data */ for (cnt=0; cnt> 4; + switch(status) { - case 0x3: retval = 1; break; - case 0x2: retval = 2; break; - case 0x1: retval = 3; break; - default : retval = 1; break; + 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); + return retval; } int i2c_slave_read(i2c_t *obj, char *data, int length) { - int count = 0; - int status; + int timeout = 0; + int count; + int break_flg = 0; - volatile int dummy = REG(DRR.UINT32) ; - - do { - i2c_wait_RDRF(obj); - status = i2c_status(obj); - if(!(status & 0x10)) { - data[count] = REG(DRR.UINT32) & 0xFF; - } - count++; - } while ( !(status & 0x10) && (count < length) ); - - if(status & 0x10) { - i2c_stop(obj); - (void)i2c_wait_STOP(obj); - i2c_set_NACKF_STOP(obj); + 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) || (!(i2c_status(obj) & SR2_RDRF))) { + /* RIICnSR2.STOP = 1 or RIICnSR2.RDRF = 0 */ + if (i2c_status(obj) & SR2_STOP) { + /* RIICnSR2.STOP = 1 */ + break_flg = 1; + break; + } + timeout ++; + if (timeout >= TIMEOUT_1S) { + 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) { + 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; - //i2c_clear_TDRE(obj); - - return count; + return (count - 1); } int i2c_slave_write(i2c_t *obj, const char *data, int length) { int count = 0; - int status; + int status = 0; if(length <= 0) { - return(0); + return 0; } - do { + while ((count < length) && (status == 0)) { status = i2c_do_write(obj, data[count]); count++; - } while ((count < length) && !(status & 0x10)); - - if (!(status & 0x10)) { - i2c_stop(obj); - (void)i2c_wait_STOP(obj); - i2c_set_NACKF_STOP(obj); } + if (status == 0) { + /* Wait send end */ + status = i2c_wait_TEND(obj); + if (status != 0) { + i2c_set_err_noslave(obj, 1); + return 0; + } + } + /* dummy read */ + (void)REG(DRR.UINT32); + (void)i2c_wait_STOP(obj); + i2c_set_SR2_NACKF_STOP(obj); - i2c_clear_TDRE(obj); - - return(count); + return count; } void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) { - REG(SAR0.UINT32) = address & 0xfe; + REG(SAR0.UINT32) = address & 0xfffffffe; } diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/objects.h b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/objects.h index bb7d45b50d..c1f7c142e6 100644 --- a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/objects.h +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/objects.h @@ -35,6 +35,7 @@ struct i2c_s { uint8_t width_low; uint8_t width_hi; int bbsy_wait_cnt; + int last_stop_flag; }; struct spi_s {