Skip to content

Commit 2e2fc14

Browse files
committed
[M252KG] 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 ffdfdc2 commit 2e2fc14

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)