Skip to content

Commit 57ab4f1

Browse files
committed
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.
1 parent 9b4b655 commit 57ab4f1

File tree

1 file changed

+58
-84
lines changed
  • ports/stm/common-hal/busio

1 file changed

+58
-84
lines changed

ports/stm/common-hal/busio/SPI.c

Lines changed: 58 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -107,104 +107,78 @@ void spi_reset(void) {
107107
spi_clock_disable(ALL_CLOCKS & ~(never_reset_mask));
108108
}
109109

110-
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
110+
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) {
111+
for(size_t i = 0; i<sz; i++, table++) {
112+
if(periph_index == table->periph_index && pin == table->pin ) {
113+
return table;
114+
}
115+
}
116+
return NULL;
117+
}
118+
119+
//match pins to SPI objects
120+
STATIC int check_pins(busio_spi_obj_t *self,
111121
const mcu_pin_obj_t * sck, const mcu_pin_obj_t * mosi,
112122
const mcu_pin_obj_t * miso) {
113-
114-
//match pins to SPI objects
115-
SPI_TypeDef * SPIx;
123+
bool spi_taken = false;
116124

117125
uint8_t sck_len = MP_ARRAY_SIZE(mcu_spi_sck_list);
118126
uint8_t mosi_len = MP_ARRAY_SIZE(mcu_spi_mosi_list);
119127
uint8_t miso_len = MP_ARRAY_SIZE(mcu_spi_miso_list);
120-
bool spi_taken = false;
121128

122129
//SCK is not optional. MOSI and MISO are
130+
if (!sck) {
131+
mp_raise_ValueError(translate("Must provide SCK pin"));
132+
}
133+
134+
if (!miso && !mosi) {
135+
mp_raise_ValueError(translate("Must provide MISO or MOSI pin"));
136+
}
137+
138+
// Loop over each possibility for SCK. Check whether MISO and/or MOSI can be used on the same peripheral
123139
for (uint i = 0; i < sck_len; i++) {
124-
if (mcu_spi_sck_list[i].pin == sck) {
125-
//if both MOSI and MISO exist, loop search normally
126-
if ((mosi != NULL) && (miso != NULL)) {
127-
//MOSI
128-
for (uint j = 0; j < mosi_len; j++) {
129-
if (mcu_spi_mosi_list[j].pin == mosi) {
130-
//MISO
131-
for (uint k = 0; k < miso_len; k++) {
132-
if ((mcu_spi_miso_list[k].pin == miso) //everything needs the same index
133-
&& (mcu_spi_sck_list[i].periph_index == mcu_spi_mosi_list[j].periph_index)
134-
&& (mcu_spi_sck_list[i].periph_index == mcu_spi_miso_list[k].periph_index)) {
135-
//keep looking if the SPI is taken, edge case
136-
if (reserved_spi[mcu_spi_sck_list[i].periph_index - 1]) {
137-
spi_taken = true;
138-
continue;
139-
}
140-
//store pins if not
141-
self->sck = &mcu_spi_sck_list[i];
142-
self->mosi = &mcu_spi_mosi_list[j];
143-
self->miso = &mcu_spi_miso_list[k];
144-
break;
145-
}
146-
}
147-
if (self->sck != NULL) {
148-
break; // Multi-level break to pick lowest peripheral
149-
}
150-
}
151-
}
152-
if (self->sck != NULL) {
153-
break;
154-
}
155-
// if just MISO, reduce search
156-
} else if (miso != NULL) {
157-
for (uint j = 0; j < miso_len; j++) {
158-
if ((mcu_spi_miso_list[j].pin == miso) //only SCK and MISO need the same index
159-
&& (mcu_spi_sck_list[i].periph_index == mcu_spi_miso_list[j].periph_index)) {
160-
if (reserved_spi[mcu_spi_sck_list[i].periph_index - 1]) {
161-
spi_taken = true;
162-
continue;
163-
}
164-
self->sck = &mcu_spi_sck_list[i];
165-
self->mosi = NULL;
166-
self->miso = &mcu_spi_miso_list[j];
167-
break;
168-
}
169-
}
170-
if (self->sck != NULL) {
171-
break;
172-
}
173-
// if just MOSI, reduce search
174-
} else if (mosi != NULL) {
175-
for (uint j = 0; j < mosi_len; j++) {
176-
if ((mcu_spi_mosi_list[j].pin == mosi) //only SCK and MOSI need the same index
177-
&& (mcu_spi_sck_list[i].periph_index == mcu_spi_mosi_list[j].periph_index)) {
178-
if (reserved_spi[mcu_spi_sck_list[i].periph_index - 1]) {
179-
spi_taken = true;
180-
continue;
181-
}
182-
self->sck = &mcu_spi_sck_list[i];
183-
self->mosi = &mcu_spi_mosi_list[j];
184-
self->miso = NULL;
185-
break;
186-
}
187-
}
188-
if (self->sck != NULL) {
189-
break;
190-
}
191-
} else {
192-
//throw an error immediately
193-
mp_raise_ValueError(translate("Must provide MISO or MOSI pin"));
194-
}
140+
const mcu_periph_obj_t *mcu_spi_sck = &mcu_spi_sck_list[i];
141+
if (mcu_spi_sck->pin != sck) {
142+
continue;
143+
}
144+
145+
int periph_index = mcu_spi_sck->periph_index;
146+
147+
const mcu_periph_obj_t *mcu_spi_miso = NULL;
148+
if (miso && !(mcu_spi_miso = find_pin_function(mcu_spi_miso_list, miso_len, miso, periph_index))) {
149+
continue;
195150
}
151+
152+
const mcu_periph_obj_t *mcu_spi_mosi = NULL;
153+
if (mosi && !(mcu_spi_mosi = find_pin_function(mcu_spi_mosi_list, mosi_len, mosi, periph_index))) {
154+
continue;
155+
}
156+
157+
if (reserved_spi[periph_index-1]) {
158+
spi_taken = true;
159+
continue;
160+
}
161+
162+
self->sck = mcu_spi_sck;
163+
self->mosi = mcu_spi_mosi;
164+
self->miso = mcu_spi_miso;
165+
166+
return periph_index;
196167
}
197168

198-
//handle typedef selection, errors
199-
if (self->sck != NULL && (self->mosi != NULL || self->miso != NULL)) {
200-
SPIx = mcu_spi_banks[self->sck->periph_index - 1];
169+
if (spi_taken) {
170+
mp_raise_ValueError(translate("Hardware busy, try alternative pins"));
201171
} else {
202-
if (spi_taken) {
203-
mp_raise_ValueError(translate("Hardware busy, try alternative pins"));
204-
} else {
205-
mp_raise_ValueError(translate("Invalid SPI pin selection"));
206-
}
172+
mp_raise_ValueError(translate("Invalid SPI pin selection"));
207173
}
174+
}
175+
176+
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
177+
const mcu_pin_obj_t * sck, const mcu_pin_obj_t * mosi,
178+
const mcu_pin_obj_t * miso) {
179+
180+
int periph_index = check_pins(self, sck, mosi, miso);
181+
SPI_TypeDef * SPIx = mcu_spi_banks[periph_index - 1];
208182

209183
//Start GPIO for each pin
210184
GPIO_InitTypeDef GPIO_InitStruct = {0};

0 commit comments

Comments
 (0)