summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Shawcroft <scott.shawcroft@gmail.com>2018-03-26 15:13:52 -0700
committerScott Shawcroft <scott.shawcroft@gmail.com>2018-03-26 15:13:52 -0700
commit37538fc0e771ab20b21e25bca7dfd72a2fd82f16 (patch)
treeac1413dcf833cae1f6e7adb3293dc438fb765b94
parentea39f4378e01a12957493cc7cb5fd57a2c21bf6a (diff)
Fix I2C init hang when the SCL pin is pulled low.
We added a check to make sure the pins are in a high state before initing the bus. This leads to a friendly error message when someone forgets to add the pull up resistors to their circuit.
-rw-r--r--ports/atmel-samd/common-hal/busio/I2C.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c
index 4ac1f340c..9fbe2101d 100644
--- a/ports/atmel-samd/common-hal/busio/I2C.c
+++ b/ports/atmel-samd/common-hal/busio/I2C.c
@@ -72,6 +72,19 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
mp_raise_ValueError("Invalid pins");
}
+ // Test that the pins are in a high state. (Hopefully indicating they are pulled up.)
+ gpio_set_pin_function(sda->pin, GPIO_PIN_FUNCTION_OFF);
+ gpio_set_pin_function(scl->pin, GPIO_PIN_FUNCTION_OFF);
+ gpio_set_pin_direction(sda->pin, GPIO_DIRECTION_IN);
+ gpio_set_pin_direction(scl->pin, GPIO_DIRECTION_IN);
+ gpio_set_pin_pull_mode(sda->pin, GPIO_PULL_OFF);
+ gpio_set_pin_pull_mode(scl->pin, GPIO_PULL_OFF);
+
+ if (!gpio_get_pin_level(sda->pin) || !gpio_get_pin_level(scl->pin)) {
+ mp_raise_RuntimeError("SDA or SCL need a pull up");
+ }
+ gpio_set_pin_function(sda->pin, sda_pinmux);
+ gpio_set_pin_function(scl->pin, scl_pinmux);
// Set up I2C clocks on sercom.
samd_peripherals_sercom_clock_init(sercom, sercom_index);
@@ -80,12 +93,6 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
mp_raise_OSError(MP_EIO);
}
- gpio_set_pin_pull_mode(sda->pin, GPIO_PULL_OFF);
- gpio_set_pin_function(sda->pin, sda_pinmux);
-
- gpio_set_pin_pull_mode(scl->pin, GPIO_PULL_OFF);
- gpio_set_pin_function(scl->pin, scl_pinmux);
-
// clkrate is always 0. baud_rate is in kHz.
// Frequency must be set before the I2C device is enabled.