mirror of https://github.com/ARMmbed/mbed-os.git
[NUC472/M453] Correct return of i2c_byte_write() on NAK
parent
57a22cd4ab
commit
d24c71fad9
|
@ -48,7 +48,7 @@ static void i2c0_vec(void);
|
|||
static void i2c1_vec(void);
|
||||
static void i2c_irq(i2c_t *obj);
|
||||
static void i2c_fsm_reset(i2c_t *obj, uint32_t i2c_ctl);
|
||||
static void i2c_fsm_tranfini(i2c_t *obj, int tran_pos_adv);
|
||||
static void i2c_fsm_tranfini(i2c_t *obj, int lastdatanaked);
|
||||
|
||||
static struct nu_i2c_var i2c0_var = {
|
||||
.obj = NULL,
|
||||
|
@ -69,8 +69,6 @@ static const struct nu_modinit_s i2c_modinit_tab[] = {
|
|||
};
|
||||
|
||||
static int i2c_do_tran(i2c_t *obj, char *buf, int length, int read, int naklastdata);
|
||||
static int i2c_do_write(i2c_t *obj, char data, int naklastdata);
|
||||
static int i2c_do_read(i2c_t *obj, char *data, int naklastdata);
|
||||
static int i2c_do_trsn(i2c_t *obj, uint32_t i2c_ctl, int sync);
|
||||
#define NU_I2C_TIMEOUT_STAT_INT 500000
|
||||
#define NU_I2C_TIMEOUT_STOP 500000
|
||||
|
@ -98,6 +96,7 @@ static void i2c_rollback_vector_interrupt(i2c_t *obj);
|
|||
|
||||
#define TRANCTRL_STARTED (1)
|
||||
#define TRANCTRL_NAKLASTDATA (1 << 1)
|
||||
#define TRANCTRL_LASTDATANAKED (1 << 2)
|
||||
|
||||
uint32_t us_ticker_read(void);
|
||||
|
||||
|
@ -169,7 +168,7 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
|
|||
return I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
|
||||
if (i2c_do_write(obj, i2c_addr2data(address, 1), 0)) {
|
||||
if (i2c_byte_write(obj, i2c_addr2data(address, 1)) != 1) {
|
||||
i2c_stop(obj);
|
||||
return I2C_ERROR_NO_SLAVE;
|
||||
}
|
||||
|
@ -192,7 +191,7 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
|
|||
return I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
|
||||
if (i2c_do_write(obj, i2c_addr2data(address, 0), 0)) {
|
||||
if (i2c_byte_write(obj, i2c_addr2data(address, 0)) != 1) {
|
||||
i2c_stop(obj);
|
||||
return I2C_ERROR_NO_SLAVE;
|
||||
}
|
||||
|
@ -215,14 +214,22 @@ void i2c_reset(i2c_t *obj)
|
|||
int i2c_byte_read(i2c_t *obj, int last)
|
||||
{
|
||||
char data = 0;
|
||||
|
||||
i2c_do_read(obj, &data, last);
|
||||
i2c_do_tran(obj, &data, 1, 1, last);
|
||||
return data;
|
||||
}
|
||||
|
||||
int i2c_byte_write(i2c_t *obj, int data)
|
||||
{
|
||||
return i2c_do_write(obj, (data & 0xFF), 0) == 0 ? 1 : 0;
|
||||
char data_[1];
|
||||
data_[0] = data & 0xFF;
|
||||
|
||||
if (i2c_do_tran(obj, data_, 1, 0, 0) == 1 &&
|
||||
! (obj->i2c.tran_ctrl & TRANCTRL_LASTDATANAKED)) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEVICE_I2CSLAVE
|
||||
|
@ -374,7 +381,6 @@ static int i2c_do_tran(i2c_t *obj, char *buf, int length, int read, int naklastd
|
|||
}
|
||||
else {
|
||||
i2c_disable_int(obj);
|
||||
obj->i2c.tran_ctrl = 0;
|
||||
tran_len = obj->i2c.tran_pos - obj->i2c.tran_beg;
|
||||
obj->i2c.tran_beg = NULL;
|
||||
obj->i2c.tran_pos = NULL;
|
||||
|
@ -385,18 +391,6 @@ static int i2c_do_tran(i2c_t *obj, char *buf, int length, int read, int naklastd
|
|||
return tran_len;
|
||||
}
|
||||
|
||||
static int i2c_do_write(i2c_t *obj, char data, int naklastdata)
|
||||
{
|
||||
char data_[1];
|
||||
data_[0] = data;
|
||||
return i2c_do_tran(obj, data_, 1, 0, naklastdata) == 1 ? 0 : I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
|
||||
static int i2c_do_read(i2c_t *obj, char *data, int naklastdata)
|
||||
{
|
||||
return i2c_do_tran(obj, data, 1, 1, naklastdata) == 1 ? 0 : I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
|
||||
static int i2c_do_trsn(i2c_t *obj, uint32_t i2c_ctl, int sync)
|
||||
{
|
||||
I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c);
|
||||
|
@ -625,11 +619,11 @@ static void i2c_irq(i2c_t *obj)
|
|||
break;
|
||||
|
||||
case 0x30: // Master Transmit Data NACK
|
||||
i2c_fsm_tranfini(obj, 0);
|
||||
i2c_fsm_tranfini(obj, 1);
|
||||
break;
|
||||
|
||||
case 0x20: // Master Transmit Address NACK
|
||||
i2c_fsm_tranfini(obj, -1); // Roll back data position to indicate slave address not ACKed
|
||||
i2c_fsm_tranfini(obj, 1);
|
||||
break;
|
||||
|
||||
case 0x38: // Master Arbitration Lost
|
||||
|
@ -637,7 +631,7 @@ static void i2c_irq(i2c_t *obj)
|
|||
break;
|
||||
|
||||
case 0x48: // Master Receive Address NACK
|
||||
i2c_fsm_tranfini(obj, -1); // Roll back data position to indicate slave address not ACKed
|
||||
i2c_fsm_tranfini(obj, 1);
|
||||
break;
|
||||
|
||||
case 0x40: // Master Receive Address ACK
|
||||
|
@ -656,7 +650,7 @@ static void i2c_irq(i2c_t *obj)
|
|||
while (1);
|
||||
}
|
||||
#endif
|
||||
i2c_fsm_tranfini(obj, 0);
|
||||
i2c_fsm_tranfini(obj, 1);
|
||||
}
|
||||
else {
|
||||
uint32_t i2c_ctl = I2C_CTL_SI_Msk | I2C_CTL_AA_Msk;
|
||||
|
@ -823,10 +817,10 @@ static void i2c_fsm_reset(i2c_t *obj, uint32_t i2c_ctl)
|
|||
obj->i2c.slaveaddr_state = NoData;
|
||||
}
|
||||
|
||||
static void i2c_fsm_tranfini(i2c_t *obj, int tran_pos_adv)
|
||||
static void i2c_fsm_tranfini(i2c_t *obj, int lastdatanaked)
|
||||
{
|
||||
if (obj->i2c.tran_pos) {
|
||||
obj->i2c.tran_pos += tran_pos_adv;
|
||||
if (lastdatanaked) {
|
||||
obj->i2c.tran_ctrl |= TRANCTRL_LASTDATANAKED;
|
||||
}
|
||||
|
||||
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
|
||||
|
|
|
@ -51,7 +51,7 @@ static void i2c3_vec(void);
|
|||
static void i2c4_vec(void);
|
||||
static void i2c_irq(i2c_t *obj);
|
||||
static void i2c_fsm_reset(i2c_t *obj, uint32_t i2c_ctl);
|
||||
static void i2c_fsm_tranfini(i2c_t *obj, int tran_pos_adv);
|
||||
static void i2c_fsm_tranfini(i2c_t *obj, int lastdatanaked);
|
||||
|
||||
static struct nu_i2c_var i2c0_var = {
|
||||
.obj = NULL,
|
||||
|
@ -87,8 +87,6 @@ static const struct nu_modinit_s i2c_modinit_tab[] = {
|
|||
};
|
||||
|
||||
static int i2c_do_tran(i2c_t *obj, char *buf, int length, int read, int naklastdata);
|
||||
static int i2c_do_write(i2c_t *obj, char data, int naklastdata);
|
||||
static int i2c_do_read(i2c_t *obj, char *data, int naklastdata);
|
||||
static int i2c_do_trsn(i2c_t *obj, uint32_t i2c_ctl, int sync);
|
||||
#define NU_I2C_TIMEOUT_STAT_INT 500000
|
||||
#define NU_I2C_TIMEOUT_STOP 500000
|
||||
|
@ -115,6 +113,7 @@ static void i2c_rollback_vector_interrupt(i2c_t *obj);
|
|||
|
||||
#define TRANCTRL_STARTED (1)
|
||||
#define TRANCTRL_NAKLASTDATA (1 << 1)
|
||||
#define TRANCTRL_LASTDATANAKED (1 << 2)
|
||||
|
||||
uint32_t us_ticker_read(void);
|
||||
|
||||
|
@ -186,7 +185,7 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
|
|||
return I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
|
||||
if (i2c_do_write(obj, i2c_addr2data(address, 1), 0)) {
|
||||
if (i2c_byte_write(obj, i2c_addr2data(address, 1)) != 1) {
|
||||
i2c_stop(obj);
|
||||
return I2C_ERROR_NO_SLAVE;
|
||||
}
|
||||
|
@ -209,7 +208,7 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
|
|||
return I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
|
||||
if (i2c_do_write(obj, i2c_addr2data(address, 0), 0)) {
|
||||
if (i2c_byte_write(obj, i2c_addr2data(address, 0)) != 1) {
|
||||
i2c_stop(obj);
|
||||
return I2C_ERROR_NO_SLAVE;
|
||||
}
|
||||
|
@ -232,14 +231,22 @@ void i2c_reset(i2c_t *obj)
|
|||
int i2c_byte_read(i2c_t *obj, int last)
|
||||
{
|
||||
char data = 0;
|
||||
|
||||
i2c_do_read(obj, &data, last);
|
||||
i2c_do_tran(obj, &data, 1, 1, last);
|
||||
return data;
|
||||
}
|
||||
|
||||
int i2c_byte_write(i2c_t *obj, int data)
|
||||
{
|
||||
return i2c_do_write(obj, (data & 0xFF), 0) == 0 ? 1 : 0;
|
||||
char data_[1];
|
||||
data_[0] = data & 0xFF;
|
||||
|
||||
if (i2c_do_tran(obj, data_, 1, 0, 0) == 1 &&
|
||||
! (obj->i2c.tran_ctrl & TRANCTRL_LASTDATANAKED)) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEVICE_I2CSLAVE
|
||||
|
@ -391,7 +398,6 @@ static int i2c_do_tran(i2c_t *obj, char *buf, int length, int read, int naklastd
|
|||
}
|
||||
else {
|
||||
i2c_disable_int(obj);
|
||||
obj->i2c.tran_ctrl = 0;
|
||||
tran_len = obj->i2c.tran_pos - obj->i2c.tran_beg;
|
||||
obj->i2c.tran_beg = NULL;
|
||||
obj->i2c.tran_pos = NULL;
|
||||
|
@ -402,18 +408,6 @@ static int i2c_do_tran(i2c_t *obj, char *buf, int length, int read, int naklastd
|
|||
return tran_len;
|
||||
}
|
||||
|
||||
static int i2c_do_write(i2c_t *obj, char data, int naklastdata)
|
||||
{
|
||||
char data_[1];
|
||||
data_[0] = data;
|
||||
return i2c_do_tran(obj, data_, 1, 0, naklastdata) == 1 ? 0 : I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
|
||||
static int i2c_do_read(i2c_t *obj, char *data, int naklastdata)
|
||||
{
|
||||
return i2c_do_tran(obj, data, 1, 1, naklastdata) == 1 ? 0 : I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
|
||||
static int i2c_do_trsn(i2c_t *obj, uint32_t i2c_ctl, int sync)
|
||||
{
|
||||
I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c);
|
||||
|
@ -655,11 +649,11 @@ static void i2c_irq(i2c_t *obj)
|
|||
break;
|
||||
|
||||
case 0x30: // Master Transmit Data NACK
|
||||
i2c_fsm_tranfini(obj, 0);
|
||||
i2c_fsm_tranfini(obj, 1);
|
||||
break;
|
||||
|
||||
case 0x20: // Master Transmit Address NACK
|
||||
i2c_fsm_tranfini(obj, -1); // Roll back data position to indicate slave address not ACKed
|
||||
i2c_fsm_tranfini(obj, 1);
|
||||
break;
|
||||
|
||||
case 0x38: // Master Arbitration Lost
|
||||
|
@ -667,7 +661,7 @@ static void i2c_irq(i2c_t *obj)
|
|||
break;
|
||||
|
||||
case 0x48: // Master Receive Address NACK
|
||||
i2c_fsm_tranfini(obj, -1); // Roll back data position to indicate slave address not ACKed
|
||||
i2c_fsm_tranfini(obj, 1);
|
||||
break;
|
||||
|
||||
case 0x40: // Master Receive Address ACK
|
||||
|
@ -686,7 +680,7 @@ static void i2c_irq(i2c_t *obj)
|
|||
while (1);
|
||||
}
|
||||
#endif
|
||||
i2c_fsm_tranfini(obj, 0);
|
||||
i2c_fsm_tranfini(obj, 1);
|
||||
}
|
||||
else {
|
||||
uint32_t i2c_ctl = I2C_CTL_SI_Msk | I2C_CTL_AA_Msk;
|
||||
|
@ -853,10 +847,10 @@ static void i2c_fsm_reset(i2c_t *obj, uint32_t i2c_ctl)
|
|||
obj->i2c.slaveaddr_state = NoData;
|
||||
}
|
||||
|
||||
static void i2c_fsm_tranfini(i2c_t *obj, int tran_pos_adv)
|
||||
static void i2c_fsm_tranfini(i2c_t *obj, int lastdatanaked)
|
||||
{
|
||||
if (obj->i2c.tran_pos) {
|
||||
obj->i2c.tran_pos += tran_pos_adv;
|
||||
if (lastdatanaked) {
|
||||
obj->i2c.tran_ctrl |= TRANCTRL_LASTDATANAKED;
|
||||
}
|
||||
|
||||
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
|
||||
|
|
Loading…
Reference in New Issue