Skip to content

Commit 3350476

Browse files
stickbreakerme-no-dev
authored andcommitted
I2C debugging and Log Dump Explaination (#2325)
* I2C debugging and Log Dump Explaination Create a help file for I2C debugging and interpretation of log dumps * Update i2c_debugging.md version * add formatting, file locations
1 parent fa6f759 commit 3350476

File tree

1 file changed

+276
-0
lines changed

1 file changed

+276
-0
lines changed

Diff for: libraries/Wire/doc/i2c_debugging.md

+276
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
# Debugging I2C
2+
3+
With the release of Arduino-ESP32 V1.0.1 the I2C subsystem contains code to exhaustively report communication errors.
4+
* Basic debugging can be enable by setting the *CORE DEBUG LEVEL* at or above *ERROR*. All errors will be directed the the *DEBUG OUTPUT* normally connected to `Serial()`.
5+
* Enhanced debugging can be used to generate specified information at specific positions during the i2c communication sequence. Increase *CORE DEBUG LEVEL* to ***DEBUG***
6+
7+
## Enable Debug Buffer
8+
The Enhanced debug features are enabled by uncommenting the `\\#define ENABLE_I2C_DEBUG_BUFFER` at line 45 of `esp32-hal-i2c.c`.
9+
* When Arduino-Esp32 is installed in Windows with Arduino Boards Manager, `esp32-hal-i2c.c` can be found in:
10+
`C:\Users\{user}\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.1\cores\esp32\`
11+
* When Arduino-Esp32 Development version is installed from GitHub, `esp32-hal-i2c.c` can be found in:
12+
`{arduino Sketch}\hardware\espressif\esp32\cores\esp32\`
13+
14+
15+
```c++
16+
//#define ENABLE_I2C_DEBUG_BUFFER
17+
```
18+
Change it to:
19+
```c++
20+
#define ENABLE_I2C_DEBUG_BUFFER
21+
```
22+
and recompile/upload the resulting code to your ESP32.
23+
24+
Enabling this `#define` will consume an additional 2570 bytes of RAM and include a commensurate amount of code FLASH. If you see the message `"Debug Buffer not Enabled"` in your console log I would suggest you un-comment the line and regenerate the error. Additional information will be supplied on the log console.
25+
26+
## Manually controlled Debugging
27+
Manual logging of the i2c control data buffers can be accomplished by using the debug control function of `Wire()`:
28+
```c++
29+
uint32_t setDebugFlags( uint32_t setBits, uint32_t resetBits);
30+
```
31+
`setBits`, and `resetBits` manually cause output of the control structures to the log console. They are bit fields that enable/disable the reporting of individual control structures during specific phases of the i2c communications sequence. The 32bit values are divided into four 8bit fields. Currently only five bits are defined. ***If an error is detected during normal operations, the relevant control structure will bit added to the log irrespective of the current debug flags.***
32+
33+
* **bit 0** causes DumpI2c to execute
34+
header information about current communications event,
35+
and the dataQueue elements showing the logical i2c transaction commands
36+
* **bit 1** causes DumpInts to execute
37+
Actual sequence of interrupts handled during last communications event, cleared on entry into `ProcQueue()`.
38+
* **bit 2** causes DumpCmdqueue to execute
39+
The last block of commands to the i2c peripheral.
40+
* **bit 3** causes DumpStatus to execute
41+
A descriptive display of the 32bit i2c peripheral status word.
42+
* **bit 4** causes DumpFifo to execute
43+
A buffer listing the sequence of data added to the txFifo of the i2c peripheral.
44+
45+
Of the four division, only three are currently implemented:
46+
* 0xXX - - - - - - : at entry of ProcQueue (`bitFlags << 24`)
47+
* 0x - - XX - - - - : at exit of ProcQueue (`bitFlags << 16`)
48+
* 0x - - - - - - XX : at entry of Flush (`bitFlags`)
49+
50+
For example, to display the sequence of Interrupts processed during the i2c communication transaction, **bit 1** would be set, and, since this information on Interrupt usage would only be valid after the communications have completed, the locus would be *at exit of ProcQueue*. The following code would be necessary.
51+
### code
52+
```c++
53+
uint8_t flag = 1 << 1; // turn on bit 1
54+
uint32_t debugFlag = flag << 16; // correctly position the 8bits of flag as the second byte of setBits.
55+
Wire.setDebugFlags(debugFlag,0);// resetBits=0 says leave all current setBits as is.
56+
57+
Wire.requestFrom(id,byteCount); // read byteCount bytes from slave at id
58+
59+
Wire.setDebugFlags(0,debugFlag); // don't add any new debug, remove debugFlag
60+
```
61+
### output of log console
62+
```
63+
[I][esp32-hal-i2c.c:437] i2cTriggerDumps(): after ProcQueue
64+
[I][esp32-hal-i2c.c:346] i2cDumpInts(): 0 row count INTR TX RX Tick
65+
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [01] 0x0001 0x0002 0x0003 0x0000 0x005baac5
66+
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [02] 0x0001 0x0200 0x0000 0x0000 0x005baac5
67+
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [03] 0x0001 0x0080 0x0000 0x0008 0x005baac6
68+
```
69+
# Debug Log example
70+
### Code
71+
To read eight bytes of data from a DS1307 RTCC
72+
```
73+
uint32_t debugFlag = 0x001F0000;
74+
uint8_t ID = 0x68;
75+
uint8_t block=8;
76+
77+
if(debugFlag >0){
78+
Wire.setDebugFlags(debugFlag,0);
79+
}
80+
81+
Wire.beginTransmission(ID);
82+
Wire.write(lowByte(addr));
83+
if((err=Wire.endTransmission(false))!=0) {
84+
Serial.printf(" EndTransmission=%d(%s)",Wire.lastError(),Wire.getErrorText(Wire.lastError()));
85+
86+
if(err!=2) {
87+
Serial.printf(", resetting\n");
88+
if( !Wire.begin()) Serial.printf(" Reset Failed\n");
89+
if(debugFlag >0) Wire.setDebugFlags(0,debugFlag);
90+
return;
91+
} else {
92+
Serial.printf(", No Device present, aborting\n");
93+
currentCommand= NO_COMMAND;
94+
return;
95+
}
96+
}
97+
err = Wire.requestFrom(ID,block,true);
98+
if(debugFlag >0){
99+
Wire.setDebugFlags(0,debugFlag);
100+
}
101+
```
102+
### output of log console
103+
```
104+
[I][esp32-hal-i2c.c:437] i2cTriggerDumps(): after ProcQueue
105+
[E][esp32-hal-i2c.c:318] i2cDumpI2c(): i2c=0x3ffbdc78
106+
[I][esp32-hal-i2c.c:319] i2cDumpI2c(): dev=0x60013000 date=0x16042000
107+
[I][esp32-hal-i2c.c:321] i2cDumpI2c(): lock=0x3ffb843c
108+
[I][esp32-hal-i2c.c:323] i2cDumpI2c(): num=0
109+
[I][esp32-hal-i2c.c:324] i2cDumpI2c(): mode=1
110+
[I][esp32-hal-i2c.c:325] i2cDumpI2c(): stage=3
111+
[I][esp32-hal-i2c.c:326] i2cDumpI2c(): error=1
112+
[I][esp32-hal-i2c.c:327] i2cDumpI2c(): event=0x3ffb85c4 bits=10
113+
[I][esp32-hal-i2c.c:328] i2cDumpI2c(): intr_handle=0x3ffb85f4
114+
[I][esp32-hal-i2c.c:329] i2cDumpI2c(): dq=0x3ffb858c
115+
[I][esp32-hal-i2c.c:330] i2cDumpI2c(): queueCount=2
116+
[I][esp32-hal-i2c.c:331] i2cDumpI2c(): queuePos=1
117+
[I][esp32-hal-i2c.c:332] i2cDumpI2c(): errorByteCnt=0
118+
[I][esp32-hal-i2c.c:333] i2cDumpI2c(): errorQueue=0
119+
[I][esp32-hal-i2c.c:334] i2cDumpI2c(): debugFlags=0x001F0000
120+
[I][esp32-hal-i2c.c:288] i2cDumpDqData(): [0] 7bit 68 W buf@=0x3ffc04b2, len=1, pos=1, ctrl=11101
121+
[I][esp32-hal-i2c.c:306] i2cDumpDqData(): 0x0000: . 00
122+
[I][esp32-hal-i2c.c:288] i2cDumpDqData(): [1] 7bit 68 R STOP buf@=0x3ffc042c, len=8, pos=8, ctrl=11111
123+
[I][esp32-hal-i2c.c:306] i2cDumpDqData(): 0x0000: 5P...... 35 50 07 06 13 09 18 00
124+
[I][esp32-hal-i2c.c:346] i2cDumpInts(): 0 row count INTR TX RX Tick
125+
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [01] 0x0001 0x0002 0x0003 0x0000 0x000073d5
126+
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [02] 0x0001 0x0200 0x0000 0x0000 0x000073d5
127+
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [03] 0x0001 0x0080 0x0000 0x0008 0x000073d6
128+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 0] Y RSTART val[0] exp[0] en[0] bytes[0]
129+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 1] Y WRITE val[0] exp[0] en[1] bytes[1]
130+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 2] Y WRITE val[0] exp[0] en[1] bytes[1]
131+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 3] Y RSTART val[0] exp[0] en[0] bytes[0]
132+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 4] Y WRITE val[0] exp[0] en[1] bytes[1]
133+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 5] Y READ val[0] exp[0] en[0] bytes[7]
134+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 6] Y READ val[1] exp[0] en[0] bytes[1]
135+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 7] Y STOP val[0] exp[0] en[0] bytes[0]
136+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 8] N RSTART val[0] exp[0] en[0] bytes[0]
137+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 9] N RSTART val[0] exp[0] en[0] bytes[0]
138+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [10] N RSTART val[0] exp[0] en[0] bytes[0]
139+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [11] N RSTART val[0] exp[0] en[0] bytes[0]
140+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [12] N RSTART val[0] exp[0] en[0] bytes[0]
141+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [13] N RSTART val[0] exp[0] en[0] bytes[0]
142+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [14] N RSTART val[0] exp[0] en[0] bytes[0]
143+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [15] N RSTART val[0] exp[0] en[0] bytes[0]
144+
[I][esp32-hal-i2c.c:385] i2cDumpStatus(): ack(0) sl_rw(0) to(0) arb(0) busy(0) sl(1) trans(0) rx(0) tx(0) sclMain(5) scl(6)
145+
[I][esp32-hal-i2c.c:424] i2cDumpFifo(): WRITE 0x68 0
146+
[I][esp32-hal-i2c.c:424] i2cDumpFifo(): READ 0x68
147+
```
148+
## Explaination of log output
149+
### DumpI2c
150+
```
151+
[I][esp32-hal-i2c.c:437] i2cTriggerDumps(): after ProcQueue
152+
[E][esp32-hal-i2c.c:318] i2cDumpI2c(): i2c=0x3ffbdc78
153+
[I][esp32-hal-i2c.c:319] i2cDumpI2c(): dev=0x60013000 date=0x16042000
154+
[I][esp32-hal-i2c.c:321] i2cDumpI2c(): lock=0x3ffb843c
155+
[I][esp32-hal-i2c.c:323] i2cDumpI2c(): num=0
156+
[I][esp32-hal-i2c.c:324] i2cDumpI2c(): mode=1
157+
[I][esp32-hal-i2c.c:325] i2cDumpI2c(): stage=3
158+
[I][esp32-hal-i2c.c:326] i2cDumpI2c(): error=1
159+
[I][esp32-hal-i2c.c:327] i2cDumpI2c(): event=0x3ffb85c4 bits=10
160+
[I][esp32-hal-i2c.c:328] i2cDumpI2c(): intr_handle=0x3ffb85f4
161+
[I][esp32-hal-i2c.c:329] i2cDumpI2c(): dq=0x3ffb858c
162+
[I][esp32-hal-i2c.c:330] i2cDumpI2c(): queueCount=2
163+
[I][esp32-hal-i2c.c:331] i2cDumpI2c(): queuePos=1
164+
[I][esp32-hal-i2c.c:332] i2cDumpI2c(): errorByteCnt=0
165+
[I][esp32-hal-i2c.c:333] i2cDumpI2c(): errorQueue=0
166+
[I][esp32-hal-i2c.c:334] i2cDumpI2c(): debugFlags=0x001F0000
167+
```
168+
variable | description
169+
---- | ----
170+
**i2c** | *memory address for control block*
171+
**dev** | *memory address for access to i2c peripheral registers*
172+
**date** | *revision date of peripheral silicon 2016, 42 week*
173+
**lock** | *hal lock handle*
174+
**num** | *0,1 which peripheral is being controlled*
175+
**mode** | *configuration of driver 0=none, 1=MASTER, 2=SLAVE, 3=MASTER and SLAVE*
176+
**stage** | *internal STATE of driver 0=not configured, 1=startup, 2=running, 3=done*
177+
**error** | *internal ERROR status 0=not configured, 1=ok, 2=error, 3=address NAK, 4=data NAK, 5=arbitration loss, 6=timeout*
178+
**event** | *handle for interprocess FreeRTOS eventSemaphore for communication between ISR and APP*
179+
**intr_handle** | *FreeRTOS handle for allocated interrupt*
180+
**dq** | *memory address for data queue control block*
181+
**queueCount** | *number of data operations in queue control block*
182+
**queuePos** | *last executed data block*
183+
**errorByteCnt** | *position in current data block when error occured -1=address byte*
184+
**errorQueue** | *queue that was executing when error occurred*
185+
**debugFlags** | *current specified error bits*
186+
187+
### DQ data
188+
```
189+
[I][esp32-hal-i2c.c:288] i2cDumpDqData(): [0] 7bit 68 W buf@=0x3ffc04b2, len=1, pos=1, ctrl=11101
190+
[I][esp32-hal-i2c.c:306] i2cDumpDqData(): 0x0000: . 00
191+
[I][esp32-hal-i2c.c:288] i2cDumpDqData(): [1] 7bit 68 R STOP buf@=0x3ffc042c, len=8, pos=8, ctrl=11111
192+
[I][esp32-hal-i2c.c:306] i2cDumpDqData(): 0x0000: 5P...... 35 50 07 06 13 09 18 00
193+
```
194+
variable | description
195+
--- | ---
196+
**[n]** | *index of data queue element*
197+
**i2c address** | *7bit= 7bit i2c slave address, 10bit= 10bit i2c slave address*
198+
**direction** | *W=Write, R=READ*
199+
**STOP** | *command issued a I2C STOP, else if blank, a RESTART was issued by next dq element.*
200+
**buf@** | *pointer to data buffer*
201+
**len** | *length of data buffer*
202+
**pos** | *last position used in buffer*
203+
**ctrl** | *bit field for data queue control, this bits describe if all necessary commands have been added to peripheral command buffer. in order(START,ADDRESS_Write,DATA,STOP,ADDRESS_value*
204+
**0xnnnn** | *data buffer content, displayable followed by HEX, 32 bytes on a line.*
205+
206+
### DumpInts
207+
```
208+
[I][esp32-hal-i2c.c:346] i2cDumpInts(): 0 row count INTR TX RX Tick
209+
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [01] 0x0001 0x0002 0x0003 0x0000 0x000073d5
210+
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [02] 0x0001 0x0200 0x0000 0x0000 0x000073d5
211+
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [03] 0x0001 0x0080 0x0000 0x0008 0x000073d6
212+
```
213+
variable | description
214+
---- | ----
215+
**row** | *array index*
216+
**count** | *number of consecutive, duplicate interrupts*
217+
**INTR** | *bit value of active interrupt (from ..\esp32\tools\sdk\include\soc\soc\i2c_struct.h)*
218+
**TX** | *number of bytes added to txFifo*
219+
**RX** | *number of bytes read from rxFifo*
220+
**Tick** | *current tick counter from xTaskGetTickCountFromISR()*
221+
222+
### DumpCmdQueue
223+
```
224+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 0] Y RSTART val[0] exp[0] en[0] bytes[0]
225+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 1] Y WRITE val[0] exp[0] en[1] bytes[1]
226+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 2] Y WRITE val[0] exp[0] en[1] bytes[1]
227+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 3] Y RSTART val[0] exp[0] en[0] bytes[0]
228+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 4] Y WRITE val[0] exp[0] en[1] bytes[1]
229+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 5] Y READ val[0] exp[0] en[0] bytes[7]
230+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 6] Y READ val[1] exp[0] en[0] bytes[1]
231+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 7] Y STOP val[0] exp[0] en[0] bytes[0]
232+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 8] N RSTART val[0] exp[0] en[0] bytes[0]
233+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 9] N RSTART val[0] exp[0] en[0] bytes[0]
234+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [10] N RSTART val[0] exp[0] en[0] bytes[0]
235+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [11] N RSTART val[0] exp[0] en[0] bytes[0]
236+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [12] N RSTART val[0] exp[0] en[0] bytes[0]
237+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [13] N RSTART val[0] exp[0] en[0] bytes[0]
238+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [14] N RSTART val[0] exp[0] en[0] bytes[0]
239+
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [15] N RSTART val[0] exp[0] en[0] bytes[0]
240+
```
241+
Column | description
242+
---- | ----
243+
**command** | *RSTART= generate i2c START sequence, WRITE= output byte(s), READ= input byte(s), STOP= generate i2c STOP sequence, END= continuation flag for peripheral to pause execution waiting for a refilled command list*
244+
**val** | *value for ACK bit, 0 = LOW, 1= HIGH*
245+
**exp** | *test of ACK bit 0=no, 1=yes*
246+
**en** | *output of val, 0=no, 1=yes*
247+
**bytes** | *number of byte to send(WRITE) or receive(READ) 1..255*
248+
249+
### DumpStatus
250+
```
251+
[I][esp32-hal-i2c.c:385] i2cDumpStatus(): ack(0) sl_rw(0) to(0) arb(0) busy(0) sl(1) trans(0) rx(0) tx(0) sclMain(5) scl(6)
252+
```
253+
variable | description
254+
---- | ----
255+
**ack** | *last value for ACK bit*
256+
**sl_rw** | *mode for SLAVE operation 0=write, 1=read*
257+
**to** | *timeout*
258+
**arb** | *arbitration loss*
259+
**busy** | *bus is inuse by other Master, or SLAVE is holding SCL,SDA*
260+
**sl** | *last address on bus was equal to slave_addr*
261+
**trans** | *a byte has moved though peripheral*
262+
**rx** | *count of bytes in rxFifo*
263+
**tx** | *count of bytes in txFifo*
264+
**sclMain** | *state machine for i2c module. 0: SCL_MAIN_IDLE, 1: SCL_ADDRESS_SHIFT, 2: SCL_ACK_ADDRESS, 3: SCL_RX_DATA, 4: SCL_TX_DATA, 5: SCL_SEND_ACK, 6 :SCL_WAIT_ACK*
265+
**scl** | *SCL clock state. 0: SCL_IDLE, 1: SCL_START, 2: SCL_LOW_EDGE, 3: SCL_LOW, 4: SCL_HIGH_EDGE, 5: SCL_HIGH, 6:SCL_STOP*
266+
267+
### DumpFifo
268+
```
269+
[I][esp32-hal-i2c.c:424] i2cDumpFifo(): WRITE 0x68 0
270+
[I][esp32-hal-i2c.c:424] i2cDumpFifo(): READ 0x68
271+
```
272+
Mode | datavalues
273+
--- | ---
274+
**WRITE** | the following bytes added to the txFifo are in response to a WRITE command
275+
**READ** | the following bytes added to the txFifo are in response to a READ command
276+

0 commit comments

Comments
 (0)