[NUC472/M453] Correct return of i2c_byte_write() on NAK

pull/3309/head
ccli8 2016-11-22 13:45:01 +08:00
parent 57a22cd4ab
commit d24c71fad9
2 changed files with 44 additions and 56 deletions

View File

@ -48,7 +48,7 @@ static void i2c0_vec(void);
static void i2c1_vec(void); static void i2c1_vec(void);
static void i2c_irq(i2c_t *obj); static void i2c_irq(i2c_t *obj);
static void i2c_fsm_reset(i2c_t *obj, uint32_t i2c_ctl); 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 = { static struct nu_i2c_var i2c0_var = {
.obj = NULL, .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_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); 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_STAT_INT 500000
#define NU_I2C_TIMEOUT_STOP 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_STARTED (1)
#define TRANCTRL_NAKLASTDATA (1 << 1) #define TRANCTRL_NAKLASTDATA (1 << 1)
#define TRANCTRL_LASTDATANAKED (1 << 2)
uint32_t us_ticker_read(void); 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; 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); i2c_stop(obj);
return I2C_ERROR_NO_SLAVE; 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; 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); i2c_stop(obj);
return I2C_ERROR_NO_SLAVE; return I2C_ERROR_NO_SLAVE;
} }
@ -215,14 +214,22 @@ void i2c_reset(i2c_t *obj)
int i2c_byte_read(i2c_t *obj, int last) int i2c_byte_read(i2c_t *obj, int last)
{ {
char data = 0; char data = 0;
i2c_do_tran(obj, &data, 1, 1, last);
i2c_do_read(obj, &data, last);
return data; return data;
} }
int i2c_byte_write(i2c_t *obj, int 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 #if DEVICE_I2CSLAVE
@ -374,7 +381,6 @@ static int i2c_do_tran(i2c_t *obj, char *buf, int length, int read, int naklastd
} }
else { else {
i2c_disable_int(obj); i2c_disable_int(obj);
obj->i2c.tran_ctrl = 0;
tran_len = obj->i2c.tran_pos - obj->i2c.tran_beg; tran_len = obj->i2c.tran_pos - obj->i2c.tran_beg;
obj->i2c.tran_beg = NULL; obj->i2c.tran_beg = NULL;
obj->i2c.tran_pos = 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; 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) 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); I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c);
@ -625,11 +619,11 @@ static void i2c_irq(i2c_t *obj)
break; break;
case 0x30: // Master Transmit Data NACK case 0x30: // Master Transmit Data NACK
i2c_fsm_tranfini(obj, 0); i2c_fsm_tranfini(obj, 1);
break; break;
case 0x20: // Master Transmit Address NACK 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; break;
case 0x38: // Master Arbitration Lost case 0x38: // Master Arbitration Lost
@ -637,7 +631,7 @@ static void i2c_irq(i2c_t *obj)
break; break;
case 0x48: // Master Receive Address NACK 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; break;
case 0x40: // Master Receive Address ACK case 0x40: // Master Receive Address ACK
@ -656,7 +650,7 @@ static void i2c_irq(i2c_t *obj)
while (1); while (1);
} }
#endif #endif
i2c_fsm_tranfini(obj, 0); i2c_fsm_tranfini(obj, 1);
} }
else { else {
uint32_t i2c_ctl = I2C_CTL_SI_Msk | I2C_CTL_AA_Msk; 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; 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) { if (lastdatanaked) {
obj->i2c.tran_pos += tran_pos_adv; obj->i2c.tran_ctrl |= TRANCTRL_LASTDATANAKED;
} }
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;

View File

@ -51,7 +51,7 @@ static void i2c3_vec(void);
static void i2c4_vec(void); static void i2c4_vec(void);
static void i2c_irq(i2c_t *obj); static void i2c_irq(i2c_t *obj);
static void i2c_fsm_reset(i2c_t *obj, uint32_t i2c_ctl); 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 = { static struct nu_i2c_var i2c0_var = {
.obj = NULL, .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_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); 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_STAT_INT 500000
#define NU_I2C_TIMEOUT_STOP 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_STARTED (1)
#define TRANCTRL_NAKLASTDATA (1 << 1) #define TRANCTRL_NAKLASTDATA (1 << 1)
#define TRANCTRL_LASTDATANAKED (1 << 2)
uint32_t us_ticker_read(void); 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; 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); i2c_stop(obj);
return I2C_ERROR_NO_SLAVE; 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; 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); i2c_stop(obj);
return I2C_ERROR_NO_SLAVE; return I2C_ERROR_NO_SLAVE;
} }
@ -232,14 +231,22 @@ void i2c_reset(i2c_t *obj)
int i2c_byte_read(i2c_t *obj, int last) int i2c_byte_read(i2c_t *obj, int last)
{ {
char data = 0; char data = 0;
i2c_do_tran(obj, &data, 1, 1, last);
i2c_do_read(obj, &data, last);
return data; return data;
} }
int i2c_byte_write(i2c_t *obj, int 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 #if DEVICE_I2CSLAVE
@ -391,7 +398,6 @@ static int i2c_do_tran(i2c_t *obj, char *buf, int length, int read, int naklastd
} }
else { else {
i2c_disable_int(obj); i2c_disable_int(obj);
obj->i2c.tran_ctrl = 0;
tran_len = obj->i2c.tran_pos - obj->i2c.tran_beg; tran_len = obj->i2c.tran_pos - obj->i2c.tran_beg;
obj->i2c.tran_beg = NULL; obj->i2c.tran_beg = NULL;
obj->i2c.tran_pos = 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; 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) 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); I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c);
@ -655,11 +649,11 @@ static void i2c_irq(i2c_t *obj)
break; break;
case 0x30: // Master Transmit Data NACK case 0x30: // Master Transmit Data NACK
i2c_fsm_tranfini(obj, 0); i2c_fsm_tranfini(obj, 1);
break; break;
case 0x20: // Master Transmit Address NACK 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; break;
case 0x38: // Master Arbitration Lost case 0x38: // Master Arbitration Lost
@ -667,7 +661,7 @@ static void i2c_irq(i2c_t *obj)
break; break;
case 0x48: // Master Receive Address NACK 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; break;
case 0x40: // Master Receive Address ACK case 0x40: // Master Receive Address ACK
@ -686,7 +680,7 @@ static void i2c_irq(i2c_t *obj)
while (1); while (1);
} }
#endif #endif
i2c_fsm_tranfini(obj, 0); i2c_fsm_tranfini(obj, 1);
} }
else { else {
uint32_t i2c_ctl = I2C_CTL_SI_Msk | I2C_CTL_AA_Msk; 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; 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) { if (lastdatanaked) {
obj->i2c.tran_pos += tran_pos_adv; obj->i2c.tran_ctrl |= TRANCTRL_LASTDATANAKED;
} }
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;