Skip to content

Commit b28fc5f

Browse files
author
Chuck Todd
committed
reorder functions, spaceify, clockStretching recovery
Move where dumpCmdQueue() exists in .c under IDF as component, it's previous position was causing a 'error: implicit declaration of function' Small change in ISR to try to survive an extended SCL stretching event. @lonerzzz is encountering a timeout during init of a device at 0x30. It is holding SCL low longer than 13.1ms. This change may recover.
1 parent a5b33af commit b28fc5f

File tree

1 file changed

+60
-51
lines changed

1 file changed

+60
-51
lines changed

cores/esp32/esp32-hal-i2c.c

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,19 @@
3131

3232
#define DR_REG_I2C_EXT_BASE_FIXED 0x60013000
3333
#define DR_REG_I2C1_EXT_BASE_FIXED 0x60027000
34-
34+
3535
struct i2c_struct_t {
3636
i2c_dev_t * dev;
3737
#if !CONFIG_DISABLE_HAL_LOCKS
3838
xSemaphoreHandle lock;
3939
#endif
4040
uint8_t num;
41-
I2C_MODE_t mode;
41+
I2C_MODE_t mode;
4242
I2C_STAGE_t stage;
43-
I2C_ERROR_t error;
44-
EventGroupHandle_t i2c_event; // a way to monitor ISR process
45-
// maybe use it to trigger callback for OnRequest()
46-
intr_handle_t intr_handle; /*!< I2C interrupt handle*/
43+
I2C_ERROR_t error;
44+
EventGroupHandle_t i2c_event; // a way to monitor ISR process
45+
// maybe use it to trigger callback for OnRequest()
46+
intr_handle_t intr_handle; /*!< I2C interrupt handle*/
4747
I2C_DATA_QUEUE_t * dq;
4848
uint16_t queueCount;
4949
uint16_t queuePos;
@@ -78,6 +78,7 @@ static i2c_t _i2c_bus_array[2] = {
7878
#endif
7979

8080
/* Stickbreaker added for ISR 11/2017
81+
functional with Silicon date=0x16042000
8182
*/
8283
static i2c_err_t i2cAddQueue(i2c_t * i2c,uint8_t mode, uint16_t i2cDeviceAddr, uint8_t *dataPtr, uint16_t dataLen,bool sendStop, EventGroupHandle_t event){
8384

@@ -153,6 +154,11 @@ i2c_err_t i2cAddQueueRead(i2c_t * i2c, uint16_t i2cDeviceAddr, uint8_t *dataPtr,
153154
//10bit read is kind of weird, first you do a 0byte Write with 10bit
154155
// address, then a ReSTART then a 7bit Read using the the upper 7bit +
155156
// readBit.
157+
158+
// this might cause an internal register pointer problem with 10bit
159+
// devices, But, Don't have any to test agains.
160+
// this is the Industry Standard specification.
161+
156162
if((i2cDeviceAddr &0xFC00)==0x7800){ // ten bit read
157163
i2c_err_t err = i2cAddQueue(i2c,0,i2cDeviceAddr,NULL,0,false,event);
158164
if(err==I2C_ERROR_OK){
@@ -218,26 +224,26 @@ i2c_err_t i2cDetachSDA(i2c_t * i2c, int8_t sda)
218224
* */
219225
void i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uint8_t byte_num, bool ack_val, bool ack_exp, bool ack_check)
220226
{
221-
I2C_COMMAND_t cmd;
222-
cmd.val=0;
223-
cmd.ack_en = ack_check;
224-
cmd.ack_exp = ack_exp;
225-
cmd.ack_val = ack_val;
226-
cmd.byte_num = byte_num;
227-
cmd.op_code = op_code;
227+
I2C_COMMAND_t cmd;
228+
cmd.val=0;
229+
cmd.ack_en = ack_check;
230+
cmd.ack_exp = ack_exp;
231+
cmd.ack_val = ack_val;
232+
cmd.byte_num = byte_num;
233+
cmd.op_code = op_code;
228234
i2c->dev->command[index].val = cmd.val;
229235
}
230236

231237
void i2cResetFiFo(i2c_t * i2c)
232238
{
233-
I2C_FIFO_CONF_t f;
234-
f.val = i2c->dev->fifo_conf.val;
235-
f.tx_fifo_rst = 1;
236-
f.rx_fifo_rst = 1;
237-
i2c->dev->fifo_conf.val = f.val;
238-
f.tx_fifo_rst = 0;
239-
f.rx_fifo_rst = 0;
240-
i2c->dev->fifo_conf.val = f.val;
239+
I2C_FIFO_CONF_t f;
240+
f.val = i2c->dev->fifo_conf.val;
241+
f.tx_fifo_rst = 1;
242+
f.rx_fifo_rst = 1;
243+
i2c->dev->fifo_conf.val = f.val;
244+
f.tx_fifo_rst = 0;
245+
f.rx_fifo_rst = 0;
246+
i2c->dev->fifo_conf.val = f.val;
241247
}
242248

243249
i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed)
@@ -373,6 +379,24 @@ void i2cReset(i2c_t* i2c){
373379
static uint32_t intBuff[INTBUFFMAX][3];
374380
static uint32_t intPos=0;
375381
#endif
382+
383+
/* Stickbreaker ISR mode debug support
384+
*/
385+
void IRAM_ATTR dumpCmdQueue(i2c_t *i2c){
386+
uint8_t i=0;
387+
while(i<16){
388+
I2C_COMMAND_t c;
389+
c.val=i2c->dev->command[i].val;
390+
log_e("[%2d] %c op[%d] val[%d] exp[%d] en[%d] bytes[%d]",i,(c.done?'Y':'N'),
391+
c.op_code,
392+
c.ack_val,
393+
c.ack_exp,
394+
c.ack_en,
395+
c.byte_num);
396+
i++;
397+
}
398+
}
399+
376400
/* Stickbreaker ISR mode support
377401
*/
378402
static void IRAM_ATTR fillCmdQueue(i2c_t * i2c, bool INTS){
@@ -438,7 +462,7 @@ while(!done){ // fill the command[] until either 0..14 filled or out of cmds and
438462
if((!done)&&(tdq->ctrl.addrCmdSent)){ //room in command[] for at least One data (read/Write) cmd
439463
uint8_t blkSize=0; // max is 255? does numBytes =0 actually mean 256? haven't tried it.
440464
//log_e("needed=%2d index=%d",*neededRead,cmdIdx);
441-
while(( tdq->cmdBytesNeeded > tdq->ctrl.mode )&&(!done )) { // more bytes needed and room in cmd queue, leave room for END
465+
while(( tdq->cmdBytesNeeded > tdq->ctrl.mode )&&(!done )) { // more bytes needed and room in cmd queue, leave room for END
442466
blkSize = (tdq->cmdBytesNeeded > 255)?255:(tdq->cmdBytesNeeded - tdq->ctrl.mode); // Last read cmd needs different ACK setting, so leave 1 byte remainer on reads
443467
tdq->cmdBytesNeeded -= blkSize; //
444468
if(tdq->ctrl.mode==1){ //read mode
@@ -521,7 +545,7 @@ while(!done){ // fill the command[] until either 0..14 filled or out of cmds and
521545

522546
if(cmdIdx==15){ //need continuation, even if STOP is in 14, it will not matter
523547
// cmd buffer is almost full, Add END as a continuation feature
524-
// log_e("END at %d, left=%d",cmdIdx,neededRead);
548+
// log_e("END at %d, left=%d",cmdIdx,neededRead);
525549
i2cSetCmd(i2c, (cmdIdx)++,I2C_CMD_END, 0,false,false,false);
526550
i2c->dev->int_ena.end_detect=1; //maybe?
527551
i2c->dev->int_clr.end_detect=1; //maybe?
@@ -583,7 +607,7 @@ log_n("Enable Core Debug Level \"Error\"");
583607

584608
void i2cDumpI2c(i2c_t * i2c){
585609
log_e("i2c=%p",i2c);
586-
log_e("dev=%p",i2c->dev);
610+
log_e("dev=%p date=%p",i2c->dev,i2c->dev->date);
587611
log_e("lock=%p",i2c->lock);
588612
log_e("num=%d",i2c->num);
589613
log_e("mode=%d",i2c->mode);
@@ -598,23 +622,6 @@ log_e("byteCnt=%d",i2c->byteCnt);
598622
if(i2c->dq) i2cDumpDqData(i2c);
599623
}
600624

601-
/* Stickbreaker ISR mode debug support
602-
*/
603-
void IRAM_ATTR dumpCmdQueue(i2c_t *i2c){
604-
uint8_t i=0;
605-
while(i<16){
606-
I2C_COMMAND_t c;
607-
c.val=i2c->dev->command[i].val;
608-
log_e("[%2d] %c op[%d] val[%d] exp[%d] en[%d] bytes[%d]",i,(c.done?'Y':'N'),
609-
c.op_code,
610-
c.ack_val,
611-
c.ack_exp,
612-
c.ack_en,
613-
c.byte_num);
614-
i++;
615-
}
616-
}
617-
618625
/* Stickbreaker ISR mode support
619626
*/
620627
static void IRAM_ATTR fillTxFifo(i2c_t * i2c){
@@ -872,34 +879,37 @@ while (activeInt != 0) { // Ordering of 'if(activeInt)' statements is important,
872879
if (p_i2c->mode == I2C_MASTER) {
873880
// log_e("AcK Err byteCnt=%d, queuepos=%d",p_i2c->byteCnt,p_i2c->queuePos);
874881
if(p_i2c->byteCnt==1) i2cIsrExit(p_i2c,EVENT_ERROR_NAK,true);
875-
else if((p_i2c->byteCnt == 2) && (p_i2c->dq[p_i2c->queuePos].ctrl.addrReq == 2))
882+
else if((p_i2c->byteCnt == 2) && (p_i2c->dq[p_i2c->queuePos].ctrl.addrReq == 2))
876883
i2cIsrExit(p_i2c,EVENT_ERROR_NAK,true);
877884
else i2cIsrExit(p_i2c,EVENT_ERROR_DATA_NAK,true);
878885
}
879886
return;
880887
}
881888

882889
if (activeInt & I2C_TIME_OUT_INT_ST_M) {//fatal death Happens Here
883-
i2cIsrExit(p_i2c,EVENT_ERROR_TIMEOUT,true);
884-
return;
890+
// let Gross timeout occure
891+
p_i2c->dev->int_clr.time_out =1;
892+
activeInt &=~I2C_TIME_OUT_INT_ST;
893+
// i2cIsrExit(p_i2c,EVENT_ERROR_TIMEOUT,true);
894+
// return;
885895
}
886-
896+
887897
if (activeInt & I2C_TRANS_COMPLETE_INT_ST_M) {
888898
i2cIsrExit(p_i2c,EVENT_DONE,false);
889899
return; // no more work to do
890900
/*
891901
// how does slave mode act?
892902
if (p_i2c->mode == I2C_SLAVE) { // STOP detected
893-
// empty fifo
894-
// dispatch callback
903+
// empty fifo
904+
// dispatch callback
895905
*/
896906
}
897907

898908
if (activeInt & I2C_ARBITRATION_LOST_INT_ST_M) { //fatal
899909
i2cIsrExit(p_i2c,EVENT_ERROR_ARBITRATION,true);
900910
return; // no more work to do
901911
}
902-
912+
903913
if (activeInt & I2C_SLAVE_TRAN_COMP_INT_ST_M) {
904914
p_i2c->dev->int_clr.slave_tran_comp = 1;
905915
// need to complete this !
@@ -908,7 +918,7 @@ while (activeInt != 0) { // Ordering of 'if(activeInt)' statements is important,
908918
if (activeInt & I2C_END_DETECT_INT_ST_M) {
909919
p_i2c->dev->int_ena.end_detect = 0;
910920
p_i2c->dev->int_clr.end_detect = 1;
911-
p_i2c->dev->ctr.trans_start=0;
921+
p_i2c->dev->ctr.trans_start=0;
912922
fillCmdQueue(p_i2c,true); // enable interrupts
913923
p_i2c->dev->ctr.trans_start=1; // go for it
914924
activeInt&=~I2C_END_DETECT_INT_ST_M;
@@ -948,7 +958,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
948958
//log_e("procQueue i2c=%p",&i2c);
949959
*readCount = 0; //total reads accomplished in all queue elements
950960
if(i2c == NULL){
951-
return I2C_ERROR_DEV;
961+
return I2C_ERROR_DEV;
952962
}
953963

954964
I2C_MUTEX_LOCK();
@@ -1172,7 +1182,6 @@ return i2cFreeQueue(i2c);
11721182
24Nov17
11731183
Need to think about not usings I2C_MASTER_TRAN_COMP_INT_ST to adjust queuePos. This
11741184
INT triggers every byte. The only reason to know which byte is being transfered is
1175-
to decide where to store a READ or if an error occured. It may be possible to use
11761185
the status_reg.tx_fifo_cnt and a .txQueued to do this in the fillRxFifo(). The
11771186
same mechanism could work if an error occured in i2cErrorExit().
11781187
*/

0 commit comments

Comments
 (0)