From 57ab4f1329f61844409735189a482359d7d4b7a7 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 24 Jun 2020 11:28:28 -0500 Subject: [PATCH 1/2] stm: SPI: revamp pin search code I discussed with Hierophect on Discord about how to "de-nest" the code for configuring SPI objects on STM, because the problems with one nesting level per pin becomes unmanageable with the up to 10 pins of SDIO. This code (which is only compile-tested so far) demonstrates the concept we discussed. The SCK pin is always required. Loop over all possibilities of the SCK pin. When we are considering a particular item in the mcu_spi_sck_list we have now become committed to using a particular periph_index. If all the other pins can be satisfied by that periph_index, then we have a working combination. Once we have a working combination that is not reserved, we can return that combination. On reaching the end, we have checked all the possible possibilities and can give the same errors as before: One if there was a possibility that worked but was reserved; and another if no possibility worked. --- ports/stm/common-hal/busio/SPI.c | 148 +++++++++++++------------------ 1 file changed, 61 insertions(+), 87 deletions(-) diff --git a/ports/stm/common-hal/busio/SPI.c b/ports/stm/common-hal/busio/SPI.c index c76705cd85..d4dd6cb3fc 100644 --- a/ports/stm/common-hal/busio/SPI.c +++ b/ports/stm/common-hal/busio/SPI.c @@ -107,105 +107,79 @@ void spi_reset(void) { spi_clock_disable(ALL_CLOCKS & ~(never_reset_mask)); } -void common_hal_busio_spi_construct(busio_spi_obj_t *self, +STATIC const mcu_periph_obj_t *find_pin_function(const mcu_periph_obj_t *table, size_t sz, const mcu_pin_obj_t *pin, int periph_index) { + for(size_t i = 0; iperiph_index && pin == table->pin ) { + return table; + } + } + return NULL; +} + +//match pins to SPI objects +STATIC int check_pins(busio_spi_obj_t *self, const mcu_pin_obj_t * sck, const mcu_pin_obj_t * mosi, const mcu_pin_obj_t * miso) { - - //match pins to SPI objects - SPI_TypeDef * SPIx; + bool spi_taken = false; uint8_t sck_len = MP_ARRAY_SIZE(mcu_spi_sck_list); uint8_t mosi_len = MP_ARRAY_SIZE(mcu_spi_mosi_list); uint8_t miso_len = MP_ARRAY_SIZE(mcu_spi_miso_list); - bool spi_taken = false; //SCK is not optional. MOSI and MISO are - for (uint i = 0; i < sck_len; i++) { - if (mcu_spi_sck_list[i].pin == sck) { - //if both MOSI and MISO exist, loop search normally - if ((mosi != NULL) && (miso != NULL)) { - //MOSI - for (uint j = 0; j < mosi_len; j++) { - if (mcu_spi_mosi_list[j].pin == mosi) { - //MISO - for (uint k = 0; k < miso_len; k++) { - if ((mcu_spi_miso_list[k].pin == miso) //everything needs the same index - && (mcu_spi_sck_list[i].periph_index == mcu_spi_mosi_list[j].periph_index) - && (mcu_spi_sck_list[i].periph_index == mcu_spi_miso_list[k].periph_index)) { - //keep looking if the SPI is taken, edge case - if (reserved_spi[mcu_spi_sck_list[i].periph_index - 1]) { - spi_taken = true; - continue; - } - //store pins if not - self->sck = &mcu_spi_sck_list[i]; - self->mosi = &mcu_spi_mosi_list[j]; - self->miso = &mcu_spi_miso_list[k]; - break; - } - } - if (self->sck != NULL) { - break; // Multi-level break to pick lowest peripheral - } - } - } - if (self->sck != NULL) { - break; - } - // if just MISO, reduce search - } else if (miso != NULL) { - for (uint j = 0; j < miso_len; j++) { - if ((mcu_spi_miso_list[j].pin == miso) //only SCK and MISO need the same index - && (mcu_spi_sck_list[i].periph_index == mcu_spi_miso_list[j].periph_index)) { - if (reserved_spi[mcu_spi_sck_list[i].periph_index - 1]) { - spi_taken = true; - continue; - } - self->sck = &mcu_spi_sck_list[i]; - self->mosi = NULL; - self->miso = &mcu_spi_miso_list[j]; - break; - } - } - if (self->sck != NULL) { - break; - } - // if just MOSI, reduce search - } else if (mosi != NULL) { - for (uint j = 0; j < mosi_len; j++) { - if ((mcu_spi_mosi_list[j].pin == mosi) //only SCK and MOSI need the same index - && (mcu_spi_sck_list[i].periph_index == mcu_spi_mosi_list[j].periph_index)) { - if (reserved_spi[mcu_spi_sck_list[i].periph_index - 1]) { - spi_taken = true; - continue; - } - self->sck = &mcu_spi_sck_list[i]; - self->mosi = &mcu_spi_mosi_list[j]; - self->miso = NULL; - break; - } - } - if (self->sck != NULL) { - break; - } - } else { - //throw an error immediately - mp_raise_ValueError(translate("Must provide MISO or MOSI pin")); - } - } + if (!sck) { + mp_raise_ValueError(translate("Must provide SCK pin")); } - //handle typedef selection, errors - if (self->sck != NULL && (self->mosi != NULL || self->miso != NULL)) { - SPIx = mcu_spi_banks[self->sck->periph_index - 1]; - } else { - if (spi_taken) { - mp_raise_ValueError(translate("Hardware busy, try alternative pins")); - } else { - mp_raise_ValueError(translate("Invalid SPI pin selection")); - } + if (!miso && !mosi) { + mp_raise_ValueError(translate("Must provide MISO or MOSI pin")); } + // Loop over each possibility for SCK. Check whether MISO and/or MOSI can be used on the same peripheral + for (uint i = 0; i < sck_len; i++) { + const mcu_periph_obj_t *mcu_spi_sck = &mcu_spi_sck_list[i]; + if (mcu_spi_sck->pin != sck) { + continue; + } + + int periph_index = mcu_spi_sck->periph_index; + + const mcu_periph_obj_t *mcu_spi_miso = NULL; + if (miso && !(mcu_spi_miso = find_pin_function(mcu_spi_miso_list, miso_len, miso, periph_index))) { + continue; + } + + const mcu_periph_obj_t *mcu_spi_mosi = NULL; + if (mosi && !(mcu_spi_mosi = find_pin_function(mcu_spi_mosi_list, mosi_len, mosi, periph_index))) { + continue; + } + + if (reserved_spi[periph_index-1]) { + spi_taken = true; + continue; + } + + self->sck = mcu_spi_sck; + self->mosi = mcu_spi_mosi; + self->miso = mcu_spi_miso; + + return periph_index; + } + + if (spi_taken) { + mp_raise_ValueError(translate("Hardware busy, try alternative pins")); + } else { + mp_raise_ValueError(translate("Invalid SPI pin selection")); + } +} + +void common_hal_busio_spi_construct(busio_spi_obj_t *self, + const mcu_pin_obj_t * sck, const mcu_pin_obj_t * mosi, + const mcu_pin_obj_t * miso) { + + int periph_index = check_pins(self, sck, mosi, miso); + SPI_TypeDef * SPIx = mcu_spi_banks[periph_index - 1]; + //Start GPIO for each pin GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = pin_mask(sck->number); From 959b4da9bbaf48e10707b1a5859f7cc4c5ee0b84 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 7 Jul 2020 14:38:34 -0500 Subject: [PATCH 2/2] make translate --- locale/circuitpython.pot | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 6e32ebab98..f3c9d04113 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-07-02 15:29+0200\n" +"POT-Creation-Date: 2020-07-07 14:38-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -1092,6 +1092,10 @@ msgstr "" msgid "Must provide MISO or MOSI pin" msgstr "" +#: ports/stm/common-hal/busio/SPI.c +msgid "Must provide SCK pin" +msgstr "" + #: shared-bindings/rgbmatrix/RGBMatrix.c #, c-format msgid "Must use a multiple of 6 rgb pins, not %d"