Merge pull request #1203 from dhalbert/nrf-multiple-i2c-spi

nrf: multiple i2c and spi instances; improve nrfx_config.h
This commit is contained in:
Scott Shawcroft 2018-09-21 12:16:43 -04:00 committed by GitHub
commit 0015db1c4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 296 additions and 107 deletions

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-18 22:20-0400\n" "POT-Creation-Date: 2018-09-20 21:52-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -356,7 +356,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/busio/SPI.c:132 #: ports/atmel-samd/common-hal/busio/SPI.c:132
#: ports/atmel-samd/common-hal/busio/UART.c:119 #: ports/atmel-samd/common-hal/busio/UART.c:119
#: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45 #: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45
#: ports/nrf/common-hal/busio/I2C.c:58 #: ports/nrf/common-hal/busio/I2C.c:77
msgid "Invalid pins" msgid "Invalid pins"
msgstr "" msgstr ""
@ -685,6 +685,18 @@ msgstr ""
msgid "AnalogOut functionality not supported" msgid "AnalogOut functionality not supported"
msgstr "" msgstr ""
#: ports/nrf/common-hal/busio/I2C.c:91
msgid "All I2C peripherals are in use"
msgstr ""
#: ports/nrf/common-hal/busio/SPI.c:109
msgid "All SPI peripherals are in use"
msgstr ""
#: ports/nrf/common-hal/busio/SPI.c:170
msgid "Baud rate too high for this SPI peripheral"
msgstr ""
#: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47 #: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47
#: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60 #: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60
#: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71 #: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-18 22:20-0400\n" "POT-Creation-Date: 2018-09-20 21:52-0400\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: Sebastian Plamauer\n" "Last-Translator: Sebastian Plamauer\n"
"Language-Team: \n" "Language-Team: \n"
@ -365,7 +365,7 @@ msgstr "Nicht genug Pins vorhanden"
#: ports/atmel-samd/common-hal/busio/SPI.c:132 #: ports/atmel-samd/common-hal/busio/SPI.c:132
#: ports/atmel-samd/common-hal/busio/UART.c:119 #: ports/atmel-samd/common-hal/busio/UART.c:119
#: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45 #: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45
#: ports/nrf/common-hal/busio/I2C.c:58 #: ports/nrf/common-hal/busio/I2C.c:77
msgid "Invalid pins" msgid "Invalid pins"
msgstr "Ungültige Pins" msgstr "Ungültige Pins"
@ -694,6 +694,20 @@ msgstr ""
msgid "AnalogOut functionality not supported" msgid "AnalogOut functionality not supported"
msgstr "" msgstr ""
#: ports/nrf/common-hal/busio/I2C.c:91
#, fuzzy
msgid "All I2C peripherals are in use"
msgstr "Alle timer werden benutzt"
#: ports/nrf/common-hal/busio/SPI.c:109
#, fuzzy
msgid "All SPI peripherals are in use"
msgstr "Alle timer werden benutzt"
#: ports/nrf/common-hal/busio/SPI.c:170
msgid "Baud rate too high for this SPI peripheral"
msgstr ""
#: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47 #: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47
#: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60 #: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60
#: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71 #: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-18 22:20-0400\n" "POT-Creation-Date: 2018-09-20 21:52-0400\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
@ -356,7 +356,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/busio/SPI.c:132 #: ports/atmel-samd/common-hal/busio/SPI.c:132
#: ports/atmel-samd/common-hal/busio/UART.c:119 #: ports/atmel-samd/common-hal/busio/UART.c:119
#: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45 #: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45
#: ports/nrf/common-hal/busio/I2C.c:58 #: ports/nrf/common-hal/busio/I2C.c:77
msgid "Invalid pins" msgid "Invalid pins"
msgstr "" msgstr ""
@ -685,6 +685,18 @@ msgstr ""
msgid "AnalogOut functionality not supported" msgid "AnalogOut functionality not supported"
msgstr "" msgstr ""
#: ports/nrf/common-hal/busio/I2C.c:91
msgid "All I2C peripherals are in use"
msgstr ""
#: ports/nrf/common-hal/busio/SPI.c:109
msgid "All SPI peripherals are in use"
msgstr ""
#: ports/nrf/common-hal/busio/SPI.c:170
msgid "Baud rate too high for this SPI peripheral"
msgstr ""
#: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47 #: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47
#: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60 #: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60
#: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71 #: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-18 22:20-0400\n" "POT-Creation-Date: 2018-09-20 21:52-0400\n"
"PO-Revision-Date: 2018-08-24 22:56-0500\n" "PO-Revision-Date: 2018-08-24 22:56-0500\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
@ -372,7 +372,7 @@ msgstr "No hay suficientes pines disponibles"
#: ports/atmel-samd/common-hal/busio/SPI.c:132 #: ports/atmel-samd/common-hal/busio/SPI.c:132
#: ports/atmel-samd/common-hal/busio/UART.c:119 #: ports/atmel-samd/common-hal/busio/UART.c:119
#: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45 #: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45
#: ports/nrf/common-hal/busio/I2C.c:58 #: ports/nrf/common-hal/busio/I2C.c:77
msgid "Invalid pins" msgid "Invalid pins"
msgstr "pines inválidos" msgstr "pines inválidos"
@ -703,6 +703,20 @@ msgstr ""
msgid "AnalogOut functionality not supported" msgid "AnalogOut functionality not supported"
msgstr "" msgstr ""
#: ports/nrf/common-hal/busio/I2C.c:91
#, fuzzy
msgid "All I2C peripherals are in use"
msgstr "Todos los timers estan siendo utilizados"
#: ports/nrf/common-hal/busio/SPI.c:109
#, fuzzy
msgid "All SPI peripherals are in use"
msgstr "Todos los timers estan siendo utilizados"
#: ports/nrf/common-hal/busio/SPI.c:170
msgid "Baud rate too high for this SPI peripheral"
msgstr ""
#: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47 #: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47
#: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60 #: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60
#: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71 #: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-18 22:20-0400\n" "POT-Creation-Date: 2018-09-20 21:52-0400\n"
"PO-Revision-Date: 2018-08-30 23:04-0700\n" "PO-Revision-Date: 2018-08-30 23:04-0700\n"
"Last-Translator: Timothy <me@timothygarcia.ca>\n" "Last-Translator: Timothy <me@timothygarcia.ca>\n"
"Language-Team: fil\n" "Language-Team: fil\n"
@ -368,7 +368,7 @@ msgstr "Hindi sapat ang magagamit na pins"
#: ports/atmel-samd/common-hal/busio/SPI.c:132 #: ports/atmel-samd/common-hal/busio/SPI.c:132
#: ports/atmel-samd/common-hal/busio/UART.c:119 #: ports/atmel-samd/common-hal/busio/UART.c:119
#: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45 #: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45
#: ports/nrf/common-hal/busio/I2C.c:58 #: ports/nrf/common-hal/busio/I2C.c:77
msgid "Invalid pins" msgid "Invalid pins"
msgstr "Mali ang pins" msgstr "Mali ang pins"
@ -700,6 +700,20 @@ msgstr "hindi alam na config param"
msgid "AnalogOut functionality not supported" msgid "AnalogOut functionality not supported"
msgstr "Hindi supportado ang AnalogOut" msgstr "Hindi supportado ang AnalogOut"
#: ports/nrf/common-hal/busio/I2C.c:91
#, fuzzy
msgid "All I2C peripherals are in use"
msgstr "Lahat ng timer ginagamit"
#: ports/nrf/common-hal/busio/SPI.c:109
#, fuzzy
msgid "All SPI peripherals are in use"
msgstr "Lahat ng timer ginagamit"
#: ports/nrf/common-hal/busio/SPI.c:170
msgid "Baud rate too high for this SPI peripheral"
msgstr ""
#: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47 #: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47
#: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60 #: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60
#: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71 #: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 0.1\n" "Project-Id-Version: 0.1\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-18 22:20-0400\n" "POT-Creation-Date: 2018-09-20 21:52-0400\n"
"PO-Revision-Date: 2018-08-14 11:01+0200\n" "PO-Revision-Date: 2018-08-14 11:01+0200\n"
"Last-Translator: Pierrick Couturier <arofarn@arofarn.info>\n" "Last-Translator: Pierrick Couturier <arofarn@arofarn.info>\n"
"Language-Team: fr\n" "Language-Team: fr\n"
@ -363,7 +363,7 @@ msgstr "Pas assez de broches disponibles"
#: ports/atmel-samd/common-hal/busio/SPI.c:132 #: ports/atmel-samd/common-hal/busio/SPI.c:132
#: ports/atmel-samd/common-hal/busio/UART.c:119 #: ports/atmel-samd/common-hal/busio/UART.c:119
#: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45 #: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45
#: ports/nrf/common-hal/busio/I2C.c:58 #: ports/nrf/common-hal/busio/I2C.c:77
msgid "Invalid pins" msgid "Invalid pins"
msgstr "Broche invalide" msgstr "Broche invalide"
@ -696,6 +696,20 @@ msgstr "paramètre de config. inconnu"
msgid "AnalogOut functionality not supported" msgid "AnalogOut functionality not supported"
msgstr "AnalogOut non supporté" msgstr "AnalogOut non supporté"
#: ports/nrf/common-hal/busio/I2C.c:91
#, fuzzy
msgid "All I2C peripherals are in use"
msgstr "Tous les timers sont utilisés"
#: ports/nrf/common-hal/busio/SPI.c:109
#, fuzzy
msgid "All SPI peripherals are in use"
msgstr "Tous les timers sont utilisés"
#: ports/nrf/common-hal/busio/SPI.c:170
msgid "Baud rate too high for this SPI peripheral"
msgstr ""
#: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47 #: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47
#: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60 #: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60
#: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71 #: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71
@ -2386,10 +2400,10 @@ msgstr "'S' et 'O' ne sont pas des types de format supportés"
msgid "too many arguments provided with the given format" msgid "too many arguments provided with the given format"
msgstr "trop d'arguments fournis avec ce format" msgstr "trop d'arguments fournis avec ce format"
#, fuzzy
#~ msgid "value_size must be power of two"
#~ msgstr "'len' doit être un multiple de 4"
#, fuzzy #, fuzzy
#~ msgid "palette must be displayio.Palette" #~ msgid "palette must be displayio.Palette"
#~ msgstr "la palette doit être longue de 32 octets" #~ msgstr "la palette doit être longue de 32 octets"
#, fuzzy
#~ msgid "value_size must be power of two"
#~ msgstr "'len' doit être un multiple de 4"

