mirror of https://github.com/ARMmbed/mbed-os.git
Add some processing of I2C driver
Changes are as below - Add STOP condition omission processing of I2C Master - Add I2C Slave processingpull/875/head
parent
44b4fb4b41
commit
88604ff8fe
|
@ -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 */
|
||||
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,14 +238,20 @@ inline int i2c_start(i2c_t *obj) {
|
|||
while (REG(CR2.UINT32) & CR2_BBSY) {
|
||||
timeout ++;
|
||||
if (timeout >= obj->bbsy_wait_cnt) {
|
||||
i2c_reg_reset(obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Start Condition */
|
||||
REG(CR2.UINT8[0]) |= CR2_ST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Start Condition */
|
||||
REG(CR2.UINT8[0]) |= CR2_ST;
|
||||
}
|
||||
|
||||
inline int i2c_restart(i2c_t *obj) {
|
||||
/* SR2.START = 0 */
|
||||
REG(SR2.UINT32) &= ~SR2_START;
|
||||
/* ReStart condition */
|
||||
REG(CR2.UINT32) |= CR2_RS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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,15 +306,15 @@ 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;
|
||||
|
||||
}
|
||||
|
||||
static inline int i2c_do_read(i2c_t *obj, int last) {
|
||||
|
@ -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;
|
||||
|
||||
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);
|
||||
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 */
|
||||
/* If not repeated start, send stop. */
|
||||
if (stop) {
|
||||
i2c_stop(obj);
|
||||
/* dummy read */
|
||||
value = REG(DRR.UINT32);
|
||||
(void)i2c_wait_STOP(obj);
|
||||
i2c_set_NACKF_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;
|
||||
|
||||
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);
|
||||
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<length; cnt++) {
|
||||
status = i2c_do_write(obj, data[cnt]);
|
||||
if(status != 0) {
|
||||
i2c_set_err_noslave(obj);
|
||||
i2c_set_err_noslave(obj, stop);
|
||||
return cnt;
|
||||
}
|
||||
}
|
||||
/* Wait send end */
|
||||
status = i2c_wait_TEND(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) {
|
||||
i2c_stop(obj);
|
||||
(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;
|
||||
|
||||
}
|
||||
i2c_set_NACKF_STOP(obj);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
@ -528,30 +596,29 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
|
|||
void i2c_reset(i2c_t *obj) {
|
||||
i2c_stop(obj);
|
||||
(void)i2c_wait_STOP(obj);
|
||||
i2c_set_NACKF_STOP(obj);
|
||||
i2c_set_SR2_NACKF_STOP(obj);
|
||||
}
|
||||
|
||||
int i2c_byte_read(i2c_t *obj, int last) {
|
||||
int status;
|
||||
|
||||
/* dummy read */
|
||||
(void)REG(DRR.UINT32);
|
||||
/* wait for it to arrive */
|
||||
status = i2c_wait_RDRF(obj);
|
||||
if (status != 0) {
|
||||
i2c_stop(obj);
|
||||
(void)i2c_wait_STOP(obj);
|
||||
i2c_set_NACKF_STOP(obj);
|
||||
i2c_set_err_noslave(obj, 1);
|
||||
return I2C_ERROR_NO_SLAVE;
|
||||
}
|
||||
|
||||
return (i2c_do_read(obj, last) & 0xFF);
|
||||
return (i2c_do_read(obj, last));
|
||||
}
|
||||
|
||||
int i2c_byte_write(i2c_t *obj, int data) {
|
||||
int ack;
|
||||
int status = i2c_do_write(obj, (data & 0xFF));
|
||||
int status;
|
||||
|
||||
status = i2c_do_write(obj, (data & 0xFF));
|
||||
if (status != 0) {
|
||||
i2c_set_err_noslave(obj, 1);
|
||||
ack = 0;
|
||||
} else {
|
||||
ack = 1;
|
||||
|
@ -562,9 +629,9 @@ int i2c_byte_write(i2c_t *obj, int data) {
|
|||
|
||||
void i2c_slave_mode(i2c_t *obj, int enable_slave) {
|
||||
if (enable_slave != 0) {
|
||||
REG(SER.UINT32) = 0x01; // only slave addr 1 is enabled
|
||||
REG(SER.UINT32) |= SER_SAR0E; // only slave addr 0 is enabled
|
||||
} else {
|
||||
REG(SER.UINT32) = 0x00; // no slave addr enabled
|
||||
REG(SER.UINT32) &= ~SER_SAR0E; // no slave addr enabled
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,67 +639,109 @@ int i2c_slave_receive(i2c_t *obj) {
|
|||
int status;
|
||||
int retval;
|
||||
|
||||
status = i2c_addressed(obj);
|
||||
status = REG(SR1.UINT8[0]) & SR1_AAS0;
|
||||
status |= (REG(CR2.UINT8[0]) & CR2_TRS) >> 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;
|
||||
if(length <= 0) {
|
||||
return 0;
|
||||
}
|
||||
count++;
|
||||
} while ( !(status & 0x10) && (count < length) );
|
||||
|
||||
if(status & 0x10) {
|
||||
i2c_stop(obj);
|
||||
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);
|
||||
i2c_set_NACKF_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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue