Skip to content

Commit 88ad7d8

Browse files
committed
[Nuvoton] 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 bc0b39e commit 88ad7d8

File tree

5 files changed

+149
-30
lines changed

5 files changed

+149
-30
lines changed

targets/TARGET_NUVOTON/TARGET_M2351/i2c_api.c

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

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

9293
uint32_t us_ticker_read(void);
9394

@@ -597,11 +598,17 @@ static void i2c_irq(i2c_t *obj)
597598
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
598599
if (obj->i2c.tran_pos < obj->i2c.tran_end) {
599600
if (status == 0x50 || status == 0x58) {
600-
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
601+
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
602+
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
603+
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
604+
}
601605
}
602606

603607
if (status == 0x58) {
604608
i2c_fsm_tranfini(obj, 1);
609+
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
610+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
611+
i2c_disable_int(obj);
605612
} else {
606613
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
607614
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -610,6 +617,7 @@ static void i2c_irq(i2c_t *obj)
610617
i2c_ctl &= ~I2C_CTL0_AA_Msk;
611618
}
612619
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
620+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
613621
}
614622
} else {
615623
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
@@ -664,12 +672,18 @@ static void i2c_irq(i2c_t *obj)
664672
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
665673
if (obj->i2c.tran_pos < obj->i2c.tran_end) {
666674
if (status == 0x80 || status == 0x88) {
667-
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
675+
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
676+
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
677+
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
678+
}
668679
}
669680

670681
if (status == 0x88) {
671682
obj->i2c.slaveaddr_state = NoData;
672683
i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
684+
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
685+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
686+
i2c_disable_int(obj);
673687
} else {
674688
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
675689
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -678,6 +692,7 @@ static void i2c_irq(i2c_t *obj)
678692
i2c_ctl &= ~I2C_CTL0_AA_Msk;
679693
}
680694
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
695+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
681696
}
682697
} else {
683698
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
@@ -700,12 +715,18 @@ static void i2c_irq(i2c_t *obj)
700715
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
701716
if (obj->i2c.tran_pos < obj->i2c.tran_end) {
702717
if (status == 0x90 || status == 0x98) {
703-
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
718+
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
719+
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
720+
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
721+
}
704722
}
705723

706724
if (status == 0x98) {
707725
obj->i2c.slaveaddr_state = NoData;
708726
i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
727+
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
728+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
729+
i2c_disable_int(obj);
709730
} else {
710731
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
711732
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -714,6 +735,7 @@ static void i2c_irq(i2c_t *obj)
714735
i2c_ctl &= ~I2C_CTL0_AA_Msk;
715736
}
716737
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
738+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
717739
}
718740
} else {
719741
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;

targets/TARGET_NUVOTON/TARGET_M451/i2c_api.c

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,10 @@ static void i2c_enable_vector_interrupt(i2c_t *obj, uint32_t handler, int enable
9494
static void i2c_rollback_vector_interrupt(i2c_t *obj);
9595
#endif
9696

97-
#define TRANCTRL_STARTED (1)
98-
#define TRANCTRL_NAKLASTDATA (1 << 1)
99-
#define TRANCTRL_LASTDATANAKED (1 << 2)
97+
#define TRANCTRL_STARTED (1) // Guard I2C ISR from data transfer prematurely
98+
#define TRANCTRL_NAKLASTDATA (1 << 1) // Request NACK on last data
99+
#define TRANCTRL_LASTDATANAKED (1 << 2) // Last data NACKed
100+
#define TRANCTRL_RECVDATA (1 << 3) // Receive data available
100101

101102
uint32_t us_ticker_read(void);
102103

@@ -641,7 +642,10 @@ static void i2c_irq(i2c_t *obj)
641642
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
642643
if (obj->i2c.tran_pos < obj->i2c.tran_end) {
643644
if (status == 0x50 || status == 0x58) {
644-
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
645+
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
646+
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
647+
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
648+
}
645649
}
646650

647651
if (status == 0x58) {
@@ -653,6 +657,10 @@ static void i2c_irq(i2c_t *obj)
653657
#endif
654658
i2c_fsm_tranfini(obj, 1);
655659
}
660+
else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
661+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
662+
i2c_disable_int(obj);
663+
}
656664
else {
657665
uint32_t i2c_ctl = I2C_CTL_SI_Msk | I2C_CTL_AA_Msk;
658666
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -661,6 +669,7 @@ static void i2c_irq(i2c_t *obj)
661669
i2c_ctl &= ~I2C_CTL_AA_Msk;
662670
}
663671
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
672+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
664673
}
665674
}
666675
else {
@@ -719,7 +728,10 @@ static void i2c_irq(i2c_t *obj)
719728
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
720729
if (obj->i2c.tran_pos < obj->i2c.tran_end) {
721730
if (status == 0x80 || status == 0x88) {
722-
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
731+
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
732+
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
733+
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
734+
}
723735
}
724736

725737
if (status == 0x88) {
@@ -732,6 +744,10 @@ static void i2c_irq(i2c_t *obj)
732744
obj->i2c.slaveaddr_state = NoData;
733745
i2c_fsm_reset(obj, I2C_CTL_SI_Msk | I2C_CTL_AA_Msk);
734746
}
747+
else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
748+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
749+
i2c_disable_int(obj);
750+
}
735751
else {
736752
uint32_t i2c_ctl = I2C_CTL_SI_Msk | I2C_CTL_AA_Msk;
737753
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -740,6 +756,7 @@ static void i2c_irq(i2c_t *obj)
740756
i2c_ctl &= ~I2C_CTL_AA_Msk;
741757
}
742758
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
759+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
743760
}
744761
}
745762
else {
@@ -764,7 +781,10 @@ static void i2c_irq(i2c_t *obj)
764781
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
765782
if (obj->i2c.tran_pos < obj->i2c.tran_end) {
766783
if (status == 0x90 || status == 0x98) {
767-
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
784+
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
785+
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
786+
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
787+
}
768788
}
769789

770790
if (status == 0x98) {
@@ -777,6 +797,10 @@ static void i2c_irq(i2c_t *obj)
777797
obj->i2c.slaveaddr_state = NoData;
778798
i2c_fsm_reset(obj, I2C_CTL_SI_Msk | I2C_CTL_AA_Msk);
779799
}
800+
else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
801+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
802+
i2c_disable_int(obj);
803+
}
780804
else {
781805
uint32_t i2c_ctl = I2C_CTL_SI_Msk | I2C_CTL_AA_Msk;
782806
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -785,6 +809,7 @@ static void i2c_irq(i2c_t *obj)
785809
i2c_ctl &= ~I2C_CTL_AA_Msk;
786810
}
787811
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
812+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
788813
}
789814
}
790815
else {

targets/TARGET_NUVOTON/TARGET_M480/i2c_api.c

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

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

9293
uint32_t us_ticker_read(void);
9394

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

597601
if (status == 0x58) {
598602
i2c_fsm_tranfini(obj, 1);
603+
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
604+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
605+
i2c_disable_int(obj);
599606
} else {
600607
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
601608
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -604,6 +611,7 @@ static void i2c_irq(i2c_t *obj)
604611
i2c_ctl &= ~I2C_CTL0_AA_Msk;
605612
}
606613
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
614+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
607615
}
608616
} else {
609617
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
@@ -658,12 +666,18 @@ static void i2c_irq(i2c_t *obj)
658666
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
659667
if (obj->i2c.tran_pos < obj->i2c.tran_end) {
660668
if (status == 0x80 || status == 0x88) {
661-
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
669+
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
670+
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
671+
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
672+
}
662673
}
663674

664675
if (status == 0x88) {
665676
obj->i2c.slaveaddr_state = NoData;
666677
i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
678+
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
679+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
680+
i2c_disable_int(obj);
667681
} else {
668682
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
669683
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -672,6 +686,7 @@ static void i2c_irq(i2c_t *obj)
672686
i2c_ctl &= ~I2C_CTL0_AA_Msk;
673687
}
674688
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
689+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
675690
}
676691
} else {
677692
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
@@ -694,12 +709,18 @@ static void i2c_irq(i2c_t *obj)
694709
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
695710
if (obj->i2c.tran_pos < obj->i2c.tran_end) {
696711
if (status == 0x90 || status == 0x98) {
697-
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
712+
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
713+
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
714+
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
715+
}
698716
}
699717

700718
if (status == 0x98) {
701719
obj->i2c.slaveaddr_state = NoData;
702720
i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
721+
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
722+
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
723+
i2c_disable_int(obj);
703724
} else {
704725
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
705726
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@@ -708,6 +729,7 @@ static void i2c_irq(i2c_t *obj)
708729
i2c_ctl &= ~I2C_CTL0_AA_Msk;
709730
}
710731
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
732+
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
711733
}
712734
} else {
713735
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;

0 commit comments

Comments
 (0)