View File

@ -34,8 +34,27 @@
#include "nrfx_twim.h" #include "nrfx_twim.h"
#include "nrf_gpio.h" #include "nrf_gpio.h"
#include "nrfx_spim.h"
#include "nrf_gpio.h"
STATIC twim_peripheral_t twim_peripherals[] = {
#if NRFX_CHECK(NRFX_TWIM0_ENABLED)
// SPIM0 and TWIM0 share an address.
{ .twim = NRFX_TWIM_INSTANCE(0),
.in_use = false,
.max_xfer_size = TWIM0_EASYDMA_MAXCNT_SIZE,
},
#endif
#if NRFX_CHECK(NRFX_TWIM1_ENABLED)
// SPIM1 and TWIM1 share an address.
{ .twim = NRFX_TWIM_INSTANCE(1),
.in_use = false,
.max_xfer_size = TWIM1_EASYDMA_MAXCNT_SIZE,
},
#endif
};
#define INST_NO 0 #define INST_NO 0
#define MAX_XFER_SIZE ((1U << NRFX_CONCAT_3(TWIM, INST_NO, _EASYDMA_MAXCNT_SIZE)) - 1)
static uint8_t twi_error_to_mp(const nrfx_err_t err) { static uint8_t twi_error_to_mp(const nrfx_err_t err) {
switch (err) { switch (err) {
@ -54,11 +73,23 @@ static uint8_t twi_error_to_mp(const nrfx_err_t err) {
} }
void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) { void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) {
if (scl->number == sda->number) if (scl->number == sda->number) {
mp_raise_ValueError(translate("Invalid pins")); mp_raise_ValueError(translate("Invalid pins"));
}
const nrfx_twim_t instance = NRFX_TWIM_INSTANCE(INST_NO); // Find a free instance.
self->twim = instance; self->twim_peripheral = NULL;
for (size_t i = 0 ; i < MP_ARRAY_SIZE(twim_peripherals); i++) {
if (!twim_peripherals[i].in_use) {
self->twim_peripheral = &twim_peripherals[i];
self->twim_peripheral->in_use = true;
break;
}
}
if (self->twim_peripheral == NULL) {
mp_raise_ValueError(translate("All I2C peripherals are in use"));
}
nrfx_twim_config_t config = NRFX_TWIM_DEFAULT_CONFIG; nrfx_twim_config_t config = NRFX_TWIM_DEFAULT_CONFIG;
config.scl = scl->number; config.scl = scl->number;
@ -76,12 +107,12 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *
claim_pin(sda); claim_pin(sda);
claim_pin(scl); claim_pin(scl);
nrfx_err_t err = nrfx_twim_init(&self->twim, &config, NULL, NULL); nrfx_err_t err = nrfx_twim_init(&self->twim_peripheral->twim, &config, NULL, NULL);
// A soft reset doesn't uninit the driver so we might end up with a invalid state // A soft reset doesn't uninit the driver so we might end up with a invalid state
if (err == NRFX_ERROR_INVALID_STATE) { if (err == NRFX_ERROR_INVALID_STATE) {
nrfx_twim_uninit(&self->twim); nrfx_twim_uninit(&self->twim_peripheral->twim);
err = nrfx_twim_init(&self->twim, &config, NULL, NULL); err = nrfx_twim_init(&self->twim_peripheral->twim, &config, NULL, NULL);
} }
if (err != NRFX_SUCCESS) { if (err != NRFX_SUCCESS) {
@ -99,20 +130,22 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) {
if (common_hal_busio_i2c_deinited(self)) if (common_hal_busio_i2c_deinited(self))
return; return;
nrfx_twim_uninit(&self->twim); nrfx_twim_uninit(&self->twim_peripheral->twim);
reset_pin_number(self->sda_pin_number); reset_pin_number(self->sda_pin_number);
reset_pin_number(self->scl_pin_number); reset_pin_number(self->scl_pin_number);
self->sda_pin_number = NO_PIN; self->sda_pin_number = NO_PIN;
self->scl_pin_number = NO_PIN; self->scl_pin_number = NO_PIN;
self->twim_peripheral->in_use = false;
} }
// nrfx_twim_tx doesn't support 0-length data so we fall back to the hal API // nrfx_twim_tx doesn't support 0-length data so we fall back to the hal API
bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
NRF_TWIM_Type *reg = self->twim.p_twim; NRF_TWIM_Type *reg = self->twim_peripheral->twim.p_twim;
bool found = true; bool found = true;
nrfx_twim_enable(&self->twim); nrfx_twim_enable(&self->twim_peripheral->twim);
nrf_twim_address_set(reg, addr); nrf_twim_address_set(reg, addr);
nrf_twim_tx_buffer_set(reg, NULL, 0); nrf_twim_tx_buffer_set(reg, NULL, 0);
@ -135,19 +168,19 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
found = false; found = false;
} }
nrfx_twim_disable(&self->twim); nrfx_twim_disable(&self->twim_peripheral->twim);
return found; return found;
} }
bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) {
bool grabbed_lock = false; bool grabbed_lock = false;
// CRITICAL_SECTION_ENTER() // NRFX_CRITICAL_SECTION_ENTER();
if (!self->has_lock) { if (!self->has_lock) {
grabbed_lock = true; grabbed_lock = true;
self->has_lock = true; self->has_lock = true;
} }
// CRITICAL_SECTION_LEAVE(); // NRFX_CRITICAL_SECTION_EXIT();
return grabbed_lock; return grabbed_lock;
} }
@ -163,22 +196,23 @@ uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const u
if(len == 0) if(len == 0)
return common_hal_busio_i2c_probe(self, addr) ? 0 : MP_ENODEV; return common_hal_busio_i2c_probe(self, addr) ? 0 : MP_ENODEV;
const uint32_t parts = len / MAX_XFER_SIZE; const uint32_t max_xfer_size = self->twim_peripheral->max_xfer_size;
const uint32_t remainder = len % MAX_XFER_SIZE; const uint32_t parts = len / max_xfer_size;
const uint32_t remainder = len % max_xfer_size;
nrfx_err_t err = NRFX_SUCCESS; nrfx_err_t err = NRFX_SUCCESS;
nrfx_twim_enable(&self->twim); nrfx_twim_enable(&self->twim_peripheral->twim);
for (uint32_t i = 0; i < parts; ++i) { for (uint32_t i = 0; i < parts; ++i) {
err = nrfx_twim_tx(&self->twim, addr, data + i * MAX_XFER_SIZE, MAX_XFER_SIZE, !stopBit); err = nrfx_twim_tx(&self->twim_peripheral->twim, addr, data + i * max_xfer_size, max_xfer_size, !stopBit);
if (err != NRFX_SUCCESS) if (err != NRFX_SUCCESS)
break; break;
} }
if ((remainder > 0) && (err == NRFX_SUCCESS)) if ((remainder > 0) && (err == NRFX_SUCCESS))
err = nrfx_twim_tx(&self->twim, addr, data + parts * MAX_XFER_SIZE, remainder, !stopBit); err = nrfx_twim_tx(&self->twim_peripheral->twim, addr, data + parts * max_xfer_size, remainder, !stopBit);
nrfx_twim_disable(&self->twim); nrfx_twim_disable(&self->twim_peripheral->twim);
return twi_error_to_mp(err); return twi_error_to_mp(err);
} }
@ -187,22 +221,23 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t
if(len == 0) if(len == 0)
return 0; return 0;
const uint32_t parts = len / MAX_XFER_SIZE; const uint32_t max_xfer_size = self->twim_peripheral->max_xfer_size;
const uint32_t remainder = len % MAX_XFER_SIZE; const uint32_t parts = len / max_xfer_size;
const uint32_t remainder = len % max_xfer_size;
nrfx_err_t err = NRFX_SUCCESS; nrfx_err_t err = NRFX_SUCCESS;
nrfx_twim_enable(&self->twim); nrfx_twim_enable(&self->twim_peripheral->twim);
for (uint32_t i = 0; i < parts; ++i) { for (uint32_t i = 0; i < parts; ++i) {
err = nrfx_twim_rx(&self->twim, addr, data + i * MAX_XFER_SIZE, MAX_XFER_SIZE); err = nrfx_twim_rx(&self->twim_peripheral->twim, addr, data + i * max_xfer_size, max_xfer_size);
if (err != NRFX_SUCCESS) if (err != NRFX_SUCCESS)
break; break;
} }
if ((remainder > 0) && (err == NRFX_SUCCESS)) if ((remainder > 0) && (err == NRFX_SUCCESS))
err = nrfx_twim_rx(&self->twim, addr, data + parts * MAX_XFER_SIZE, remainder); err = nrfx_twim_rx(&self->twim_peripheral->twim, addr, data + parts * max_xfer_size, remainder);
nrfx_twim_disable(&self->twim); nrfx_twim_disable(&self->twim_peripheral->twim);
return twi_error_to_mp(err); return twi_error_to_mp(err);
} }

