PaulStoffregen / OneWire

Library for Dallas/Maxim 1-Wire Chips
http://www.pjrc.com/teensy/td_libs_OneWire.html
579 stars 382 forks source link

Improvement STM32 OpenDrain output, timing issues #143

Open tshcherban opened 3 weeks ago

tshcherban commented 3 weeks ago

There is a lot of code like this

DIRECT_MODE_INPUT(reg, mask);
...
DIRECT_WRITE_LOW(reg, mask);
...
DIRECT_MODE_OUTPUT(reg, mask);  // drive output low
...
DIRECT_MODE_INPUT(reg, mask);   // allow it to float

to drive the line high/low and read it. Why cant we just set GPIO to the open_drain output (on a compatible platforms) and pull it low or release (instead of switching it from input to output and vice versa)? That would trim down unnecessary pin reconfigurations, and improve timings during read/write operations. Also, with the original code on STM32@32MHz communication seems to be barely stable, because if I capture the line signal, logic analyzers with OneWire decoders complaining about timing issues, unknown commands etc.

I've modified the OneWire library to just write low/high on OpenDrain output, and even got a stability improvement over a timing issue on the STM32 platform. For now its able to run on 24/16 MHz instead of just >= 32 MHz, and logic analyzer still recognizes wire commands/bytes. Seems a platforms supporting opendrain output would benefit from this change?

Code changes I've made:

util\OneWire_direct_gpio.h

#define DIRECT_MODE_INPUT(base, pin)    pin_function((PinName)pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0))
#define DIRECT_MODE_OUTPUT(base, pin)   pin_function((PinName)pin, STM_PIN_DATA(STM_MODE_OUTPUT_PP, GPIO_NOPULL, 0))

replaced with

#define DIRECT_MODE_INPUT(base, pin)    digitalWriteFast((PinName)pin, HIGH)
#define DIRECT_MODE_OUTPUT(base, pin)

OneWire.cpp

pinMode(pin, INPUT);

replaced with a

pinMode(PB3, OUTPUT_OPEN_DRAIN);

Of course just for test, normally that goes under #ifdef macro for corresponding architecture.