-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Draft: Add 1-Wire driver #19848
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
base: master
Are you sure you want to change the base?
Draft: Add 1-Wire driver #19848
Conversation
9b16584
to
cd75a9b
Compare
Nice PR ! |
Ok. I don't know much about RIOT's test system yet. I will work on getting up to speed and write some tests for this PR.
The The way I've been testing this API and driver so far is with a ds2433 and driver. The ds2433 driver is functional, but still needs work before I submit it for PR. |
/** | ||
* @brief Search for devices on the given 1-Wire bus | ||
* | ||
* @see https://pdfserv.maximintegrated.com/en/an/AN937.pdf page 51+52 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This link now redirects to https://www.analog.com/media/en/technical-documentation/tech-articles/book-of-ibuttonreg-standards.pdf
} | ||
|
||
/* Start search. Refer to e.g. to | ||
* https://pdfserv.maximintegrated.com/en/an/AN937.pdf, page 51 and 52 for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, the URL redirects to a new page now.
//TODO: use bitfield.h for tx/rx buffers? | ||
|
||
/* bus timings as given in | ||
* https://www.maximintegrated.com/en/design/technical-documents/app-notes/1/126.html |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
drivers/soft_onewire/soft_onewire.c
Outdated
//TODO: better names? | ||
#define T_RESET_HOLD_US (480U) | ||
#define T_RESET_SAMPLE_US (70U) | ||
#define T_RESET_RECOVERY_US (410U) | ||
#define T_RW_START_US (6U) | ||
#define T_W_0_HOLD_US (60U) | ||
#define T_W_0_END_US (10U) | ||
#define T_W_1_DELAY_US (64U) | ||
#define T_R_WAIT_US (9U) | ||
#define T_R_END_US (55U) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe something like "ONEWIRE_RESET_HOLD_US"? With the "US" it should be quite clear that it's a time.
d92b70d
to
39a6876
Compare
39a6876
to
a8dd266
Compare
I think the test would need some more instructions, in a |
Yeah, the test is not really complete as is. After writing the test, I realized what a pain it is to define a bus and its params. So I'm reworking that now. I also went ahead and ported the ds18 driver to use the onewire API (coming in a separate PR). I've re-worked the API to use less RAM and ROM when only one back-end is enabled too. You should see some changes in this PR once I am finished. Pretty close... |
a8dd266
to
42e088c
Compare
At this point. I don't expect to make any more big changes to the driver code. The test code still needs some work and doc. I'm also scratching my head on how the test could be made to be common as it really could be used to test any onewire backend. I hate the thought of each new backend just copying the test and have a bunch of near duplicates. |
@dylad : a few years later, yes. See my WIP branch for that. |
static inline uint_fast8_t onewire_crc8(uint_fast16_t seed, const void *data, | ||
size_t len) | ||
{ | ||
return crc8(data, len, 0x80, seed); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I think I am not calculating the CRC properly here. Still working on figuring out the right polynomial and how to handle reflecting the input.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing up front: the polynomial is wrong. CRC8 for 1-Wire uses 0x8C and not 0x80. Actually 0x80 won't generate good CRC checksums anyways.
So it depends on if you really want to use the built-in CRC8 function or not.
For the built-in function to work, you have to reflect all the input bytes, the polynomial and the output byte. That is a lot of computation.
I wrote a smöl test program to demonstrate:
#include <checksum/crc8.h>
#include <stdio.h>
// from: https://github.com/nickandrew/avr-onewire/blob/master/maxim-crc8.c
uint8_t crc8_update(uint8_t crc, uint8_t data) {
uint8_t i;
crc = crc ^ data;
for (i = 0; i < 8; ++i) {
if (crc & 0x01) {
crc = (crc >> 1) ^ 0x8c;
} else {
crc >>= 1;
}
}
return crc;
}
uint8_t reflect_byte(uint8_t b) {
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b;
}
int main(void) {
for(uint32_t i = 0; i < 256; i++) {
uint8_t i_refl = reflect_byte(i);
uint8_t riot_CRC8 = reflect_byte(crc8((uint8_t*) &i_refl, 1, 0x31, 0x00));
uint8_t onewire_CRC8 = crc8_update(0, (uint8_t) i);
uint8_t xor_CRC8 = riot_CRC8 ^ onewire_CRC8;
printf("i: %03d, CRC8: %02X, Onewire CRC8: %02X, XOR: %02X\n",i, riot_CRC8, onewire_CRC8, xor_CRC8);
}
return 0;
}
And the output is the following:
2025-06-06 15:34:59,666 # RIOT native hardware initialization complete.
2025-06-06 15:34:59,667 #
2025-06-06 15:34:59,668 # main(): This is RIOT! (Version: 2025.04-devel-500-g42e08-add-driver-onewire)
2025-06-06 15:34:59,668 # i: 000, CRC8: 00, Onewire CRC8: 00, XOR: 00
2025-06-06 15:34:59,669 # i: 001, CRC8: 5E, Onewire CRC8: 5E, XOR: 00
2025-06-06 15:34:59,669 # i: 002, CRC8: BC, Onewire CRC8: BC, XOR: 00
2025-06-06 15:34:59,669 # i: 003, CRC8: E2, Onewire CRC8: E2, XOR: 00
2025-06-06 15:34:59,670 # i: 004, CRC8: 61, Onewire CRC8: 61, XOR: 00
2025-06-06 15:34:59,671 # i: 005, CRC8: 3F, Onewire CRC8: 3F, XOR: 00
2025-06-06 15:34:59,671 # i: 006, CRC8: DD, Onewire CRC8: DD, XOR: 00
2025-06-06 15:34:59,671 # i: 007, CRC8: 83, Onewire CRC8: 83, XOR: 00
2025-06-06 15:34:59,672 # i: 008, CRC8: C2, Onewire CRC8: C2, XOR: 00
2025-06-06 15:34:59,672 # i: 009, CRC8: 9C, Onewire CRC8: 9C, XOR: 00
2025-06-06 15:34:59,673 # i: 010, CRC8: 7E, Onewire CRC8: 7E, XOR: 00
2025-06-06 15:34:59,673 # i: 011, CRC8: 20, Onewire CRC8: 20, XOR: 00
2025-06-06 15:34:59,674 # i: 012, CRC8: A3, Onewire CRC8: A3, XOR: 00
2025-06-06 15:34:59,675 # i: 013, CRC8: FD, Onewire CRC8: FD, XOR: 00
2025-06-06 15:34:59,675 # i: 014, CRC8: 1F, Onewire CRC8: 1F, XOR: 00
2025-06-06 15:34:59,676 # i: 015, CRC8: 41, Onewire CRC8: 41, XOR: 00
2025-06-06 15:34:59,676 # i: 016, CRC8: 9D, Onewire CRC8: 9D, XOR: 00
2025-06-06 15:34:59,677 # i: 017, CRC8: C3, Onewire CRC8: C3, XOR: 00
2025-06-06 15:34:59,678 # i: 018, CRC8: 21, Onewire CRC8: 21, XOR: 00
2025-06-06 15:34:59,679 # i: 019, CRC8: 7F, Onewire CRC8: 7F, XOR: 00
2025-06-06 15:34:59,679 # i: 020, CRC8: FC, Onewire CRC8: FC, XOR: 00
2025-06-06 15:34:59,680 # i: 021, CRC8: A2, Onewire CRC8: A2, XOR: 00
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO it would be best to just add a crc8r
or crc8_refl
or crc8_reflected
function to sys/checksum/crc8
and extend the unittest for it.
Perhaps in a separate PR.
Maybe I got some time to look at that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return crc8(data, len, 0x80, seed); | |
return crc8_lsb(data, len, 0x8C, seed); |
Once #21543 is merged, you can change it to this. Remember to also change the CRC polynomial.
Unfortunately I don't have the Discovery at hand, but I tried with an nRF52840DK and a Nucleo-L152RE and L073RZ. The nRF52840DK just doesn't work, it does not recognize the DS18B20. Neither with the This is the log (with ENABLE_DEBUG = 1 in the
The same happens on other GPIO pins as well and also with an external 4.7k Pull Up. It appears like some data is exchanged on the bus, but idk enough about OneWire to tell what might be the fault here. For good measure I tried with an 1k Pullup, but that leads to the same result. The sensor is a fake, but it does work. I checked it with an Arduino Uno and this tool: https://github.com/cpetrich/counterfeit_DS18B20
The Nucleos crash with a failed assertion:
So it seems like it is the first assertion in the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some static errors about the documentation.
* When called, the bus driver should perform a bus reset and detect the slave | ||
* device present pulse. | ||
* | ||
* @param[in] bus 1-Wire bus descriptor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @param[in] bus 1-Wire bus descriptor | |
* @param[in] super 1-Wire bus descriptor |
/** | ||
* @brief Callback to transfer bytes from the bus | ||
* | ||
* @param[in] bus 1-Wire bus descriptor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @param[in] bus 1-Wire bus descriptor | |
* @param[in] super 1-Wire bus descriptor |
/** | ||
* @brief Callback to transfer bytes to the bus | ||
* | ||
* @param[in] bus 1-Wire bus descriptor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @param[in] bus 1-Wire bus descriptor | |
* @param[in] super 1-Wire bus descriptor |
/** | ||
* @brief Initialize soft 1-Wire bus | ||
* | ||
* @param[in] bus bus descriptor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @param[in] bus bus descriptor | |
* @param[in] super bus descriptor |
@defgroup drivers_onewire_devs 1-Wire Device Drivers | ||
@ingroup drivers_onewire | ||
@brief 1-Wire Slave Device Drivers | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Contribution description
This patch adds a 1-Wire driver which can handle multiple driver implementations. Included in the patch is a soft 1-Wire driver implementation.
Testing procedure
TODO
Issues/PRs references