Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[arduino-esp32 as component in idf hello world] one character 0xFF allways receive and sucks #1061

Closed
ESP32DE opened this issue Feb 1, 2018 · 40 comments

Comments

@ESP32DE
Copy link

ESP32DE commented Feb 1, 2018

hi

after a few time i try esp32-arduino core
( last actually version with 490 commits ) with ESP-IDF ( last ESP-IDF version with 4630 commits )
as component for a fun project

i noted that i get allways some rubbish character after boot
the code is simple:

//file: main.cpp
#include "Arduino.h"

void setup(){
  Serial.begin(115200);
}

void loop(){
  Serial.println("loop");
  delay(1000);
}

the output:
grafik

i change the code then with a delay for enough time give for setup the peripherals

//file: main.cpp
#include "Arduino.h"

void setup(){
  Serial.begin(115200);
  delay(500);
}

void loop(){
  Serial.println("loop");
  delay(1000);
}

the output is little better only one character on begin sucks

grafik

i try then few things but this one character goes not away

//file: main.cpp
#include "Arduino.h"

void setup(){
  Serial.begin(115200);
   delay(5000);
}

void loop(){

  delay(5000);
  while (-1) {
   Serial.println("loop");
   delay(1000);
  }
} 

but this character sucks allways again

grafik

grafik

the character is 0xFF ( on baud 115200 )

grafik

from where this character comes?
which task has this sign?
why is it here?
can we eliminate it?

thanks
best wishes

@ESP32DE ESP32DE changed the title [arduino as component in idf hello world] one character 0xFF allways receive and sucks [arduino-esp32 as component in idf hello world] one character 0xFF allways receive and sucks Feb 1, 2018
@me-no-dev
Copy link
Member

ughhh... things like that are usually caused by unstable UART lines that detect fake data if there is some voltage fluctuation on the pins (you can start UART1 on other pins and try touching them. you will see the same thing to happen).
What is the UART chip on that board? What board is that?

@ESP32DE
Copy link
Author

ESP32DE commented Feb 1, 2018

:)

yes this was my first thinking too so i used and tested:

  • DevKitC
  • Nano32
  • Wrover-Kit
  • Pico D4 Kit
  • ESP32-Gateway
  • ESP32-EVB
  • ESP32-Pro
  • JESP32-NANO
  • ..

UARTS:

  • CP2102
  • FT2232
  • FTDI1637-C
  • ..

all with same result.

this small pause before start i think it is ok -
most MCU need a small setup time, so the first rubbish character's is ok
and we can setup with a small delay(100) for setup time.

but the one 0xFF character ( 115200 baud ) sucks
perhabs this 0xFF is a return from anything and it is in the uart buffer and was not flush before Serial write?

@ESP32DE
Copy link
Author

ESP32DE commented Feb 1, 2018

flush is done here right`?

@ESP32DE
Copy link
Author

ESP32DE commented Feb 1, 2018

test:

grafik

no 0xFF character that sucks:

grafik

@ESP32DE
Copy link
Author

ESP32DE commented Feb 1, 2018

some further test step by step..

grafik

allways same - no 0xFF - character
grafik

then deeper tests:

grafik

and here we are again with this 0xFF

grafik

so the question is:
from where comes this 0xFF between the code positions :)

@ESP32DE
Copy link
Author

ESP32DE commented Feb 1, 2018

same doing in arduino ide, there is no 0xFF character,
but there is othe log on start too - can it be that the log mechanism send this 0xFF ?

grafik

@ESP32DE
Copy link
Author

ESP32DE commented Feb 1, 2018

more testings: switch off all log print ( bootloader, app, ...)

this 0xFF character sucks in ESP-IDF with esp32-arduino as component
i think - the problem is in ESP-IDF then `?

grafik

grafik

@MarkusAD
Copy link
Contributor

MarkusAD commented Feb 2, 2018

Make a loop in setup that eats any initial characters...

Serial.begin(115200);
delay(500);
while (Serial.available()) {
 char c = Serial.read();
}

If its getting in the output buffer the above wont help, neither will Serial.flush() because flush works more like unix drain() in that it just waits for all output to be written out. Flush should really just drop the output buffer completely but thats not how it works on arduino or esp.

@MarkusAD
Copy link
Contributor

MarkusAD commented Feb 2, 2018

It doesn't affect straight esp-idf.. just tried and got no sign of any garbage characters (lolin32 ch341).

I (240) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
loop
loop
...

@ESP32DE
Copy link
Author

ESP32DE commented Feb 2, 2018

@markyad
txs
yes you are right, the Serial.flush() is like unix drain().. no drop effect in arduino .
yes second you also right, in esp-idf itself - no garbage character.

the garbage comes, if you use esp-idf and the arduino as component, did you try this?

grafik

if yes, which esp-idf version did you use with the arduino component?

btw: same one garbage character with this


//file: main.cpp
#include "Arduino.h"

void setup(){
  Serial.begin(115200);
  delay(500);
}

void loop(){
  // Serial.println("IDLE");
  delay(1000);
}

grafik

best wishes

@MarkusAD
Copy link
Contributor

MarkusAD commented Feb 2, 2018

I just now tried it in arduino as component of esp-idf with 3 different setups mostly different logging and peripheral configs...

I (250) cpu_start: Pro cpu start user code
I (268) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
loop
loop

Im really stumped now... I used all latest git code and latest xtensa gcc.

@ESP32DE
Copy link
Author

ESP32DE commented Feb 2, 2018

which baudrate you use?

@MarkusAD
Copy link
Contributor

MarkusAD commented Feb 2, 2018

upload 230400 and monitor 115200.

@ESP32DE
Copy link
Author

ESP32DE commented Feb 2, 2018

txs, you use monitor?
ok i will try this, i use hterminal for seeing the hex and i use ansi terminal

@stickbreaker
Copy link
Contributor

@markyad 0xff is being generated by a glitch on the tx pin. The UART of the USB Serial converter is seeing a low going pulse that is being interpreted as a Start bit. After the glitch, the TX pin is returning to a high level which the Serial Converter interprets as a 0xFF character. I would recommend you search through the UART init code, compare the differences between your working (ESP-IDF) and non Working (Arduino-esp32). Somewhere in the init code of the the Arduino section the TX pin is being driven Low.

We are encountering similar problems with I2C bus initialization. A low going glitch is being created when the GPIO pins are attached to the I2C hardware. Our glitch cause the I2C hardware state machine to lockup, not just output a erroneous character.

Chuck.

@MarkusAD
Copy link
Contributor

MarkusAD commented Feb 2, 2018

all 3 of arduino-ide, esp-idf, and arduino as component are working here with no glitches... I am using miniterm.py python terminal.

@MarkusAD
Copy link
Contributor

MarkusAD commented Feb 2, 2018

also I tried various uart configs... serial gps connected, nothing connected, and long wires connected to nothing. I never could reproduce it.

@ESP32DE
Copy link
Author

ESP32DE commented Feb 2, 2018

grafik

@ESP32DE
Copy link
Author

ESP32DE commented Feb 2, 2018

which OS you use - i use windows 7 for this.

@MarkusAD
Copy link
Contributor

MarkusAD commented Feb 2, 2018

linux ubuntu and usb is through a powered usb hub (esp32 powered by hub).

@ESP32DE
Copy link
Author

ESP32DE commented Feb 2, 2018

txs
ok i will try with linux ubuntu and monitor too but later today,
and then i push the result here.
i think did never saw this bevor in ubuntu 16.04 too, usually i use linux and IDF
strange FF :)

( i setup to \r\n for better view )

FF

grafik

do later

@MarkusAD
Copy link
Contributor

MarkusAD commented Feb 2, 2018

Also tried on a non-powered usb port which a usb voltmeter shows supply voltage lagging to 4.9V... still works here lol, I'm stumped.

@negativekelvin
Copy link

espressif/esp-idf@6fbd6a0

@ESP32DE
Copy link
Author

ESP32DE commented Feb 2, 2018

grafik


//file: main.cpp
#include "Arduino.h"

void setup(){

  // workaround
  pinMode(1,OUTPUT);
  digitalWrite(1,HIGH);

  Serial.begin(115200);
}

void loop(){
	Serial.println("loop");
	delay(3000);
}

grafik

@negativekelvin
@stickbreaker
@markyad

txs!

@ESP32DE
Copy link
Author

ESP32DE commented Feb 2, 2018

@me-no-dev
? get this "Issues" a red BUG flag now :)

edit:

//file: main.cpp
#include "Arduino.h"

void setup(){
  // workaround
  // pinMode(1,OUTPUT);
  // ok with this only too
  digitalWrite(1,HIGH);

  Serial.begin(115200);
}

void loop(){
	Serial.println("loop");
	delay(3000);
}

@stickbreaker
Copy link
Contributor

@ESP32DE I'll try that sequence on the I2C init tomorrow.
The big difference I see for I2C would be to omit the call to pinMode(scl,OUTPUT_OPEN_DRAIN | PULLUP); and just do a digitalWrite(scl,1); instead.

This is what we are currently using in esp32-hal-i2c.c

  pinMode(scl, OUTPUT_OPEN_DRAIN | PULLUP);
  pinMatrixOutAttach(scl, I2C_SCL_IDX(i2c->num), false, false);
  pinMatrixInAttach(scl, I2C_SCL_IDX(i2c->num), false);

It might work, unless the OPEN_DRAIN causes and issue.

Chuck.

@ESP32DE
Copy link
Author

ESP32DE commented Feb 2, 2018

@stickbreaker
only a back question:
do you mean scl for clock ( scl ) or dataline ( sda )
usually only sda is configured as OPENDRAIN..
ah have not seen your esp32-hal-i2c.c link
now i understand. ( its your repo? )

@me-no-dev
scl is setup as OPENDRAIN ?
usually sda is setup as OPENDRAIN and LEVEL HIGH ( PULLUP )
and (master) scl is an OUTPUT and (slave) scl is INPUT ... ( but i am not sure :) )

@ESP32DE
Copy link
Author

ESP32DE commented Feb 2, 2018

https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp32-hal-uart.c#L156

before ( 0xFF )

void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted)
{
    if(uart == NULL || txPin > 39) {
        return;
    }
    pinMode(txPin, OUTPUT);
    pinMatrixOutAttach(txPin, UART_TXD_IDX(uart->num), inverted, false);
}

after: ( -- )

void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted)
{
    if(uart == NULL || txPin > 39) {
        return;
    }
    pinMode(txPin, OUTPUT);
    digitalWrite(txPin,HIGH);
    pinMatrixOutAttach(txPin, UART_TXD_IDX(uart->num), inverted, false);
}

i think - it is fixed with this
https://github.com/ESP32DE/arduino-esp32/blob/master/cores/esp32/esp32-hal-uart.c#L156

Sketch: ( pausing/delay and workaround not more need )

//file: main.cpp
#include "Arduino.h"

void setup(){

  // workaround
  // pinMode(1,OUTPUT);
  // ok with this only too
  // digitalWrite(1,HIGH);

  Serial.begin(115200);

}

void loop(){
	Serial.println("loop-fixed");
	delay(3000);
}


grafik

#1065

best wishes
rudi ;-)

@ESP32DE ESP32DE closed this as completed Feb 2, 2018
@ESP32DE ESP32DE reopened this Feb 2, 2018
@ESP32DE
Copy link
Author

ESP32DE commented Feb 2, 2018

@me-no-dev
feel free to close it or anything
this fixed my uart glitch problem here
PR is done - txs.

@stickbreaker
how you go on in I2C ?

@stickbreaker
Copy link
Contributor

@ESP32DE Both SDA and SCL are open drain signals. The glitch happens when attaching the GPIO pin to the I2C hardware state machine I haven't tried it yet. I have to setup my test case and unwind my work on Slave mode I2C. I don't want my Slave mode code to interfere with this glitch resolution. I have Tried the digitalWrite() modification before, But have always set pinMode() in conjunction.
The I2C hardware has a configuration option to select Open Drain or Direct Drive on the SCL pin, so, perhaps our initial setup pinMode() could be the genesis of our problem. I just assumed it was necessary.

Issue #349 has a good scope screen capture of the glitchs when the hardware is init'd.
I2C Hardware Init Glitch
See those two low going spikes, one on each of the lines, (the RED vertical marker at upper left of image)

These I2C glitches cause devices on the I2C bus to lockup, sometimes the glitch also hangs the I2C peripheral inside the ESP32 when it does this, sometimes we cannot recover without a powercycle. The signal adjacent to the glitch is our attempt to release the lockup by manually sending a null out the port.

One problem with this glitch recovery method, is that the 0x00 will cause a problem if there is a second ESP32 on the I2C bus. The default initial state of the I2C hardware is SlaveMode, Address 0x00. So that initial 'reset' causes the second Slave to jump into a Slave Receive mode. with a zero length packet. This is one of the Issues I am having with my Slave Mode work. When I power cycle my test set, I can get into unconfigured/partially configured/ unstable states. If I could avoid the SDA glitch (which is treated as a START without a STOP) which can create a TIMEOUT cascade Bus hang. My life would be much easier.

Chuck.

@ESP32DE
Copy link
Author

ESP32DE commented Feb 3, 2018

@stickbreaker
hi chuck,

this i2c spice / setup we did talk in esp32.com
did have never timer for this,

cause you helped me here with this,
i have take a try now,
here you go on:

first, we must talk simply the base in I2C,
cause SDA goes here low on Wire.begin this means that here is a "START conversion"
and will crazy things in the I2S bus...
actually we have this code situation:

#include <Wire.h>>
void setup() {
  // put your setup code here, to run once:
  delay(3000);
  Wire.begin();
}
void loop() {
  // put your main code here, to run repeatedly:
}

and this result:

grafik

now cause the Wire.begin() makes here some unlucky things,
a simple test 1 gives me this:

grafik

ok, this helps not
so we do a step further here in Test 2:

grafik

how looks this to you ? :)

now finaly we go on in Test 3 with this:

grafik

vola!

take this as workaround in the meantime :)
simple insert in the Wire.begin before there is the attach, this Level set on SDA and SCL
and you go on. ( i will search the code position later and try to make PR to @me-no-dev in this too )

let me know, if you need more help or anything and how you go on now.
thanks for you tip on this UART suck character :)

hope you can now go on
best wishes and nice weekend
rudi ;-)

( i did simply use a logic anal , i have Rigol here too but i think it is not need for the setup in wire and conversions, if there are spikes in the data conversion, i would use rigol then, let me know )

ESP32DE added a commit to ESP32DE/arduino-esp32 that referenced this issue Feb 3, 2018
see espressif#1061
here a tested version and an optional suggestion
@ESP32DE
Copy link
Author

ESP32DE commented Feb 3, 2018

have phun!
best wishes
rudi ;-)
@me-no-dev thanks
PR is done here:
#1073
happy coding!

ESP32DE added a commit to ESP32DE/arduino-esp32 that referenced this issue Feb 3, 2018
see 
talk: espressif#1061
PR on origin master : espressif#1073
@ESP32DE
Copy link
Author

ESP32DE commented Feb 3, 2018

nice weekend!

@ESP32DE
Copy link
Author

ESP32DE commented Feb 3, 2018

@stickbreaker

The default initial state of the I2C hardware is SlaveMode, Address 0x00. So that initial 'reset' causes the second Slave to jump into a Slave Receive mode. with a zero length packet. This is one of the Issues I am having with my Slave Mode work

mhm.. ( you have fully right )
grafik

so we need an other setup procedure for this pins
( why this send a fully 8 bit packet in setup, perhabs it looks for second "arduino" for switching in master or slave mode routine - likewise )

what, if we change this setup to a procedure "only for shake each" pins moretimes?
i will read into this second problem - yes - this setup can be a second suck not only in your design.
let me see ( next time in next test - i will response asap here then again )

@ESP32DE
Copy link
Author

ESP32DE commented Feb 3, 2018

@stickbreaker
hi chuck
test this onetime:
https://github.com/stickbreaker/arduino-esp32/blob/b502fd742468fc211b235bbe0902f6d9c8802bca/libraries/Wire/src/Wire.cpp#L96

comment it simple for a test with your rigol.. test

// i2cInitFix(i2c);

the zero packet comes from this code:

void i2cInitFix(i2c_t * i2c){
    if(i2c == NULL){
        return;
    }
    I2C_MUTEX_LOCK();
    i2cResetFiFo(i2c);
    i2cResetCmd(i2c);
    i2c->dev->int_clr.val = 0xFFFFFFFF;
    i2cSetCmd(i2c, 0, I2C_CMD_RSTART, 0, false, false, false);
    i2c->dev->fifo_data.data = 0;
    i2cSetCmd(i2c, 1, I2C_CMD_WRITE, 1, false, false, false);
    i2cSetCmd(i2c, 2, I2C_CMD_STOP, 0, false, false, false);
    if (i2c->dev->status_reg.bus_busy) // If this condition is true, the while loop will timeout as done will not be set
    {
        log_e("Busy at initialization!");
    }
    i2c->dev->ctr.trans_start = 1;
    uint16_t count = 50000;
    while ((!i2c->dev->command[2].done) && (--count > 0));
    I2C_MUTEX_UNLOCK();
}


example:
for a still test
if you fill the fifo with one byte (0x37)
if you change the line
i2c->dev->fifo_data.data = 0;
to
i2c->dev->fifo_data.data = 0x37;

looks like this:
grafik

suggest, we change the

i2cInitFix

