Added error-checking in onewire routines

This commit is contained in:
Alex Stewart 2016-03-17 13:36:31 -07:00
parent a2b9d688ea
commit 9b49b426f6
2 changed files with 63 additions and 35 deletions

View file

@ -3,6 +3,22 @@
#include "task.h" #include "task.h"
#include "esp/gpio.h" #include "esp/gpio.h"
// Waits up to `max_wait` microseconds for the specified pin to go high.
// Returns true if successful, false if the bus never comes high (likely
// shorted).
static inline bool _onewire_wait_for_bus(int pin, int max_wait) {
bool state;
for (int i = 0; i < ((max_wait + 4) / 5); i++) {
if (gpio_read(pin)) break;
sdk_os_delay_us(5);
}
state = gpio_read(pin);
// Wait an extra 1us to make sure the devices have an adequate recovery
// time before we drive things low again.
sdk_os_delay_us(1);
return state;
}
// Perform the onewire reset function. We will wait up to 250uS for // Perform the onewire reset function. We will wait up to 250uS for
// the bus to come high, if it doesn't then it is broken or shorted // the bus to come high, if it doesn't then it is broken or shorted
// and we return false; // and we return false;
@ -11,19 +27,11 @@
// //
bool onewire_reset(int pin) { bool onewire_reset(int pin) {
bool r; bool r;
const int retries = 50;
gpio_enable(pin, GPIO_OUT_OPEN_DRAIN); gpio_enable(pin, GPIO_OUT_OPEN_DRAIN);
gpio_write(pin, 1); gpio_write(pin, 1);
// wait until the wire is high... just in case // wait until the wire is high... just in case
for (int i = 0; i < retries; i++) { if (!_onewire_wait_for_bus(pin, 250)) return false;
if (gpio_read(pin)) break;
sdk_os_delay_us(5);
}
if (!gpio_read(pin)) {
// Bus shorted?
return false;
}
gpio_write(pin, 0); gpio_write(pin, 0);
sdk_os_delay_us(480); sdk_os_delay_us(480);
@ -35,17 +43,13 @@ bool onewire_reset(int pin) {
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
// Wait for all devices to finish pulling the bus low before returning // Wait for all devices to finish pulling the bus low before returning
for (int i = 0; i < retries; i++) { if (!_onewire_wait_for_bus(pin, 410)) return false;
if (gpio_read(pin)) break;
sdk_os_delay_us(5);
}
sdk_os_delay_us(2);
return r; return r;
} }
static void onewire_write_bit(int pin, uint8_t v) { static bool _onewire_write_bit(int pin, uint8_t v) {
//TODO: should verify that the bus is high before starting if (!_onewire_wait_for_bus(pin, 10)) return false;
if (v & 1) { if (v & 1) {
taskENTER_CRITICAL(); taskENTER_CRITICAL();
gpio_write(pin, 0); // drive output low gpio_write(pin, 0); // drive output low
@ -61,12 +65,14 @@ static void onewire_write_bit(int pin, uint8_t v) {
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
} }
sdk_os_delay_us(1); sdk_os_delay_us(1);
return true;
} }
static int onewire_read_bit(int pin) { static int _onewire_read_bit(int pin) {
int r; int r;
//TODO: should verify that the bus is high before starting if (!_onewire_wait_for_bus(pin, 10)) return -1;
taskENTER_CRITICAL(); taskENTER_CRITICAL();
gpio_write(pin, 0); gpio_write(pin, 0);
sdk_os_delay_us(2); sdk_os_delay_us(2);
@ -84,40 +90,56 @@ static int onewire_read_bit(int pin) {
// power after the write (e.g. DS18B20 in parasite power mode) then call // power after the write (e.g. DS18B20 in parasite power mode) then call
// onewire_power() after this is complete to actively drive the line high. // onewire_power() after this is complete to actively drive the line high.
// //
void onewire_write(int pin, uint8_t v) { bool onewire_write(int pin, uint8_t v) {
uint8_t bitMask; uint8_t bitMask;
for (bitMask = 0x01; bitMask; bitMask <<= 1) { for (bitMask = 0x01; bitMask; bitMask <<= 1) {
onewire_write_bit(pin, (bitMask & v)?1:0); if (!_onewire_write_bit(pin, (bitMask & v)?1:0)) {
return false;
} }
} }
return true;
}
void onewire_write_bytes(int pin, const uint8_t *buf, size_t count) { bool onewire_write_bytes(int pin, const uint8_t *buf, size_t count) {
size_t i; size_t i;
for (i = 0 ; i < count ; i++) { for (i = 0 ; i < count ; i++) {
onewire_write(pin, buf[i]); if (!onewire_write(pin, buf[i])) {
return false;
} }
} }
return true;
}
// Read a byte // Read a byte
// //
uint8_t onewire_read(int pin) { int onewire_read(int pin) {
uint8_t bitMask; uint8_t bitMask;
uint8_t r = 0; int r = 0;
int bit;
for (bitMask = 0x01; bitMask; bitMask <<= 1) { for (bitMask = 0x01; bitMask; bitMask <<= 1) {
if (onewire_read_bit(pin)) r |= bitMask; bit = _onewire_read_bit(pin);
if (bit < 0) {
return -1;
} else if (bit) {
r |= bitMask;
}
} }
return r; return r;
} }
void onewire_read_bytes(int pin, uint8_t *buf, size_t count) { bool onewire_read_bytes(int pin, uint8_t *buf, size_t count) {
size_t i; size_t i;
int b;
for (i = 0 ; i < count ; i++) { for (i = 0 ; i < count ; i++) {
buf[i] = onewire_read(pin); b = onewire_read(pin);
if (b < 0) return false;
buf[i] = b;
} }
return true;
} }
// Do a ROM select // Do a ROM select
@ -181,6 +203,7 @@ void onewire_search_prefix(onewire_search_t *search, uint8_t family_code) {
// 0 : device not found, end of search // 0 : device not found, end of search
// //
onewire_addr_t onewire_search_next(onewire_search_t *search, int pin) { onewire_addr_t onewire_search_next(onewire_search_t *search, int pin) {
//TODO: add more checking for read/write errors
uint8_t id_bit_number; uint8_t id_bit_number;
uint8_t last_zero, search_result; uint8_t last_zero, search_result;
int rom_byte_number; int rom_byte_number;
@ -212,11 +235,14 @@ onewire_addr_t onewire_search_next(onewire_search_t *search, int pin) {
// loop to do the search // loop to do the search
do { do {
// read a bit and its complement // read a bit and its complement
id_bit = onewire_read_bit(pin); id_bit = _onewire_read_bit(pin);
cmp_id_bit = onewire_read_bit(pin); cmp_id_bit = _onewire_read_bit(pin);
// check for no devices on 1-wire // check for no devices on 1-wire
if ((id_bit == 1) && (cmp_id_bit == 1)) { if ((id_bit < 0) || (cmp_id_bit < 0)) {
// Read error
break;
} else if ((id_bit == 1) && (cmp_id_bit == 1)) {
break; break;
} else { } else {
// all devices coupled have 0 or 1 // all devices coupled have 0 or 1
@ -247,7 +273,7 @@ onewire_addr_t onewire_search_next(onewire_search_t *search, int pin) {
} }
// serial number search direction write bit // serial number search direction write bit
onewire_write_bit(pin, search_direction); _onewire_write_bit(pin, search_direction);
// increment the byte counter id_bit_number // increment the byte counter id_bit_number
// and shift the mask rom_byte_mask // and shift the mask rom_byte_mask

View file

@ -57,14 +57,16 @@ void onewire_skip_rom(int pin);
// resistor to pull the line high when not driven low. If you need strong // resistor to pull the line high when not driven low. If you need strong
// power after the write (e.g. DS18B20 in parasite power mode) then call // power after the write (e.g. DS18B20 in parasite power mode) then call
// onewire_power() after this is complete to actively drive the line high. // onewire_power() after this is complete to actively drive the line high.
void onewire_write(int pin, uint8_t v); // Returns true if successful, false on error.
bool onewire_write(int pin, uint8_t v);
void onewire_write_bytes(int pin, const uint8_t *buf, size_t count); bool onewire_write_bytes(int pin, const uint8_t *buf, size_t count);
// Read a byte. // Read a byte.
uint8_t onewire_read(int pin); // Returns the read byte on success, negative value on error.
int onewire_read(int pin);
void onewire_read_bytes(int pin, uint8_t *buf, size_t count); bool onewire_read_bytes(int pin, uint8_t *buf, size_t count);
// Actively drive the bus high to provide extra power for certain operations of // Actively drive the bus high to provide extra power for certain operations of
// parasitically-powered devices. // parasitically-powered devices.