Skip to content

Commit 9729df7

Browse files
stickbreakerCurclamas
authored andcommitted
Spurious Interrupts Temporary fix 20180711 (espressif#1625)
the 'eject' ERROR is and indication of an interrupt triggering without an source. I am working to eliminate these serviceable interrupt. This update increase stability on a HelTek Wifi Lora 32 board. with a SSD1306 OLED. This update fixes a glaring error in the interrupt allocation code, the Interrupt mask was wrong. I also dynamically adjust the FiFo thresholds based on Bus clockrate. The change to FiFo thresholds has reduced the number for 'eject' events. I also change 'eject' from and ERROR to DEBUG. An 'eject' event does not compromise i2c transmissions. It happens after a transaction has completed. Chuck.
1 parent 10f89db commit 9729df7

File tree

1 file changed

+43
-14
lines changed

1 file changed

+43
-14
lines changed

Diff for: cores/esp32/esp32-hal-i2c.c

+43-14
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,18 @@ static void IRAM_ATTR fillTxFifo(i2c_t * i2c)
491491

492492
if(!full || (a >= i2c->queueCount)) { // disable IRQ, the next dq will re-enable it
493493
i2c->dev->int_ena.tx_fifo_empty=0;
494+
495+
if(!full) { // add a byte to keep spurious tx_empty int
496+
uint8_t filler=i2c->dev->fifo_conf.tx_fifo_empty_thrhd;
497+
if(filler >( 31 - i2c->dev->status_reg.tx_fifo_cnt)){
498+
filler = ( 31 - i2c->dev->status_reg.tx_fifo_cnt);
499+
}
500+
501+
while(filler > 0){
502+
i2c->dev->fifo_data.val = 0xFE; // Just a dummy byte
503+
filler--;
504+
}
505+
}
494506
}
495507

496508
i2c->dev->int_clr.tx_fifo_empty=1;
@@ -563,9 +575,9 @@ static void IRAM_ATTR i2cIsrExit(i2c_t * i2c,const uint32_t eventCode,bool Fatal
563575
if(i2c->dq[i2c->queuePos].ctrl.mode == 1) {
564576
emptyRxFifo(i2c); // grab last few characters
565577
}
566-
578+
// log_d("raw=0x%05x status=0x%05x",i2c->dev->int_raw.val,i2c->dev->int_status.val);
567579
i2c->dev->int_ena.val = 0; // shutdown interrupts
568-
i2c->dev->int_clr.val = 0x1FFFF;
580+
i2c->dev->int_clr.val = 0x1FFF;
569581
i2c->stage = I2C_DONE;
570582
i2c->exitCode = exitCode; //true eventcode
571583

@@ -586,12 +598,16 @@ static void IRAM_ATTR i2cIsrExit(i2c_t * i2c,const uint32_t eventCode,bool Fatal
586598
static void IRAM_ATTR i2c_isr_handler_default(void* arg)
587599
{
588600
i2c_t* p_i2c = (i2c_t*) arg; // recover data
589-
uint32_t activeInt = p_i2c->dev->int_status.val&0x1FFF;
590-
591-
//portBASE_TYPE HPTaskAwoken = pdFALSE,xResult;
601+
uint32_t activeInt = p_i2c->dev->int_status.val&0x7FF;
592602

593-
if(p_i2c->stage==I2C_DONE) { //get Out
594-
log_e("eject int=%p, ena=%p",activeInt,p_i2c->dev->int_ena.val);
603+
if(!activeInt){ //spurious interrupt, possibly bus relate 20180711
604+
log_d("raw=0x%05x status=0x%05x",p_i2c->dev->int_raw.val,p_i2c->dev->int_status.val);
605+
}
606+
if(p_i2c->stage==I2C_DONE) { //get Out, can't service, not configured
607+
// this error is some kind of a race condition at high clock >400khz
608+
// see #1588. it does not compromise i2c communications though, just
609+
// a poke in the eye
610+
log_d("eject raw=%p, int=%p",p_i2c->dev->int_raw.val,activeInt);
595611
p_i2c->dev->int_ena.val = 0;
596612
p_i2c->dev->int_clr.val = activeInt; //0x1FFF;
597613
return;
@@ -610,8 +626,7 @@ static void IRAM_ATTR i2c_isr_handler_default(void* arg)
610626
intBuff[intPos[p_i2c->num]][2][p_i2c->num] = xTaskGetTickCountFromISR(); // when IRQ fired
611627

612628
#endif
613-
//uint32_t oldInt =activeInt;
614-
629+
615630
if (activeInt & I2C_TRANS_START_INT_ST_M) {
616631
// p_i2c->byteCnt=0;
617632
if(p_i2c->stage==I2C_STARTUP) {
@@ -871,18 +886,21 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
871886
f.rx_fifo_rst = 1; // fifo in reset
872887
f.tx_fifo_rst = 1; // fifo in reset
873888
f.nonfifo_en = 0; // use fifo mode
889+
f.nonfifo_tx_thres =63;
874890
// need to adjust threshold based on I2C clock rate, at 100k, 30 usually works,
875891
// sometimes the emptyRx() actually moves 31 bytes
876892
// it hasn't overflowed yet, I cannot tell if the new byte is added while
877893
// emptyRX() is executing or before?
878-
f.rx_fifo_full_thrhd = 30; // 30 bytes before INT is issued
894+
// let i2cSetFrequency() set thrhds
895+
// f.rx_fifo_full_thrhd = 30; // 30 bytes before INT is issued
896+
// f.tx_fifo_empty_thrhd = 0;
879897
f.fifo_addr_cfg_en = 0; // no directed access
880898
i2c->dev->fifo_conf.val = f.val; // post them all
881899

882900
f.rx_fifo_rst = 0; // release fifo
883901
f.tx_fifo_rst = 0;
884902
i2c->dev->fifo_conf.val = f.val; // post them all
885-
903+
886904
i2c->dev->int_clr.val = 0xFFFFFFFF; // kill them All!
887905
i2c->dev->ctr.ms_mode = 1; // master!
888906
i2c->queuePos=0;
@@ -936,9 +954,9 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
936954
ESP_INTR_FLAG_LOWMED; //< Low and medium prio interrupts. These can be handled in C.
937955

938956
if(i2c->num) {
939-
ret = esp_intr_alloc_intrstatus(ETS_I2C_EXT1_INTR_SOURCE, flags, (uint32_t)&i2c->dev->int_status.val, 0x1FFF, &i2c_isr_handler_default,i2c, &i2c->intr_handle);
957+
ret = esp_intr_alloc_intrstatus(ETS_I2C_EXT1_INTR_SOURCE, flags, (uint32_t)&i2c->dev->int_status.val, 0x7FF, &i2c_isr_handler_default,i2c, &i2c->intr_handle);
940958
} else {
941-
ret = esp_intr_alloc_intrstatus(ETS_I2C_EXT0_INTR_SOURCE, flags, (uint32_t)&i2c->dev->int_status.val, 0x1FFF, &i2c_isr_handler_default,i2c, &i2c->intr_handle);
959+
ret = esp_intr_alloc_intrstatus(ETS_I2C_EXT0_INTR_SOURCE, flags, (uint32_t)&i2c->dev->int_status.val, 0x7FF, &i2c_isr_handler_default,i2c, &i2c->intr_handle);
942960
}
943961

944962
if(ret!=ESP_OK) {
@@ -1326,12 +1344,23 @@ i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed)
13261344
if(i2c == NULL) {
13271345
return I2C_ERROR_DEV;
13281346
}
1329-
1347+
I2C_FIFO_CONF_t f;
1348+
13301349
uint32_t period = (APB_CLK_FREQ/clk_speed) / 2;
13311350
uint32_t halfPeriod = period/2;
13321351
uint32_t quarterPeriod = period/4;
13331352

13341353
I2C_MUTEX_LOCK();
1354+
1355+
// Adjust Fifo thresholds based on frequency
1356+
f.val = i2c->dev->fifo_conf.val;
1357+
uint32_t a = (clk_speed / 50000L )+1;
1358+
if (a > 24) a=24;
1359+
f.rx_fifo_full_thrhd = 32 - a;
1360+
f.tx_fifo_empty_thrhd = a;
1361+
i2c->dev->fifo_conf.val = f.val; // set thresholds
1362+
log_v("threshold=%d",a);
1363+
13351364
//the clock num during SCL is low level
13361365
i2c->dev->scl_low_period.period = period;
13371366
//the clock num during SCL is high level

0 commit comments

Comments
 (0)