code so that we setup all fine but
do not send a fully one byte TEST PACKET only for lookup for Bus free?!
to check for the bus free, it usually enough, we test SDA
and sure, if there are more Master's in the system we test CLK then too.

@stickbreaker
Copy link
Contributor

@ESP32DE The zero byte output was decided up because as the I2C protocol is defined, no compatible Device may answer to that address.

Your decoded I2C display is not showing the electrical signal. It is just showing 'valid' I2C decoding. The hardware glitch we are working around is a very short pulse. in the nanosecond range.

I believe your measurement device is suppressing this glitch from being displayed. The issue is that a START condition is defined as SDA going low While SCL is high. A STOP is defined as SDA going High while SCL is High. So, a glitch on SDA (low going pulse while SCL is high creates a null transaction, A START no data bits then a STOP. A NULL transaction is an illegal transaction on the I2C bus. The only guaranteed reset operation to recover from this invalid transaction is to Preform a START, (SDA going low while SCL is HIGH). PULSE SCL low nine times(8bits data one bit ACK) then Preform a STOP( SCL HIGH and then release SDA (Low to High).

This operation will reset other devices connected to the I2C bus, but if the I2C StateMachine inside the ESP32 is confused It will disallow operations through itself(Bus Busy state). To reset the Internal hardware the I2C peripheral is disabled and enabled (The glitch is generated when the peripheral is enabled, can you see where this could create an infinite recursion? disable/enable creates a glitch which causes the statemachine to detect a START (bus is now busy), the Bus Busy state is cleared by disable/enable ....)

I haven't had a chance to test your solution, setting the output high before attaching the pins.

Chuck.

@stickbreaker
Copy link
Contributor

@ESP32DE A simple bus busy state can be generated by simply grounding SDA while the I2C bus is inactive.

Wire up a simple breadboard with an ESP32, some I2C device, an 3.3k pullups to 3.3v.

Initialize the Wire() object, initialize your I2C device.

Manually stimulate SDA (touch a wire from GND to SDA).

Then try to communicate with your I2C device. The ESP32 I2C state machine will be locked up in a bus busy condition, or, perhaps in a re occurring TimeOut loop. Depending on how clean your grounding signal was (how many oscillations SDA went through from High to Low and how they were interpreted by the State Machine,) the state machine could shift into a TimeOut countdown. If it does, every 13.1ms a I2C Timeout interrupt is generated because the state machine does not see any activity on the I2C bus and It "Knows" there is a transaction underway! But nothing is happening! The only current recovery method is either a power Cycle, or peripheral disable/enable that doesn't cause a glitch cascade.

Chuck.

@dpharris
Copy link

dpharris commented Feb 9, 2018

There must be a way to reset the I2C state-machine without having to resort to a reset ... sounds like a sledge hammer to kill a mosquito.

@ESP32DE
Copy link
Author

ESP32DE commented Feb 9, 2018

@stickbreaker
i know the i2c protocol.
i will try your suggest with an osc asap and see what happens with this glitches in the signal itself.

btw
i did in the esp8266 i2c slave simple tags
for each start conversion
for each stop conversion
for each data send
i cound the data bits
and break it if there was a "false alarm"
i controll each step by tags
so the reset is not need

what if the master send "mistakenly a start?"
( or like you say with a test to connect GND to SDA shortly )
it has to reset itself
even if data was sent wrong
or missing.
there are then ACK and NAK
and they also want to be used :)

and so long SDA is on gnd
no master have to send
cause the bus is busy

the waittime then for a new try ( 13.1 ms ? ) do then a full reset?
this is bad, example on clk stretching - then there is something parts wrong configured :)
if the glitch makes this timeout caused, then this would be very bad
i will test with OSCI asap, i know the I2C Oled 0.96 did allways glitches
if you use more in the line ( 2-3 peaces ) the capazitor on this is bad and
did "recoiling" to the SDA line timewise, temporarily, without notice.
there are a few poorly designed ones on the market.

the test will be first time between 2 esp32
one as master , second as slave.
and step by step i will try to append a i2c sensor and watch the OSCI
not sure when i can take this time. but i will try.

i will try to use some I2C parts that have different addresses, and not switch enable active by GPIO.

@dpharris
+1

@copercini
Copy link
Contributor

As the main issue was solved (rubbish character after boot) and the I2C core was changed to @stickbreaker code officially after 13dcfe5 (thanks @stickbreaker) with several modifications of the code discussed here. Let's close this old issue and if you still have problems with the new I2C code, open new issues =)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants