2828 */
2929
3030#include "shared-bindings/busio/I2C.h"
31+ #include "shared-bindings/microcontroller/__init__.h"
3132#include "py/mperrno.h"
3233#include "py/runtime.h"
3334#include "supervisor/shared/translate.h"
3435
3536#include "nrfx_twim.h"
36- #include "nrf_gpio.h"
37-
3837#include "nrfx_spim.h"
3938#include "nrf_gpio.h"
4039
@@ -107,7 +106,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *
107106 for (size_t i = 0 ; i < MP_ARRAY_SIZE (twim_peripherals ); i ++ ) {
108107 if (!twim_peripherals [i ].in_use ) {
109108 self -> twim_peripheral = & twim_peripherals [i ];
110- self -> twim_peripheral -> in_use = true;
109+ // Mark it as in_use later after other validation is finished.
111110 break ;
112111 }
113112 }
@@ -116,10 +115,27 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *
116115 mp_raise_ValueError (translate ("All I2C peripherals are in use" ));
117116 }
118117
118+ // Test that the pins are in a high state. (Hopefully indicating they are pulled up.)
119+ nrf_gpio_cfg_input (scl -> number , NRF_GPIO_PIN_PULLDOWN );
120+ nrf_gpio_cfg_input (sda -> number , NRF_GPIO_PIN_PULLDOWN );
121+
122+ common_hal_mcu_delay_us (10 );
123+
124+ nrf_gpio_cfg_input (scl -> number , NRF_GPIO_PIN_NOPULL );
125+ nrf_gpio_cfg_input (sda -> number , NRF_GPIO_PIN_NOPULL );
126+
127+ // We must pull up within 3us to achieve 400khz.
128+ common_hal_mcu_delay_us (3 );
129+
130+ if (!nrf_gpio_pin_read (sda -> number ) || !nrf_gpio_pin_read (scl -> number )) {
131+ reset_pin_number (sda -> number );
132+ reset_pin_number (scl -> number );
133+ mp_raise_RuntimeError (translate ("SDA or SCL needs a pull up" ));
134+ }
135+
119136 nrfx_twim_config_t config = NRFX_TWIM_DEFAULT_CONFIG ;
120137 config .scl = scl -> number ;
121138 config .sda = sda -> number ;
122-
123139 // change freq. only if it's less than the default 400K
124140 if (frequency < 100000 ) {
125141 config .frequency = NRF_TWIM_FREQ_100K ;
@@ -132,6 +148,8 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *
132148 claim_pin (sda );
133149 claim_pin (scl );
134150
151+ // About to init. If we fail after this point, common_hal_busio_i2c_deinit() will set in_use to false.
152+ self -> twim_peripheral -> in_use = true;
135153 nrfx_err_t err = nrfx_twim_init (& self -> twim_peripheral -> twim , & config , NULL , NULL );
136154
137155 // A soft reset doesn't uninit the driver so we might end up with a invalid state
@@ -152,8 +170,9 @@ bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {
152170}
153171
154172void common_hal_busio_i2c_deinit (busio_i2c_obj_t * self ) {
155- if (common_hal_busio_i2c_deinited (self ))
173+ if (common_hal_busio_i2c_deinited (self )) {
156174 return ;
175+ }
157176
158177 nrfx_twim_uninit (& self -> twim_peripheral -> twim );
159178
0 commit comments