Skip to content

Commit cd3fcc8

Browse files
authored
Merge pull request adafruit#2252 from dhalbert/cpb-two-i2c
nrf: allocate two I2C on CPB
2 parents c369313 + 85a6482 commit cd3fcc8

File tree

7 files changed

+71
-17
lines changed

7 files changed

+71
-17
lines changed

ports/atmel-samd/common-hal/busio/I2C.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
116116
if (i2c_m_sync_set_baudrate(&self->i2c_desc, 0, frequency / 1000) != ERR_NONE) {
117117
reset_pin_number(sda->number);
118118
reset_pin_number(scl->number);
119+
common_hal_busio_i2c_deinit(self);
119120
mp_raise_ValueError(translate("Unsupported baudrate"));
120121
}
121122

ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.mk

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,10 @@ endif
2222
NRF_DEFINES += -DNRF52840_XXAA -DNRF52840
2323

2424
INTERNAL_FLASH_FILESYSTEM = 1
25+
26+
# Allocate two, not just one I2C peripheral, so that we have both
27+
# on-board and off-board I2C available.
28+
# When SPIM3 becomes available we'll be able to have two I2C and two SPI peripherals.
29+
# We use a CFLAGS define here because there are include order issues
30+
# if we try to include "mpconfigport.h" into nrfx_config.h .
31+
CFLAGS += -DCIRCUITPY_NRF_NUM_I2C=2

ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,10 @@ NRF_DEFINES += -DNRF52840_XXAA -DNRF52840
2424
QSPI_FLASH_FILESYSTEM = 1
2525
EXTERNAL_FLASH_DEVICE_COUNT = 1
2626
EXTERNAL_FLASH_DEVICES = "GD25Q16C"
27+
28+
# Allocate two, not just one I2C peripheral for CPB, so that we have both
29+
# on-board and off-board I2C available.
30+
# When SPIM3 becomes available we'll be able to have two I2C and two SPI peripherals.
31+
# We use a CFLAGS define here because there are include order issues
32+
# if we try to include "mpconfigport.h" into nrfx_config.h .
33+
CFLAGS += -DCIRCUITPY_NRF_NUM_I2C=2

ports/nrf/common-hal/busio/I2C.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,12 @@
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

154172
void 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

ports/nrf/nrfx_config.h

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,9 @@
55
#define NRFX_POWER_ENABLED 1
66
#define NRFX_POWER_CONFIG_IRQ_PRIORITY 7
77

8-
// Turn on nrfx supported workarounds for errata in Rev1/Rev2 of nRF52832
9-
#ifdef NRF52832_XXAA
10-
#define NRFX_SPIS_NRF52_ANOMALY_109_WORKAROUND_ENABLED 1
11-
#endif
12-
13-
// NOTE: THIS WORKAROUND CAUSES BLE CODE TO CRASH; tested on 2019-03-11.
8+
// NOTE: THIS WORKAROUND CAUSES BLE CODE TO CRASH.
9+
// It doesn't work with the SoftDevice.
10+
// See https://devzone.nordicsemi.com/f/nordic-q-a/33982/sdk-15-software-crash-during-spi-session
1411
// Turn on nrfx supported workarounds for errata in Rev1 of nRF52840
1512
#ifdef NRF52840_XXAA
1613
// #define NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED 1
@@ -24,11 +21,26 @@
2421
// so out of the box TWIM0/SPIM0 and TWIM1/SPIM1 cannot be shared
2522
// between common-hal/busio/I2C.c and SPI.c.
2623
// We could write an interrupt handler that checks whether it's
27-
// being used for SPI or I2C, but perhaps two I2C's and 1-2 SPI's are good enough for now.
24+
// being used for SPI or I2C, but perhaps one I2C and two SPI or two I2C and one SPI
25+
// are good enough for now.
26+
27+
// CIRCUITPY_NRF_NUM_I2C is 1 or 2 to choose how many I2C (TWIM) peripherals
28+
// to provide.
29+
// This can go away once we have SPIM3 working: then we can have two
30+
// I2C and two SPI.
31+
#ifndef CIRCUITPY_NRF_NUM_I2C
32+
#define CIRCUITPY_NRF_NUM_I2C 1
33+
#endif
34+
35+
#if CIRCUITPY_NRF_NUM_I2C != 1 && CIRCUITPY_NRF_NUM_I2C != 2
36+
# error CIRCUITPY_NRF_NUM_I2C must be 1 or 2
37+
#endif
2838

2939
// Enable SPIM1, SPIM2 and SPIM3 (if available)
3040
// No conflict with TWIM0.
41+
#if CIRCUITPY_NRF_NUM_I2C == 1
3142
#define NRFX_SPIM1_ENABLED 1
43+
#endif
3244
#define NRFX_SPIM2_ENABLED 1
3345
// DON'T ENABLE SPIM3 DUE TO ANOMALY WORKAROUND FAILURE (SEE ABOVE).
3446
// #ifdef NRF52840_XXAA
@@ -45,10 +57,13 @@
4557
// QSPI
4658
#define NRFX_QSPI_ENABLED 1
4759

48-
// TWI aka. I2C; enable a single bus: TWIM0 (no conflict with SPIM1 and SPIM2)
60+
// TWI aka. I2C; always enable TWIM0 (no conflict with SPIM1 and SPIM2)
4961
#define NRFX_TWIM_ENABLED 1
5062
#define NRFX_TWIM0_ENABLED 1
51-
//#define NRFX_TWIM1_ENABLED 1
63+
64+
#if CIRCUITPY_NRF_NUM_I2C == 2
65+
#define NRFX_TWIM1_ENABLED 1
66+
#endif
5267

5368
#define NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY 7
5469
#define NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY NRF_TWIM_FREQ_400K

shared-bindings/busio/I2C.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@
6060
//| :param int frequency: The clock frequency in Hertz
6161
//| :param int timeout: The maximum clock stretching timeut - (used only for bitbangio.I2C; ignored for busio.I2C)
6262
//|
63+
//| .. note:: On the nRF52840, only one I2C object may be created,
64+
//| except on the Circuit Playground Bluefruit, which allows two,
65+
//| one for the onboard accelerometer, and one for offboard use.
66+
//|
6367
STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
6468
busio_i2c_obj_t *self = m_new_obj(busio_i2c_obj_t);
6569
self->base.type = &busio_i2c_type;

shared-bindings/busio/SPI.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,12 @@ STATIC void check_for_deinit(busio_spi_obj_t *self) {
154154
//| within spec for the SAMD21.
155155
//|
156156
//| .. note:: On the nRF52840, these baudrates are available: 125kHz, 250kHz, 1MHz, 2MHz, 4MHz,
157-
//| and 8MHz. 16MHz and 32MHz are also available, but only on the first
158-
//| `busio.SPI` object you create. Two more ``busio.SPI`` objects can be created, but they are restricted
159-
//| to 8MHz maximum. This is a hardware restriction: there is only one high-speed SPI peripheral.
157+
//| and 8MHz.
160158
//| If you pick a a baudrate other than one of these, the nearest lower
161159
//| baudrate will be chosen, with a minimum of 125kHz.
160+
//| Two SPI objects may be created, except on the Circuit Playground Bluefruit,
161+
//| which allows only one (to allow for an additional I2C object).
162+
//|
162163
STATIC mp_obj_t busio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
163164
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits };
164165
static const mp_arg_t allowed_args[] = {

0 commit comments

Comments
 (0)