@@ -31,6 +31,32 @@ extern "C" {
31
31
#include " ets_sys.h"
32
32
};
33
33
34
+ // Inline helpers
35
+ static inline __attribute__ ((always_inline)) void SDA_LOW(const int twi_sda)
36
+ {
37
+ GPES = (1 << twi_sda);
38
+ }
39
+ static inline __attribute__ ((always_inline)) void SDA_HIGH(const int twi_sda)
40
+ {
41
+ GPEC = (1 << twi_sda);
42
+ }
43
+ static inline __attribute__ ((always_inline)) bool SDA_READ(const int twi_sda)
44
+ {
45
+ return (GPI & (1 << twi_sda)) != 0 ;
46
+ }
47
+ static inline __attribute__ ((always_inline)) void SCL_LOW(const int twi_scl)
48
+ {
49
+ GPES = (1 << twi_scl);
50
+ }
51
+ static inline __attribute__ ((always_inline)) void SCL_HIGH(const int twi_scl)
52
+ {
53
+ GPEC = (1 << twi_scl);
54
+ }
55
+ static inline __attribute__ ((always_inline)) bool SCL_READ(const int twi_scl)
56
+ {
57
+ return (GPI & (1 << twi_scl)) != 0 ;
58
+ }
59
+
34
60
35
61
// Implement as a class to reduce code size by allowing access to many global variables with a single base pointer
36
62
class Twi
@@ -95,37 +121,12 @@ class Twi
95
121
unsigned char read_byte (bool nack);
96
122
void ICACHE_RAM_ATTR onTwipEvent (uint8_t status);
97
123
98
- // Inline helpers
99
- inline void SDA_LOW ()
100
- {
101
- GPES = (1 << twi_sda);
102
- }
103
- inline void SDA_HIGH ()
104
- {
105
- GPEC = (1 << twi_sda);
106
- }
107
- inline bool SDA_READ ()
108
- {
109
- return (GPI & (1 << twi_sda)) != 0 ;
110
- }
111
- inline void SCL_LOW ()
112
- {
113
- GPES = (1 << twi_scl);
114
- }
115
- inline void SCL_HIGH ()
116
- {
117
- GPEC = (1 << twi_scl);
118
- }
119
- inline bool SCL_READ ()
120
- {
121
- return (GPI & (1 << twi_scl)) != 0 ;
122
- }
123
124
// Handle the case where a slave needs to stretch the clock with a time-limited busy wait
124
125
inline void WAIT_CLOCK_STRETCH ()
125
126
{
126
127
esp8266::polledTimeout::oneShotFastUs timeout (twi_clockStretchLimit);
127
128
esp8266::polledTimeout::periodicFastUs yieldTimeout (5000 );
128
- while (!timeout && !SCL_READ ()) // outer loop is stretch duration up to stretch limit
129
+ while (!timeout && !SCL_READ (twi_scl )) // outer loop is stretch duration up to stretch limit
129
130
{
130
131
if (yieldTimeout) // inner loop yields every 5ms
131
132
yield ();
@@ -146,9 +147,9 @@ class Twi
146
147
uint8_t transmit (const uint8_t * data, uint8_t length);
147
148
void attachSlaveRxEvent (void (*function)(uint8_t *, size_t ));
148
149
void attachSlaveTxEvent (void (*function)(void ));
149
- inline void ICACHE_RAM_ATTR reply (uint8_t ack);
150
- inline void ICACHE_RAM_ATTR stop (void );
151
- inline void ICACHE_RAM_ATTR releaseBus (void );
150
+ void ICACHE_RAM_ATTR reply (uint8_t ack);
151
+ void ICACHE_RAM_ATTR stop (void );
152
+ void ICACHE_RAM_ATTR releaseBus (void );
152
153
void enableSlave ();
153
154
};
154
155
@@ -277,57 +278,57 @@ void ICACHE_RAM_ATTR Twi::busywait(unsigned char v)
277
278
278
279
bool Twi::write_start (void )
279
280
{
280
- SCL_HIGH ();
281
- SDA_HIGH ();
282
- if (!SDA_READ ())
281
+ SCL_HIGH (twi_scl );
282
+ SDA_HIGH (twi_sda );
283
+ if (!SDA_READ (twi_sda ))
283
284
{
284
285
return false ;
285
286
}
286
287
busywait (twi_dcount);
287
- SDA_LOW ();
288
+ SDA_LOW (twi_sda );
288
289
busywait (twi_dcount);
289
290
return true ;
290
291
}
291
292
292
293
bool Twi::write_stop (void )
293
294
{
294
- SCL_LOW ();
295
- SDA_LOW ();
295
+ SCL_LOW (twi_scl );
296
+ SDA_LOW (twi_sda );
296
297
busywait (twi_dcount);
297
- SCL_HIGH ();
298
+ SCL_HIGH (twi_scl );
298
299
WAIT_CLOCK_STRETCH ();
299
300
busywait (twi_dcount);
300
- SDA_HIGH ();
301
+ SDA_HIGH (twi_sda );
301
302
busywait (twi_dcount);
302
303
return true ;
303
304
}
304
305
305
306
bool Twi::write_bit (bool bit)
306
307
{
307
- SCL_LOW ();
308
+ SCL_LOW (twi_scl );
308
309
if (bit)
309
310
{
310
- SDA_HIGH ();
311
+ SDA_HIGH (twi_sda );
311
312
}
312
313
else
313
314
{
314
- SDA_LOW ();
315
+ SDA_LOW (twi_sda );
315
316
}
316
317
busywait (twi_dcount + 1 );
317
- SCL_HIGH ();
318
+ SCL_HIGH (twi_scl );
318
319
WAIT_CLOCK_STRETCH ();
319
320
busywait (twi_dcount);
320
321
return true ;
321
322
}
322
323
323
324
bool Twi::read_bit (void )
324
325
{
325
- SCL_LOW ();
326
- SDA_HIGH ();
326
+ SCL_LOW (twi_scl );
327
+ SDA_HIGH (twi_sda );
327
328
busywait (twi_dcount + 2 );
328
- SCL_HIGH ();
329
+ SCL_HIGH (twi_scl );
329
330
WAIT_CLOCK_STRETCH ();
330
- bool bit = SDA_READ ();
331
+ bool bit = SDA_READ (twi_sda );
331
332
busywait (twi_dcount);
332
333
return bit;
333
334
}
@@ -392,7 +393,7 @@ unsigned char Twi::writeTo(unsigned char address, unsigned char * buf, unsigned
392
393
// busywait(twi_dcount);
393
394
}
394
395
i = 0 ;
395
- while (!SDA_READ () && (i++) < 10 )
396
+ while (!SDA_READ (twi_sda ) && (i++) < 10 )
396
397
{
397
398
twi_scl_valley ();
398
399
busywait (twi_dcount);
@@ -431,32 +432,40 @@ unsigned char Twi::readFrom(unsigned char address, unsigned char* buf, unsigned
431
432
// busywait(twi_dcount);
432
433
}
433
434
i = 0 ;
434
- while (!SDA_READ () && (i++) < 10 )
435
+ while (!SDA_READ (twi_sda ) && (i++) < 10 )
435
436
{
436
437
twi_scl_valley ();
437
438
busywait (twi_dcount);
438
439
}
439
440
return 0 ;
440
441
}
441
442
443
+ void Twi::twi_scl_valley (void )
444
+ {
445
+ SCL_LOW (twi_scl);
446
+ busywait (twi_dcount);
447
+ SCL_HIGH (twi_scl);
448
+ WAIT_CLOCK_STRETCH ();
449
+ }
450
+
442
451
uint8_t Twi::status ()
443
452
{
444
453
WAIT_CLOCK_STRETCH (); // wait for a slow slave to finish
445
- if (!SCL_READ ())
454
+ if (!SCL_READ (twi_scl ))
446
455
{
447
456
return I2C_SCL_HELD_LOW; // SCL held low by another device, no procedure available to recover
448
457
}
449
458
450
459
int clockCount = 20 ;
451
- while (!SDA_READ () && clockCount-- > 0 ) // if SDA low, read the bits slaves have to sent to a max
460
+ while (!SDA_READ (twi_sda ) && clockCount-- > 0 ) // if SDA low, read the bits slaves have to sent to a max
452
461
{
453
462
read_bit ();
454
- if (!SCL_READ ())
463
+ if (!SCL_READ (twi_scl ))
455
464
{
456
465
return I2C_SCL_HELD_LOW_AFTER_READ; // I2C bus error. SCL held low beyond slave clock stretch time
457
466
}
458
467
}
459
- if (!SDA_READ ())
468
+ if (!SDA_READ (twi_sda ))
460
469
{
461
470
return I2C_SDA_HELD_LOW; // I2C bus error. SDA line held low by slave/another_master after n bits.
462
471
}
@@ -500,42 +509,45 @@ void Twi::attachSlaveTxEvent(void (*function)(void))
500
509
twi_onSlaveTransmit = function;
501
510
}
502
511
503
- inline void ICACHE_RAM_ATTR Twi::reply (uint8_t ack)
512
+ // DO NOT INLINE, inlining reply() in combination with compiler optimizations causes function breakup into
513
+ // parts and the ICACHE_RAM_ATTR isn't propagated correctly to all parts, which of course causes crashes.
514
+ // TODO: test with gcc 9.x and if it still fails, disable optimization with -fdisable-ipa-fnsplit
515
+ void ICACHE_RAM_ATTR Twi::reply (uint8_t ack)
504
516
{
505
517
// transmit master read ready signal, with or without ack
506
518
if (ack)
507
519
{
508
520
// TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
509
- SCL_HIGH (); // _BV(TWINT)
521
+ SCL_HIGH (twi. twi_scl ); // _BV(TWINT)
510
522
twi_ack = 1 ; // _BV(TWEA)
511
523
}
512
524
else
513
525
{
514
526
// TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
515
- SCL_HIGH (); // _BV(TWINT)
527
+ SCL_HIGH (twi. twi_scl ); // _BV(TWINT)
516
528
twi_ack = 0 ; // ~_BV(TWEA)
517
529
}
518
530
}
519
531
520
- inline void ICACHE_RAM_ATTR Twi::stop (void )
532
+ void ICACHE_RAM_ATTR Twi::stop (void )
521
533
{
522
534
// send stop condition
523
535
// TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
524
- SCL_HIGH (); // _BV(TWINT)
536
+ SCL_HIGH (twi. twi_scl ); // _BV(TWINT)
525
537
twi_ack = 1 ; // _BV(TWEA)
526
538
busywait (5 ); // Maybe this should be here
527
- SDA_HIGH (); // _BV(TWSTO)
539
+ SDA_HIGH (twi. twi_sda ); // _BV(TWSTO)
528
540
// update twi state
529
541
twi_state = TWI_READY;
530
542
}
531
543
532
- inline void ICACHE_RAM_ATTR Twi::releaseBus (void )
544
+ void ICACHE_RAM_ATTR Twi::releaseBus (void )
533
545
{
534
546
// release bus
535
547
// TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
536
- SCL_HIGH (); // _BV(TWINT)
548
+ SCL_HIGH (twi. twi_scl ); // _BV(TWINT)
537
549
twi_ack = 1 ; // _BV(TWEA)
538
- SDA_HIGH ();
550
+ SDA_HIGH (twi. twi_sda );
539
551
540
552
// update twi state
541
553
twi_state = TWI_READY;
@@ -616,11 +628,11 @@ void ICACHE_RAM_ATTR Twi::onTwipEvent(uint8_t status)
616
628
bitCount--;
617
629
if (twi_data & 0x80 )
618
630
{
619
- SDA_HIGH ();
631
+ SDA_HIGH (twi. twi_sda );
620
632
}
621
633
else
622
634
{
623
- SDA_LOW ();
635
+ SDA_LOW (twi. twi_sda );
624
636
}
625
637
twi_data <<= 1 ;
626
638
@@ -650,14 +662,6 @@ void ICACHE_RAM_ATTR Twi::onTwipEvent(uint8_t status)
650
662
}
651
663
}
652
664
653
- void Twi::twi_scl_valley (void )
654
- {
655
- SCL_LOW ();
656
- busywait (twi_dcount);
657
- SCL_HIGH ();
658
- WAIT_CLOCK_STRETCH ();
659
- }
660
-
661
665
void ICACHE_RAM_ATTR Twi::onTimer (void *unused)
662
666
{
663
667
(void )unused;
@@ -714,8 +718,9 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
714
718
unsigned int scl;
715
719
716
720
// Store bool return in int to reduce final code size.
717
- sda = twi.SDA_READ ();
718
- scl = twi.SCL_READ ();
721
+
722
+ sda = SDA_READ (twi.twi_sda );
723
+ scl = SCL_READ (twi.twi_scl );
719
724
720
725
twi.twip_status = 0xF8 ; // reset TWI status
721
726
@@ -758,7 +763,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
758
763
}
759
764
else
760
765
{
761
- twi. SDA_LOW ();
766
+ SDA_LOW (twi. twi_sda );
762
767
}
763
768
}
764
769
else
@@ -769,7 +774,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
769
774
}
770
775
else
771
776
{
772
- twi. SDA_LOW ();
777
+ SDA_LOW (twi. twi_sda );
773
778
}
774
779
}
775
780
twi.twip_state = TWIP_WAIT_ACK;
@@ -787,13 +792,13 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
787
792
{
788
793
if ((twi.twi_data & 0xFE ) != twi.twi_addr )
789
794
{
790
- twi. SDA_HIGH ();
795
+ SDA_HIGH (twi. twi_sda );
791
796
twi.twip_state = TWIP_WAIT_STOP;
792
797
}
793
798
else
794
799
{
795
- twi. SCL_LOW (); // clock stretching
796
- twi. SDA_HIGH ();
800
+ SCL_LOW (twi. twi_scl ); // clock stretching
801
+ SDA_HIGH (twi. twi_sda );
797
802
twi.twip_mode = TWIPM_ADDRESSED;
798
803
if (!(twi.twi_data & 0x01 ))
799
804
{
@@ -810,8 +815,8 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
810
815
}
811
816
else
812
817
{
813
- twi. SCL_LOW (); // clock stretching
814
- twi. SDA_HIGH ();
818
+ SCL_LOW (twi. twi_scl ); // clock stretching
819
+ SDA_HIGH (twi. twi_sda );
815
820
if (!twi.twi_ack )
816
821
{
817
822
twi.onTwipEvent (TW_SR_DATA_NACK);
@@ -838,11 +843,11 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
838
843
twi.bitCount --;
839
844
if (twi.twi_data & 0x80 )
840
845
{
841
- twi. SDA_HIGH ();
846
+ SDA_HIGH (twi. twi_sda );
842
847
}
843
848
else
844
849
{
845
- twi. SDA_LOW ();
850
+ SDA_LOW (twi. twi_sda );
846
851
}
847
852
twi.twi_data <<= 1 ;
848
853
@@ -864,7 +869,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
864
869
}
865
870
else
866
871
{
867
- twi. SDA_HIGH ();
872
+ SDA_HIGH (twi. twi_sda );
868
873
twi.twip_state = TWIP_READ_ACK;
869
874
}
870
875
}
@@ -888,7 +893,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
888
893
}
889
894
else
890
895
{
891
- twi. SCL_LOW (); // clock stretching
896
+ SCL_LOW (twi. twi_scl ); // clock stretching
892
897
if (twi.twi_ack && twi.twi_ack_rec )
893
898
{
894
899
twi.onTwipEvent (TW_ST_DATA_ACK);
@@ -911,8 +916,8 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
911
916
unsigned int scl;
912
917
913
918
// Store bool return in int to reduce final code size.
914
- sda = twi. SDA_READ ();
915
- scl = twi. SCL_READ ();
919
+ sda = SDA_READ (twi. twi_sda );
920
+ scl = SCL_READ (twi. twi_scl );
916
921
917
922
int twip_state_mask = S2M (twi.twip_state );
918
923
if (scl) /* !DATA */
@@ -934,7 +939,7 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
934
939
else IFSTATE (S2M (TWIP_START) | S2M (TWIP_REP_START) | S2M (TWIP_SEND_ACK) | S2M (TWIP_WAIT_ACK) | S2M (TWIP_SLA_R) | S2M (TWIP_REC_ACK) | S2M (TWIP_READ_ACK) | S2M (TWIP_RWAIT_ACK) | S2M (TWIP_WRITE))
935
940
{
936
941
// START or STOP
937
- twi. SDA_HIGH (); // Should not be necessary
942
+ SDA_HIGH (twi. twi_sda ); // Should not be necessary
938
943
twi.onTwipEvent (TW_BUS_ERROR);
939
944
twi.twip_mode = TWIPM_WAIT;
940
945
twi.twip_state = TWIP_BUS_ERR;
@@ -944,11 +949,11 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
944
949
if (sda)
945
950
{
946
951
// STOP
947
- twi. SCL_LOW (); // clock stretching
952
+ SCL_LOW (twi. twi_scl ); // clock stretching
948
953
ets_timer_disarm (&twi.timer );
949
954
twi.twip_state = TWIP_IDLE;
950
955
twi.twip_mode = TWIPM_IDLE;
951
- twi. SCL_HIGH ();
956
+ SCL_HIGH (twi. twi_scl );
952
957
}
953
958
else
954
959
{
@@ -978,7 +983,7 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
978
983
else
979
984
{
980
985
// during first bit in byte transfer - ok
981
- twi. SCL_LOW (); // clock stretching
986
+ SCL_LOW (twi. twi_scl ); // clock stretching
982
987
twi.onTwipEvent (TW_SR_STOP);
983
988
if (sda)
984
989
{
0 commit comments