View File

@ -32,8 +32,14 @@
#include "py/obj.h" #include "py/obj.h"
typedef struct { typedef struct {
mp_obj_base_t base;
nrfx_twim_t twim; nrfx_twim_t twim;
bool in_use;
uint8_t max_xfer_size;
} twim_peripheral_t;
typedef struct {
mp_obj_base_t base;
twim_peripheral_t* twim_peripheral;
bool has_lock; bool has_lock;
uint8_t scl_pin_number; uint8_t scl_pin_number;
uint8_t sda_pin_number; uint8_t sda_pin_number;

View File

@ -27,40 +27,65 @@
#include "nrfx_spim.h" #include "nrfx_spim.h"
#include "nrf_gpio.h" #include "nrf_gpio.h"
#if NRFX_SPIM3_ENABLED STATIC spim_peripheral_t spim_peripherals[] = {
#define INST_NO 3 #if NRFX_CHECK(NRFX_SPIM3_ENABLED)
#else // SPIM3 exists only on nRF52840 and supports 32MHz max. All other SPIM's are only 8MHz max.
#define INST_NO 2 // Allocate SPIM3 first.
{ .spim = NRFX_SPIM_INSTANCE(3),
.max_frequency_MHz = 32,
.max_xfer_size = SPIM3_EASYDMA_MAXCNT_SIZE,
},
#endif #endif
#if NRFX_CHECK(NRFX_SPIM2_ENABLED)
#define MAX_XFER_SIZE ((1U << NRFX_CONCAT_3(SPIM, INST_NO, _EASYDMA_MAXCNT_SIZE)) - 1) // SPIM2 is not shared with a TWIM, so allocate before the shared ones.
{ .spim = NRFX_SPIM_INSTANCE(2),
.max_frequency_MHz = 8,
.max_xfer_size = SPIM2_EASYDMA_MAXCNT_SIZE,
},
#endif
#if NRFX_CHECK(NRFX_SPIM1_ENABLED)
// SPIM1 and TWIM1 share an address.
{ .spim = NRFX_SPIM_INSTANCE(1),
.max_frequency_MHz = 8,
.max_xfer_size = SPIM1_EASYDMA_MAXCNT_SIZE,
},
#endif
#if NRFX_CHECK(NRFX_SPIM0_ENABLED)
// SPIM0 and TWIM0 share an address.
{ .spim = NRFX_SPIM_INSTANCE(0),
.max_frequency_MHz = 8,
.max_xfer_size = SPIM0_EASYDMA_MAXCNT_SIZE,
},
#endif
};
// Convert frequency to clock-speed-dependent value // Convert frequency to clock-speed-dependent value
static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate) { static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate) {
if (baudrate <= 125000) if (baudrate <= 125000) {
return NRF_SPIM_FREQ_125K; return NRF_SPIM_FREQ_125K;
}
if (baudrate <= 250000) if (baudrate <= 250000) {
return NRF_SPIM_FREQ_250K; return NRF_SPIM_FREQ_250K;
}
if (baudrate <= 500000) if (baudrate <= 500000) {
return NRF_SPIM_FREQ_500K; return NRF_SPIM_FREQ_500K;
}
if (baudrate <= 1000000) if (baudrate <= 1000000) {
return NRF_SPIM_FREQ_1M; return NRF_SPIM_FREQ_1M;
}
if (baudrate <= 2000000) if (baudrate <= 2000000) {
return NRF_SPIM_FREQ_2M; return NRF_SPIM_FREQ_2M;
}
if (baudrate <= 4000000) if (baudrate <= 4000000) {
return NRF_SPIM_FREQ_4M; return NRF_SPIM_FREQ_4M;
}
if (baudrate <= 8000000) if (baudrate <= 8000000) {
return NRF_SPIM_FREQ_8M; return NRF_SPIM_FREQ_8M;
}
#ifdef SPIM_FREQUENCY_FREQUENCY_M16 #ifdef SPIM_FREQUENCY_FREQUENCY_M16
if (baudrate <= 16000000) if (baudrate <= 16000000) {
return NRF_SPIM_FREQ_16M; return NRF_SPIM_FREQ_16M;
}
#endif #endif
#ifdef SPIM_FREQUENCY_FREQUENCY_M32 #ifdef SPIM_FREQUENCY_FREQUENCY_M32
@ -71,8 +96,18 @@ static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate)
} }
void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, const mcu_pin_obj_t * miso) { void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, const mcu_pin_obj_t * miso) {
const nrfx_spim_t instance = NRFX_SPIM_INSTANCE(INST_NO); // Find a free instance.
self->spim = instance; self->spim_peripheral = NULL;
for (size_t i = 0 ; i < MP_ARRAY_SIZE(spim_peripherals); i++) {
if ((spim_peripherals[i].spim.p_reg->ENABLE & SPIM_ENABLE_ENABLE_Msk) == 0) {
self->spim_peripheral = &spim_peripherals[i];
break;
}
}
if (self->spim_peripheral == NULL) {
mp_raise_ValueError(translate("All SPI peripherals are in use"));
}
nrfx_spim_config_t config = NRFX_SPIM_DEFAULT_CONFIG; nrfx_spim_config_t config = NRFX_SPIM_DEFAULT_CONFIG;
config.frequency = NRF_SPIM_FREQ_8M; config.frequency = NRF_SPIM_FREQ_8M;
@ -97,12 +132,12 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *
self->MISO_pin_number = NO_PIN; self->MISO_pin_number = NO_PIN;
} }
nrfx_err_t err = nrfx_spim_init(&self->spim, &config, NULL, NULL); nrfx_err_t err = nrfx_spim_init(&self->spim_peripheral->spim, &config, NULL, NULL);
// A soft reset doesn't uninit the driver so we might end up with a invalid state // A soft reset doesn't uninit the driver so we might end up with a invalid state
if (err == NRFX_ERROR_INVALID_STATE) { if (err == NRFX_ERROR_INVALID_STATE) {
nrfx_spim_uninit(&self->spim); nrfx_spim_uninit(&self->spim_peripheral->spim);
err = nrfx_spim_init(&self->spim, &config, NULL, NULL); err = nrfx_spim_init(&self->spim_peripheral->spim, &config, NULL, NULL);
} }
if (err != NRFX_SUCCESS) { if (err != NRFX_SUCCESS) {
@ -119,7 +154,7 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
if (common_hal_busio_spi_deinited(self)) if (common_hal_busio_spi_deinited(self))
return; return;
nrfx_spim_uninit(&self->spim); nrfx_spim_uninit(&self->spim_peripheral->spim);
reset_pin_number(self->clock_pin_number); reset_pin_number(self->clock_pin_number);
reset_pin_number(self->MOSI_pin_number); reset_pin_number(self->MOSI_pin_number);
@ -131,7 +166,11 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, ui
if (bits != 8) if (bits != 8)
return false; return false;
nrf_spim_frequency_set(self->spim.p_reg, baudrate_to_spim_frequency(baudrate)); if (baudrate > self->spim_peripheral->max_frequency_MHz * 1000000) {
mp_raise_ValueError(translate("Baud rate too high for this SPI peripheral"));
return false;
}
nrf_spim_frequency_set(self->spim_peripheral->spim.p_reg, baudrate_to_spim_frequency(baudrate));
nrf_spim_mode_t mode = NRF_SPIM_MODE_0; nrf_spim_mode_t mode = NRF_SPIM_MODE_0;
if (polarity) { if (polarity) {
@ -140,19 +179,19 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, ui
mode = (phase) ? NRF_SPIM_MODE_1 : NRF_SPIM_MODE_0; mode = (phase) ? NRF_SPIM_MODE_1 : NRF_SPIM_MODE_0;
} }
nrf_spim_configure(self->spim.p_reg, mode, NRF_SPIM_BIT_ORDER_MSB_FIRST); nrf_spim_configure(self->spim_peripheral->spim.p_reg, mode, NRF_SPIM_BIT_ORDER_MSB_FIRST);
return true; return true;
} }
bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) {
bool grabbed_lock = false; bool grabbed_lock = false;
// CRITICAL_SECTION_ENTER() // NRFX_CRITICAL_SECTION_ENTER();
// if (!self->has_lock) { if (!self->has_lock) {
grabbed_lock = true; grabbed_lock = true;
self->has_lock = true; self->has_lock = true;
// } }
// CRITICAL_SECTION_LEAVE(); // NRFX_CRITICAL_SECTION_EXIT();
return grabbed_lock; return grabbed_lock;
} }
@ -168,18 +207,19 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self, const uint8_t *data, size
if (len == 0) if (len == 0)
return true; return true;
const uint32_t parts = len / MAX_XFER_SIZE; const uint32_t max_xfer_size = self->spim_peripheral->max_xfer_size;
const uint32_t remainder = len % MAX_XFER_SIZE; const uint32_t parts = len / max_xfer_size;
const uint32_t remainder = len % max_xfer_size;
for (uint32_t i = 0; i < parts; ++i) { for (uint32_t i = 0; i < parts; ++i) {
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX(data + i * MAX_XFER_SIZE, MAX_XFER_SIZE); const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX(data + i * max_xfer_size, max_xfer_size);
if (nrfx_spim_xfer(&self->spim, &xfer, 0) != NRFX_SUCCESS) if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
return false; return false;
} }
if (remainder > 0) { if (remainder > 0) {
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX(data + parts * MAX_XFER_SIZE, remainder); const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX(data + parts * max_xfer_size, remainder);
if (nrfx_spim_xfer(&self->spim, &xfer, 0) != NRFX_SUCCESS) if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
return false; return false;
} }
@ -190,18 +230,19 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len,
if (len == 0) if (len == 0)
return true; return true;
const uint32_t parts = len / MAX_XFER_SIZE; const uint32_t max_xfer_size = self->spim_peripheral->max_xfer_size;
const uint32_t remainder = len % MAX_XFER_SIZE; const uint32_t parts = len / max_xfer_size;
const uint32_t remainder = len % max_xfer_size;
for (uint32_t i = 0; i < parts; ++i) { for (uint32_t i = 0; i < parts; ++i) {
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX(data + i * MAX_XFER_SIZE, MAX_XFER_SIZE); const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX(data + i * max_xfer_size, max_xfer_size);
if (nrfx_spim_xfer(&self->spim, &xfer, 0) != NRFX_SUCCESS) if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
return false; return false;
} }
if (remainder > 0) { if (remainder > 0) {
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX(data + parts * MAX_XFER_SIZE, remainder); const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX(data + parts * max_xfer_size, remainder);
if (nrfx_spim_xfer(&self->spim, &xfer, 0) != NRFX_SUCCESS) if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
return false; return false;
} }
@ -212,20 +253,22 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
if (len == 0) if (len == 0)
return true; return true;
const uint32_t parts = len / MAX_XFER_SIZE;
const uint32_t remainder = len % MAX_XFER_SIZE; const uint32_t max_xfer_size = self->spim_peripheral->max_xfer_size;
const uint32_t parts = len / max_xfer_size;
const uint32_t remainder = len % max_xfer_size;
for (uint32_t i = 0; i < parts; ++i) { for (uint32_t i = 0; i < parts; ++i) {
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER(data_out + i * MAX_XFER_SIZE, MAX_XFER_SIZE, const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER(data_out + i * max_xfer_size, max_xfer_size,
data_in + i * MAX_XFER_SIZE, MAX_XFER_SIZE); data_in + i * max_xfer_size, max_xfer_size);
if (nrfx_spim_xfer(&self->spim, &xfer, 0) != NRFX_SUCCESS) if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
return false; return false;
} }
if (remainder > 0) { if (remainder > 0) {
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER(data_out + parts * MAX_XFER_SIZE, remainder, const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER(data_out + parts * max_xfer_size, remainder,
data_in + parts * MAX_XFER_SIZE, remainder); data_in + parts * max_xfer_size, remainder);
if (nrfx_spim_xfer(&self->spim, &xfer, 0) != NRFX_SUCCESS) if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
return false; return false;
} }
@ -233,7 +276,7 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
} }
uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self) { uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self) {
switch (self->spim.p_reg->FREQUENCY) { switch (self->spim_peripheral->spim.p_reg->FREQUENCY) {
case NRF_SPIM_FREQ_125K: case NRF_SPIM_FREQ_125K:
return 125000; return 125000;
case NRF_SPIM_FREQ_250K: case NRF_SPIM_FREQ_250K:

View File

@ -31,8 +31,14 @@
#include "py/obj.h" #include "py/obj.h"
typedef struct { typedef struct {
mp_obj_base_t base;
nrfx_spim_t spim; nrfx_spim_t spim;
uint8_t max_frequency_MHz;
uint8_t max_xfer_size;
} spim_peripheral_t;
typedef struct {
mp_obj_base_t base;
spim_peripheral_t* spim_peripheral;
bool has_lock; bool has_lock;
uint8_t clock_pin_number; uint8_t clock_pin_number;
uint8_t MOSI_pin_number; uint8_t MOSI_pin_number;

View File

@ -5,21 +5,40 @@
#define NRFX_POWER_ENABLED 1 #define NRFX_POWER_ENABLED 1
#define NRFX_POWER_CONFIG_IRQ_PRIORITY 7 #define NRFX_POWER_CONFIG_IRQ_PRIORITY 7
// Turn on nrfx supported workarounds for errata in Rev1/Rev2 of nRF52832
#ifdef NRF52832_XXAA
#define NRFX_SPIS_NRF52_ANOMALY_109_WORKAROUND_ENABLED 1
#endif
// Turn on nrfx supported workarounds for errata in Rev1 of nRF52840
#ifdef NRF52840_XXAA
#define NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED 1
#endif
// SPI // SPI
#define NRFX_SPIM_ENABLED 1 #define NRFX_SPIM_ENABLED 1
// TWIM0 and TWIM1 are the same peripherals as SPIM0 and SPIM1.
// The IRQ handlers for these peripherals are set up at compile time,
// so out of the box TWIM0/SPIM0 and TWIM1/SPIM1 cannot be shared
// between common-hal/busio/I2C.c and SPI.c.
// We could write an interrupt handler that checks whether it's
// being used for SPI or I2C, but perhaps two I2C's and 1-2 SPI's are good enough for now.
// Enable SPIM2 and SPIM3 (if available)
#define NRFX_SPIM2_ENABLED 1
#ifdef NRF52840_XXAA #ifdef NRF52840_XXAA
#define NRFX_SPIM3_ENABLED 1 #define NRFX_SPIM3_ENABLED 1
#else
#define NRFX_SPIM2_ENABLED 1
#endif #endif
#define NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY 7 #define NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY 7
#define NRFX_SPIM_MISO_PULL_CFG 1 #define NRFX_SPIM_MISO_PULL_CFG 1
// TWI aka. I2C // TWI aka. I2C; enable TWIM0 and TWIM1 (no conflict with SPIM choices)
#define NRFX_TWIM_ENABLED 1 #define NRFX_TWIM_ENABLED 1
#define NRFX_TWIM0_ENABLED 1 #define NRFX_TWIM0_ENABLED 1
#define NRFX_TWIM1_ENABLED 1
#define NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY 7 #define NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY 7
#define NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY NRF_TWIM_FREQ_400K #define NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY NRF_TWIM_FREQ_400K
@ -45,4 +64,4 @@
#define NRFX_PWM3_ENABLED 0 #define NRFX_PWM3_ENABLED 0
#endif #endif
#endif #endif // NRFX_CONFIG_H__