I’m just getting started with RIOT-OS and picked up an ESP32-WROOM-32 board. I had a DS18b20 so I thought that would be a good first project. No such luck!
I’ve been playing around with this for a few days and have come to the conclusion that there is just a lot of latency when doing gpio_init() to switch from GPIO_OD to GPIO_IN. So much, in fact, that there is no way to write a “1” to the bus successfully.
In ds18_write_bit(), to write a 1, ds18_low() (open drain, pull low) is called, immediately followed by ds18_release() (set GPIO to input). This takes about 40us according to my oscilloscope. This needs to happen in 10us-15us.
Am I missing anything? I’ve followed through the gpio_init() calls and then end up in the ESP32 SDK.
@kfessel is familiar with protocol. I do believe that the new GPIO LL API may be helpful here, but I have to admit that I never even looked into the protocol.
GPIO LL is already supported by ESP and (in addition to having lower overhead) has defined semantics regarding Open-Drain, in that reading from open drain pins must not merely mirror the output state, but actually reflect the logic level on the pin. (E.g. I2C clock stretching is possible to implement in software with GPIO LL, while it is not with
esp32 uses the
esp-idf-api which may be why things are so slow (just a guess). Generally we don’t try to optimize the init as much as the writing and reading but I believe if you use a different vendor that doesn’t require external APIs (st or microchip) might be a quick way to get the speed required.
There is a cost for abstraction…
Thanks for the replies. I haven’t gotten back to digging deeper into this. I pulled my tree up to the latest ‘master’ and I can see the addition of GPIO LL since the last release. On quick inspection I don’t see what it changes in terms of making gpio_init() faster.
I think Kevin might be right in the guess at slowness in esp-idf-api.
I did whip up a quick sketch in arduino and found that the OneWire and DS18 drivers work correctly there. I took at look at the guts to OneWire and it looks pretty straight forward. I still haven’t dug into the board-specific implementation for ESP32 to see how they program the GPIOs.
Unfortunately, I don’t have any other supported board except RPi-nano, whose support looks like it’s still fairly preliminary.
I think the
ds18 module is a bit dated. Some of your problem could be rooted in the driver’s use of
xtimer (see here). For some boards, it is known to not be precise enough for OneWire. I have future plans to add a OneWire API, backed by multiple implementations:
ztimer based backend
periph_timer based backend
perph_uart based backend
I just have not had an opportunity to finish this work as higher priority projects are being worked at the moment.