Skip to content

Commit d15abe5

Browse files
committed
M263: Fix I2C NACK error
Fix logic error on replying NACK at the end of transfer. This is also to fix FPGA CI test mbed_hal_fpga_ci_test_shield-i2c/ i2c - test single byte read i2c API.
1 parent 9d4d99c commit d15abe5

File tree

1 file changed

+28
-6
lines changed

1 file changed

+28
-6
lines changed

targets/TARGET_NUVOTON/TARGET_M261/i2c_api.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@ static void i2c_enable_vector_interrupt(i2c_t *obj, uint32_t handler, int enable
8686
static void i2c_rollback_vector_interrupt(i2c_t *obj);
8787
#endif
8888

89-
#define TRANCTRL_STARTED (1)
90-
#define TRANCTRL_NAKLASTDATA (1 << 1)
91-
#define TRANCTRL_LASTDATANAKED (1 << 2)
89+
#define TRANCTRL_STARTED (1) // Guard I2C ISR from data transfer prematurely
90+
#define TRANCTRL_NAKLASTDATA (1 << 1) // Request NACK on last data
91+
#define TRANCTRL_LASTDATANAKED (1 << 2) // Last data NACKed
92+
#define TRANCTRL_RECVDATA (1 << 3) // Receive data available
9293

9394
uint32_t us_ticker_read(void);
9495

@@ -592,11 +593,17 @@ static void i2c_irq(i2c_t *obj)
592593
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
593594
if (obj->i2c.tran_pos < obj->i2c.tran_end) {
594595
if (status == 0x50 || status == 0x58) {
595-
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
596+
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
597+
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
598+
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
599+
}
596600
}
597601

598602
if (status == 0x58) {
599603
i2c_fsm_tranfini(obj, 1);
604+
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
605+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
606+
i2c_disable_int(obj);
600607
} else {
601608
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
602609
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -605,6 +612,7 @@ static void i2c_irq(i2c_t *obj)
605612
i2c_ctl &= ~I2C_CTL0_AA_Msk;
606613
}
607614
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
615+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
608616
}
609617
} else {
610618
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
@@ -659,12 +667,18 @@ static void i2c_irq(i2c_t *obj)
659667
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
660668
if (obj->i2c.tran_pos < obj->i2c.tran_end) {
661669
if (status == 0x80 || status == 0x88) {
662-
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
670+
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
671+
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
672+
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
673+
}
663674
}
664675

665676
if (status == 0x88) {
666677
obj->i2c.slaveaddr_state = NoData;
667678
i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
679+
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
680+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
681+
i2c_disable_int(obj);
668682
} else {
669683
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
670684
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -673,6 +687,7 @@ static void i2c_irq(i2c_t *obj)
673687
i2c_ctl &= ~I2C_CTL0_AA_Msk;
674688
}
675689
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
690+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
676691
}
677692
} else {
678693
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
@@ -695,12 +710,18 @@ static void i2c_irq(i2c_t *obj)
695710
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
696711
if (obj->i2c.tran_pos < obj->i2c.tran_end) {
697712
if (status == 0x90 || status == 0x98) {
698-
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
713+
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
714+
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
715+
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
716+
}
699717
}
700718

701719
if (status == 0x98) {
702720
obj->i2c.slaveaddr_state = NoData;
703721
i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
722+
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
723+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
724+
i2c_disable_int(obj);
704725
} else {
705726
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
706727
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -709,6 +730,7 @@ static void i2c_irq(i2c_t *obj)
709730
i2c_ctl &= ~I2C_CTL0_AA_Msk;
710731
}
711732
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
733+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
712734
}
713735
} else {
714736
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;

0 commit comments

Comments
 (0)