31
31
#if NU_I2C_DEBUG
32
32
struct i2c_s MY_I2C ;
33
33
struct i2c_s MY_I2C_2 ;
34
- char MY_STATUS [64 ];
35
- int MY_STATUS_POS = 0 ;
36
- uint32_t MY_TIMEOUT ;
37
- uint32_t MY_ELAPSED ;
38
- uint32_t MY_T1 ;
39
- uint32_t MY_T2 ;
34
+ char MY_I2C_STATUS [64 ];
35
+ int MY_I2C_STATUS_POS = 0 ;
36
+ uint32_t MY_I2C_TIMEOUT ;
37
+ uint32_t MY_I2C_ELAPSED ;
38
+ uint32_t MY_I2C_T1 ;
39
+ uint32_t MY_I2C_T2 ;
40
40
#endif
41
41
42
42
struct nu_i2c_var {
@@ -163,12 +163,12 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
163
163
164
164
int i2c_start (i2c_t * obj )
165
165
{
166
- return i2c_do_trsn (obj , I2C_CTL_STA_Msk | I2C_CTL_SI_Msk , 1 ) ? 0 : I2C_ERROR_BUS_BUSY ;
166
+ return i2c_do_trsn (obj , I2C_CTL_STA_Msk | I2C_CTL_SI_Msk , 1 );
167
167
}
168
168
169
169
int i2c_stop (i2c_t * obj )
170
170
{
171
- return i2c_do_trsn (obj , I2C_CTL_STO_Msk | I2C_CTL_SI_Msk , 1 ) ? 0 : I2C_ERROR_BUS_BUSY ;
171
+ return i2c_do_trsn (obj , I2C_CTL_STO_Msk | I2C_CTL_SI_Msk , 1 );
172
172
}
173
173
174
174
void i2c_frequency (i2c_t * obj , int hz )
@@ -362,10 +362,10 @@ int i2c_allow_powerdown(void)
362
362
while (modinit_mask ) {
363
363
int i2c_idx = nu_ctz (modinit_mask );
364
364
const struct nu_modinit_s * modinit = i2c_modinit_tab + i2c_idx ;
365
- if ( modinit -> modname != NC ) {
366
- I2C_T * i2c_base = ( I2C_T * ) NU_MODBASE ( modinit -> modname );
365
+ struct nu_i2c_var * var = ( struct nu_i2c_var * ) modinit -> var ;
366
+ if ( var -> obj ) {
367
367
// Disallow entering power-down mode if I2C transfer is enabled.
368
- if (i2c_base -> CTL & I2C_CTL_INTEN_Msk ) {
368
+ if (i2c_active ( var -> obj ) ) {
369
369
return 0 ;
370
370
}
371
371
}
@@ -435,21 +435,21 @@ static int i2c_do_trsn(i2c_t *obj, uint32_t i2c_ctl, int sync)
435
435
#endif
436
436
}
437
437
else {
438
- #if 0
439
- // Avoid duplicate Start/Stop.
438
+ #if 1
439
+ // NOTE: Avoid duplicate Start/Stop. Otherwise, we may meet strange error .
440
440
uint32_t status = I2C_GET_STATUS (i2c_base );
441
441
442
442
switch (status ) {
443
443
case 0x08 : // Start
444
444
case 0x10 : // Master Repeat Start
445
- if (status & I2C_CTL_STA_Msk ) {
445
+ if (i2c_ctl & I2C_CTL_STA_Msk ) {
446
446
return 0 ;
447
447
}
448
448
else {
449
449
break ;
450
450
}
451
451
case 0xF8 : // Bus Released
452
- if (status & (I2C_CTL_STA_Msk | I2C_CTL_STO_Msk ) == I2C_CTL_STO_Msk ) {
452
+ if (i2c_ctl & (I2C_CTL_STA_Msk | I2C_CTL_STO_Msk ) == I2C_CTL_STO_Msk ) {
453
453
return 0 ;
454
454
}
455
455
else {
@@ -469,7 +469,7 @@ static int i2c_do_trsn(i2c_t *obj, uint32_t i2c_ctl, int sync)
469
469
470
470
i2c_enable_int (obj );
471
471
472
- return err ? 0 : 1 ;
472
+ return err ;
473
473
}
474
474
475
475
static int i2c_poll_status_timeout (i2c_t * obj , int (* is_status )(i2c_t * obj ), uint32_t timeout )
@@ -488,10 +488,10 @@ static int i2c_poll_status_timeout(i2c_t *obj, int (*is_status)(i2c_t *obj), uin
488
488
elapsed = (t2 > t1 ) ? (t2 - t1 ) : ((uint64_t ) t2 + 0xFFFFFFFF - t1 + 1 );
489
489
if (elapsed >= timeout ) {
490
490
#if NU_I2C_DEBUG
491
- MY_T1 = t1 ;
492
- MY_T2 = t2 ;
493
- MY_ELAPSED = elapsed ;
494
- MY_TIMEOUT = timeout ;
491
+ MY_I2C_T1 = t1 ;
492
+ MY_I2C_T2 = t2 ;
493
+ MY_I2C_ELAPSED = elapsed ;
494
+ MY_I2C_TIMEOUT = timeout ;
495
495
MY_I2C_2 = obj -> i2c ;
496
496
while (1 );
497
497
#endif
@@ -536,10 +536,10 @@ static int i2c_poll_tran_heatbeat_timeout(i2c_t *obj, uint32_t timeout)
536
536
if (elapsed >= timeout ) { // Transfer idle
537
537
#if NU_I2C_DEBUG
538
538
MY_I2C = obj -> i2c ;
539
- MY_T1 = t1 ;
540
- MY_T2 = t2 ;
541
- MY_ELAPSED = elapsed ;
542
- MY_TIMEOUT = timeout ;
539
+ MY_I2C_T1 = t1 ;
540
+ MY_I2C_T2 = t2 ;
541
+ MY_I2C_ELAPSED = elapsed ;
542
+ MY_I2C_TIMEOUT = timeout ;
543
543
MY_I2C_2 = obj -> i2c ;
544
544
while (1 );
545
545
#endif
@@ -631,12 +631,12 @@ static void i2c_irq(i2c_t *obj)
631
631
632
632
status = I2C_GET_STATUS (i2c_base );
633
633
#if NU_I2C_DEBUG
634
- if (MY_STATUS_POS < (sizeof (MY_STATUS ) / sizeof (MY_STATUS [0 ]))) {
635
- MY_STATUS [ MY_STATUS_POS ++ ] = status ;
634
+ if (MY_I2C_STATUS_POS < (sizeof (MY_I2C_STATUS ) / sizeof (MY_I2C_STATUS [0 ]))) {
635
+ MY_I2C_STATUS [ MY_I2C_STATUS_POS ++ ] = status ;
636
636
}
637
637
else {
638
- memset (MY_STATUS , 0x00 , sizeof (MY_STATUS ));
639
- MY_STATUS_POS = 0 ;
638
+ memset (MY_I2C_STATUS , 0x00 , sizeof (MY_I2C_STATUS ));
639
+ MY_I2C_STATUS_POS = 0 ;
640
640
}
641
641
#endif
642
642
@@ -657,16 +657,8 @@ static void i2c_irq(i2c_t *obj)
657
657
i2c_disable_int (obj );
658
658
break ;
659
659
}
660
-
661
- // NOTE: Error on the sequence below. Also on other inbetween transfers.
662
- // Cause is unknown. Replace Repeat Start or Stop/Start with Stop for workaround.
663
- // (1) Send wrt addr
664
- // (2) Send data
665
- // (3) Repeat Start
666
- // (4) Send rd addr
667
- // (5) Read data failed. Get Master Transmit Address ACK after Send rd addr.
668
- // Go Master Stop.
669
- i2c_fsm_reset (obj , I2C_CTL_STO_Msk | I2C_CTL_SI_Msk );
660
+ // Go Master Repeat Start
661
+ i2c_fsm_reset (obj , I2C_CTL_STA_Msk | I2C_CTL_SI_Msk );
670
662
}
671
663
}
672
664
else {
@@ -675,16 +667,17 @@ static void i2c_irq(i2c_t *obj)
675
667
break ;
676
668
case 0x30 : // Master Transmit Data NACK
677
669
case 0x20 : // Master Transmit Address NACK
678
- // Go Master Stop.
679
- i2c_fsm_reset (obj , I2C_CTL_STO_Msk | I2C_CTL_SI_Msk );
670
+ // Go Master Repeat Start
671
+ i2c_fsm_reset (obj , I2C_CTL_STA_Msk | I2C_CTL_SI_Msk );
680
672
break ;
681
673
case 0x38 : // Master Arbitration Lost
682
674
i2c_fsm_reset (obj , I2C_CTL_SI_Msk | I2C_CTL_AA_Msk );
683
675
break ;
684
676
685
677
case 0x48 : // Master Receive Address NACK
686
678
// Go Master Stop.
687
- i2c_fsm_reset (obj , I2C_CTL_STO_Msk | I2C_CTL_SI_Msk );
679
+ // Go Master Repeat Start
680
+ i2c_fsm_reset (obj , I2C_CTL_STA_Msk | I2C_CTL_SI_Msk );
688
681
break ;
689
682
case 0x40 : // Master Receive Address ACK
690
683
case 0x50 : // Master Receive Data ACK
@@ -702,8 +695,8 @@ static void i2c_irq(i2c_t *obj)
702
695
while (1 );
703
696
}
704
697
#endif
705
- // Go Master Stop.
706
- i2c_fsm_reset (obj , I2C_CTL_STO_Msk | I2C_CTL_SI_Msk );
698
+ // Go Master Repeat Start
699
+ i2c_fsm_reset (obj , I2C_CTL_STA_Msk | I2C_CTL_SI_Msk );
707
700
}
708
701
else {
709
702
uint32_t i2c_ctl = I2C_CTL_SI_Msk | I2C_CTL_AA_Msk ;
@@ -875,8 +868,8 @@ static void i2c_fsm_reset(i2c_t *obj, uint32_t i2c_ctl)
875
868
876
869
void i2c_transfer_asynch (i2c_t * obj , const void * tx , size_t tx_length , void * rx , size_t rx_length , uint32_t address , uint32_t stop , uint32_t handler , uint32_t event , DMAUsage hint )
877
870
{
878
- // NOTE: NUC472 I2C only supports 7-bit slave address.
879
- MBED_ASSERT ((address & 0xFFFFFF80 ) == 0 );
871
+ // NOTE: NUC472 I2C only supports 7-bit slave address. The mbed I2C address passed in is shifted left by 1 bit (7-bit addr << 1).
872
+ MBED_ASSERT ((address & 0xFFFFFF00 ) == 0 );
880
873
881
874
// NOTE: First transmit and then receive.
882
875
@@ -913,7 +906,7 @@ uint32_t i2c_irq_handler_asynch(i2c_t *obj)
913
906
else {
914
907
event = I2C_EVENT_TRANSFER_COMPLETE ;
915
908
if (obj -> i2c .stop ) {
916
- i2c_stop ( obj );
909
+ I2C_SET_CONTROL_REG ( i2c_base , I2C_CTL_STO_Msk | I2C_CTL_SI_Msk );
917
910
}
918
911
}
919
912
break ;
@@ -927,27 +920,36 @@ uint32_t i2c_irq_handler_asynch(i2c_t *obj)
927
920
I2C_SET_CONTROL_REG (i2c_base , I2C_CTL_SI_Msk );
928
921
}
929
922
else if (obj -> rx_buff .buffer && obj -> rx_buff .pos < obj -> rx_buff .length ) {
930
- i2c_start ( obj );
923
+ I2C_SET_CONTROL_REG ( i2c_base , I2C_CTL_STA_Msk | I2C_CTL_SI_Msk );
931
924
}
932
925
else {
933
926
event = I2C_EVENT_TRANSFER_COMPLETE ;
934
927
if (obj -> i2c .stop ) {
935
- i2c_stop ( obj );
928
+ I2C_SET_CONTROL_REG ( i2c_base , I2C_CTL_STO_Msk | I2C_CTL_SI_Msk );
936
929
}
937
930
}
938
931
break ;
939
932
940
933
case 0x20 : // Master Transmit Address NACK
941
934
event = I2C_EVENT_ERROR_NO_SLAVE ;
942
935
if (obj -> i2c .stop ) {
943
- i2c_stop ( obj );
936
+ I2C_SET_CONTROL_REG ( i2c_base , I2C_CTL_STO_Msk | I2C_CTL_SI_Msk );
944
937
}
945
938
break ;
946
939
947
940
case 0x30 : // Master Transmit Data NACK
948
- event = I2C_EVENT_TRANSFER_EARLY_NACK ;
949
- if (obj -> i2c .stop ) {
950
- i2c_stop (obj );
941
+ if (obj -> tx_buff .buffer && obj -> tx_buff .pos < obj -> tx_buff .length ) {
942
+ event = I2C_EVENT_TRANSFER_EARLY_NACK ;
943
+ I2C_SET_CONTROL_REG (i2c_base , I2C_CTL_STO_Msk | I2C_CTL_SI_Msk );
944
+ }
945
+ else if (obj -> rx_buff .buffer && obj -> rx_buff .pos < obj -> rx_buff .length ) {
946
+ I2C_SET_CONTROL_REG (i2c_base , I2C_CTL_STA_Msk | I2C_CTL_SI_Msk );
947
+ }
948
+ else {
949
+ event = I2C_EVENT_TRANSFER_COMPLETE ;
950
+ if (obj -> i2c .stop ) {
951
+ I2C_SET_CONTROL_REG (i2c_base , I2C_CTL_STO_Msk | I2C_CTL_SI_Msk );
952
+ }
951
953
}
952
954
break ;
953
955
@@ -968,7 +970,7 @@ uint32_t i2c_irq_handler_asynch(i2c_t *obj)
968
970
case 0x48 : // Master Receive Address NACK
969
971
event = I2C_EVENT_ERROR_NO_SLAVE ;
970
972
if (obj -> i2c .stop ) {
971
- i2c_stop ( obj );
973
+ I2C_SET_CONTROL_REG ( i2c_base , I2C_CTL_STO_Msk | I2C_CTL_SI_Msk );
972
974
}
973
975
break ;
974
976
@@ -988,7 +990,7 @@ uint32_t i2c_irq_handler_asynch(i2c_t *obj)
988
990
default :
989
991
event = I2C_EVENT_ERROR ;
990
992
if (obj -> i2c .stop ) {
991
- i2c_stop ( obj );
993
+ I2C_SET_CONTROL_REG ( i2c_base , I2C_CTL_STO_Msk | I2C_CTL_SI_Msk );
992
994
}
993
995
}
994
996
@@ -1000,9 +1002,15 @@ uint32_t i2c_irq_handler_asynch(i2c_t *obj)
1000
1002
}
1001
1003
1002
1004
uint8_t i2c_active (i2c_t * obj )
1003
- {
1004
- I2C_T * i2c_base = (I2C_T * ) NU_MODBASE (obj -> i2c .i2c );
1005
- return !! (i2c_base -> CTL & I2C_CTL_INTEN_Msk );
1005
+ {
1006
+ const struct nu_modinit_s * modinit = get_modinit (obj -> i2c .i2c , i2c_modinit_tab );
1007
+ MBED_ASSERT (modinit != NULL );
1008
+ MBED_ASSERT (modinit -> modname == obj -> i2c .i2c );
1009
+
1010
+ // Vector will be changed for async transfer. Use it to judge if async transfer is on-going.
1011
+ uint32_t vec = NVIC_GetVector (modinit -> irq_n );
1012
+ struct nu_i2c_var * var = (struct nu_i2c_var * ) modinit -> var ;
1013
+ return (vec && vec != var -> vec );
1006
1014
}
1007
1015
1008
1016
void i2c_abort_asynch (i2c_t * obj )
0 commit comments