Skip to content

Commit 7f29545

Browse files
ccli8adbridge
authored andcommitted
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 a5b7048 commit 7f29545

File tree

1 file changed

+28
-6
lines changed

1 file changed

+28
-6
lines changed

targets/TARGET_NUVOTON/TARGET_M251/i2c_api.c

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

84-
#define TRANCTRL_STARTED (1)
85-
#define TRANCTRL_NAKLASTDATA (1 << 1)
86-
#define TRANCTRL_LASTDATANAKED (1 << 2)
84+
#define TRANCTRL_STARTED (1) // Guard I2C ISR from data transfer prematurely
85+
#define TRANCTRL_NAKLASTDATA (1 << 1) // Request NACK on last data
86+
#define TRANCTRL_LASTDATANAKED (1 << 2) // Last data NACKed
87+
#define TRANCTRL_RECVDATA (1 << 3) // Receive data available
8788

8889
uint32_t us_ticker_read(void);
8990

@@ -583,11 +584,17 @@ static void i2c_irq(i2c_t *obj)
583584
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
584585
if (obj->i2c.tran_pos < obj->i2c.tran_end) {
585586
if (status == 0x50 || status == 0x58) {
586-
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
587+
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
588+
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
589+
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
590+
}
587591
}
588592

589593
if (status == 0x58) {
590594
i2c_fsm_tranfini(obj, 1);
595+
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
596+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
597+
i2c_disable_int(obj);
591598
} else {
592599
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
593600
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -596,6 +603,7 @@ static void i2c_irq(i2c_t *obj)
596603
i2c_ctl &= ~I2C_CTL0_AA_Msk;
597604
}
598605
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
606+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
599607
}
600608
} else {
601609
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
@@ -650,12 +658,18 @@ static void i2c_irq(i2c_t *obj)
650658
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
651659
if (obj->i2c.tran_pos < obj->i2c.tran_end) {
652660
if (status == 0x80 || status == 0x88) {
653-
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
661+
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
662+
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
663+
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
664+
}
654665
}
655666

656667
if (status == 0x88) {
657668
obj->i2c.slaveaddr_state = NoData;
658669
i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
670+
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
671+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
672+
i2c_disable_int(obj);
659673
} else {
660674
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
661675
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -664,6 +678,7 @@ static void i2c_irq(i2c_t *obj)
664678
i2c_ctl &= ~I2C_CTL0_AA_Msk;
665679
}
666680
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
681+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
667682
}
668683
} else {
669684
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
@@ -686,12 +701,18 @@ static void i2c_irq(i2c_t *obj)
686701
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
687702
if (obj->i2c.tran_pos < obj->i2c.tran_end) {
688703
if (status == 0x90 || status == 0x98) {
689-
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
704+
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
705+
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
706+
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
707+
}
690708
}
691709

692710
if (status == 0x98) {
693711
obj->i2c.slaveaddr_state = NoData;
694712
i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
713+
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
714+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
715+
i2c_disable_int(obj);
695716
} else {
696717
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
697718
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -700,6 +721,7 @@ static void i2c_irq(i2c_t *obj)
700721
i2c_ctl &= ~I2C_CTL0_AA_Msk;
701722
}
702723
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
724+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
703725
}
704726
} else {
705727
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;

0 commit comments

Comments
 (0)