Skip to content

Commit bc581fb

Browse files
committed
Add-unidirectional-SPI
1 parent 1e56de0 commit bc581fb

File tree

4 files changed

+155
-112
lines changed

4 files changed

+155
-112
lines changed

ports/mimxrt10xx/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ endif
9393

9494
CFLAGS += $(INC) -Wall -Wno-cast-align -std=gnu11 -nostdlib $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT)
9595

96+
# Disable some warnings, as do most ports. NXP SDK causes undef, tinyusb causes cast-align
97+
CFLAGS += -Wno-undef -Wno-cast-align
98+
9699
CFLAGS += \
97100
-mthumb \
98101
-mapcs \

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

Lines changed: 145 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
* THE SOFTWARE.
2626
*/
2727

28-
//TODO
2928
#include "shared-bindings/busio/SPI.h"
3029
#include "py/mperrno.h"
3130
#include "py/runtime.h"
@@ -35,46 +34,10 @@
3534

3635
#include <stdio.h>
3736

38-
//bool never_reset_sercoms[SERCOM_INST_NUM];
39-
//
40-
//void never_reset_sercom(Sercom* sercom) {
41-
// // Reset all SERCOMs except the ones being used by on-board devices.
42-
// Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS;
43-
// for (int i = 0; i < SERCOM_INST_NUM; i++) {
44-
// if (sercom_instances[i] == sercom) {
45-
// never_reset_sercoms[i] = true;
46-
// break;
47-
// }
48-
// }
49-
//}
50-
//
51-
//void allow_reset_sercom(Sercom* sercom) {
52-
// // Reset all SERCOMs except the ones being used by on-board devices.
53-
// Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS;
54-
// for (int i = 0; i < SERCOM_INST_NUM; i++) {
55-
// if (sercom_instances[i] == sercom) {
56-
// never_reset_sercoms[i] = false;
57-
// break;
58-
// }
59-
// }
60-
//}
61-
//
62-
//void reset_sercoms(void) {
63-
// // Reset all SERCOMs except the ones being used by on-board devices.
64-
// Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS;
65-
// for (int i = 0; i < SERCOM_INST_NUM; i++) {
66-
// if (never_reset_sercoms[i]) {
67-
// continue;
68-
// }
69-
// #ifdef MICROPY_HW_APA102_SERCOM
70-
// if (sercom_instances[i] == MICROPY_HW_APA102_SERCOM) {
71-
// continue;
72-
// }
73-
// #endif
74-
// // SWRST is same for all modes of SERCOMs.
75-
// sercom_instances[i]->SPI.CTRLA.bit.SWRST = 1;
76-
// }
77-
//}
37+
//arrays use 0 based numbering: SPI1 is stored at index 0
38+
#define MAX_SPI 4
39+
STATIC bool reserved_spi[MAX_SPI];
40+
STATIC bool never_reset_spi[MAX_SPI];
7841

7942
static void config_periph_pin(const mcu_periph_obj_t *periph) {
8043
IOMUXC_SetPinMux(
@@ -97,115 +60,180 @@ static void config_periph_pin(const mcu_periph_obj_t *periph) {
9760

9861
#define LPSPI_MASTER_CLK_FREQ (CLOCK_GetFreq(kCLOCK_Usb1PllPfd0Clk) / (CLOCK_GetDiv(kCLOCK_LpspiDiv)))
9962

63+
void spi_reset(void) {
64+
for (int i = 0; i < MAX_SPI; i++) {
65+
reserved_spi[i] = false;
66+
}
67+
}
68+
10069
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
10170
const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi,
10271
const mcu_pin_obj_t *miso) {
10372

104-
// TODO: Allow none mosi or miso
73+
const uint32_t sck_count = MP_ARRAY_SIZE(mcu_spi_sck_list);
74+
const uint32_t miso_count = MP_ARRAY_SIZE(mcu_spi_miso_list);
75+
const uint32_t mosi_count = MP_ARRAY_SIZE(mcu_spi_mosi_list);
76+
bool spi_taken = false;
10577

106-
const uint32_t sck_count = sizeof(mcu_spi_sck_list) / sizeof(mcu_periph_obj_t);
107-
const uint32_t miso_count = sizeof(mcu_spi_miso_list) / sizeof(mcu_periph_obj_t);
108-
const uint32_t mosi_count = sizeof(mcu_spi_mosi_list) / sizeof(mcu_periph_obj_t);
109-
110-
for (uint32_t i = 0; i < sck_count; ++i) {
111-
if (mcu_spi_sck_list[i].pin != clock)
78+
for (uint i = 0; i < sck_count; i++) {
79+
if (mcu_spi_sck_list[i].pin != clock) {
11280
continue;
113-
114-
for (uint32_t j = 0; j < miso_count; ++j) {
115-
if (mcu_spi_miso_list[j].pin != miso)
116-
continue;
117-
118-
if (mcu_spi_miso_list[j].bank_idx != mcu_spi_sck_list[i].bank_idx)
119-
continue;
120-
121-
for (uint32_t k = 0; k < mosi_count; ++k) {
122-
if (mcu_spi_mosi_list[k].pin != mosi)
81+
}
82+
//if both MOSI and MISO exist, loop search normally
83+
if ((mosi != NULL) && (miso != NULL)) {
84+
for (uint j = 0; j < mosi_count; j++) {
85+
if ((mcu_spi_mosi_list[i].pin != mosi)
86+
|| (mcu_spi_sck_list[i].bank_idx != mcu_spi_mosi_list[j].bank_idx)){
12387
continue;
124-
125-
if (mcu_spi_mosi_list[k].bank_idx != mcu_spi_miso_list[j].bank_idx)
88+
}
89+
for (uint k = 0; k < miso_count; k++) {
90+
if ((mcu_spi_miso_list[k].pin != miso) //everything needs the same index
91+
|| (mcu_spi_sck_list[i].bank_idx != mcu_spi_miso_list[k].bank_idx)) {
92+
continue;
93+
}
94+
//keep looking if the SPI is taken, edge case
95+
if (reserved_spi[mcu_spi_sck_list[i].bank_idx - 1]) {
96+
spi_taken = true;
97+
continue;
98+
}
99+
//store pins if not
100+
self->clock = &mcu_spi_sck_list[i];
101+
self->mosi = &mcu_spi_mosi_list[j];
102+
self->miso = &mcu_spi_miso_list[k];
103+
break;
104+
}
105+
if (self->clock != NULL) {
106+
break; // Multi-level break to pick lowest peripheral
107+
}
108+
}
109+
if (self->clock != NULL) {
110+
break;
111+
}
112+
// if just MISO, reduce search
113+
} else if (miso != NULL) {
114+
for (uint j = 0; j < miso_count; j++) {
115+
if ((mcu_spi_miso_list[j].pin != miso) //only SCK and MISO need the same index
116+
|| (mcu_spi_sck_list[i].bank_idx != mcu_spi_miso_list[j].bank_idx)) {
126117
continue;
127-
128-
self->clock_pin = &mcu_spi_sck_list[i];
129-
self->miso_pin = &mcu_spi_miso_list[j];
130-
self->mosi_pin = &mcu_spi_mosi_list[k];
131-
118+
}
119+
if (reserved_spi[mcu_spi_sck_list[i].bank_idx - 1]) {
120+
spi_taken = true;
121+
continue;
122+
}
123+
self->clock = &mcu_spi_sck_list[i];
124+
self->mosi = NULL;
125+
self->miso = &mcu_spi_miso_list[j];
126+
break;
127+
}
128+
if (self->clock != NULL) {
129+
break;
130+
}
131+
// if just MOSI, reduce search
132+
} else if (mosi != NULL) {
133+
for (uint j = 0; j < mosi_count; j++) {
134+
if ((mcu_spi_mosi_list[j].pin != mosi) //only SCK and MOSI need the same index
135+
|| (mcu_spi_sck_list[i].bank_idx != mcu_spi_mosi_list[j].bank_idx)) {
136+
continue;
137+
}
138+
if (reserved_spi[mcu_spi_sck_list[i].bank_idx - 1]) {
139+
spi_taken = true;
140+
continue;
141+
}
142+
self->clock = &mcu_spi_sck_list[i];
143+
self->mosi = &mcu_spi_mosi_list[j];
144+
self->miso = NULL;
132145
break;
133146
}
147+
if (self->clock != NULL) {
148+
break;
149+
}
150+
} else {
151+
//throw an error immediately
152+
mp_raise_ValueError(translate("Must provide MISO or MOSI pin"));
134153
}
135154
}
136155

137-
if(self->clock_pin == NULL || self->mosi_pin == NULL || self->miso_pin == NULL) {
138-
mp_raise_RuntimeError(translate("Invalid SPI pin selection"));
156+
// for (uint32_t i = 0; i < sck_count; ++i) {
157+
// if (mcu_spi_sck_list[i].pin != clock)
158+
// continue;
159+
160+
// for (uint32_t j = 0; j < miso_count; ++j) {
161+
// if (mcu_spi_miso_list[j].pin != miso)
162+
// continue;
163+
164+
// if (mcu_spi_miso_list[j].bank_idx != mcu_spi_sck_list[i].bank_idx)
165+
// continue;
166+
167+
// for (uint32_t k = 0; k < mosi_count; ++k) {
168+
// if (mcu_spi_mosi_list[k].pin != mosi)
169+
// continue;
170+
171+
// if (mcu_spi_mosi_list[k].bank_idx != mcu_spi_miso_list[j].bank_idx)
172+
// continue;
173+
174+
// self->clock = &mcu_spi_sck_list[i];
175+
// self->miso_pin = &mcu_spi_miso_list[j];
176+
// self->mosi_pin = &mcu_spi_mosi_list[k];
177+
178+
// break;
179+
// }
180+
// }
181+
// }
182+
183+
if (self->clock != NULL && (self->mosi != NULL || self->miso != NULL)) {
184+
self->spi = mcu_spi_banks[self->clock->bank_idx - 1];
139185
} else {
140-
self->spi = mcu_spi_banks[self->clock_pin->bank_idx - 1];
186+
if (spi_taken) {
187+
mp_raise_ValueError(translate("Hardware busy, try alternative pins"));
188+
} else {
189+
mp_raise_ValueError(translate("Invalid SPI pin selection"));
190+
}
141191
}
142192

143-
config_periph_pin(self->mosi_pin);
144-
config_periph_pin(self->miso_pin);
145-
config_periph_pin(self->clock_pin);
193+
config_periph_pin(self->clock);
194+
if (self->mosi != NULL) {
195+
config_periph_pin(self->mosi);
196+
}
197+
if (self->miso != NULL) {
198+
config_periph_pin(self->miso);
199+
}
200+
reserved_spi[self->clock->bank_idx - 1] = true;
146201

147202
lpspi_master_config_t config = { 0 };
148203
LPSPI_MasterGetDefaultConfig(&config);
149204

150205
// Always start at 250khz which is what SD cards need. They are sensitive to
151206
// SPI bus noise before they are put into SPI mode.
152207
config.baudRate = 250000;
153-
154208
LPSPI_MasterInit(self->spi, &config, LPSPI_MASTER_CLK_FREQ);
155-
156209
LPSPI_Enable(self->spi, false);
157210
uint32_t tcrPrescaleValue;
158211
self->baudrate = LPSPI_MasterSetBaudRate(self->spi, config.baudRate, LPSPI_MASTER_CLK_FREQ, &tcrPrescaleValue);
159212
LPSPI_Enable(self->spi, true);
160213

161-
claim_pin(self->clock_pin->pin);
162-
163-
// if (mosi_none) {
164-
// self->MOSI_pin = NO_PIN;
165-
// } else {
166-
// gpio_set_pin_direction(mosi->number, GPIO_DIRECTION_OUT);
167-
// gpio_set_pin_pull_mode(mosi->number, GPIO_PULL_OFF);
168-
// gpio_set_pin_function(mosi->number, mosi_pinmux);
169-
// self->MOSI_pin = mosi->number;
170-
claim_pin(self->mosi_pin->pin);
171-
// }
172-
173-
// if (miso_none) {
174-
// self->MISO_pin = NO_PIN;
175-
// } else {
176-
// gpio_set_pin_direction(miso->number, GPIO_DIRECTION_IN);
177-
// gpio_set_pin_pull_mode(miso->number, GPIO_PULL_OFF);
178-
// gpio_set_pin_function(miso->number, miso_pinmux);
179-
// self->MISO_pin = miso->number;
180-
claim_pin(self->miso_pin->pin);
181-
// }
214+
claim_pin(self->clock->pin);
215+
if (self->mosi != NULL) {
216+
claim_pin(self->mosi->pin);
217+
}
218+
if (self->miso != NULL) {
219+
claim_pin(self->miso->pin);
220+
}
182221
}
183222

184223
void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) {
185-
// never_reset_sercom(self->spi_desc.dev.prvt);
186-
187-
// never_reset_pin_number(self->clock_pin);
188-
// never_reset_pin_number(self->MOSI_pin);
189-
// never_reset_pin_number(self->MISO_pin);
224+
// TODO
190225
}
191226

192227
bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
193-
return self->clock_pin == NULL;
228+
return self->clock == NULL;
194229
}
195230

196231
void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
197232
if (common_hal_busio_spi_deinited(self)) {
198233
return;
199234
}
200235

201-
// allow_reset_sercom(self->spi_desc.dev.prvt);
202-
203-
// spi_m_sync_disable(&self->spi_desc);
204-
// spi_m_sync_deinit(&self->spi_desc);
205-
// reset_pin_number(self->clock_pin);
206-
// reset_pin_number(self->MOSI_pin);
207-
// reset_pin_number(self->MISO_pin);
208-
self->clock_pin = NULL;
236+
self->clock = NULL;
209237
}
210238

211239
bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
@@ -260,6 +288,9 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self,
260288
if (len == 0) {
261289
return true;
262290
}
291+
if (self->mosi == NULL) {
292+
mp_raise_ValueError(translate("No MOSI Pin"));
293+
}
263294

264295
lpspi_transfer_t xfer = { 0 };
265296
xfer.txData = (uint8_t*)data;
@@ -278,6 +309,9 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self,
278309
if (len == 0) {
279310
return true;
280311
}
312+
if (self->miso == NULL) {
313+
mp_raise_ValueError(translate("No MISO Pin"));
314+
}
281315

282316
LPSPI_SetDummyData(self->spi, write_value);
283317

@@ -296,6 +330,9 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
296330
if (len == 0) {
297331
return true;
298332
}
333+
if (self->miso == NULL || self->mosi == NULL) {
334+
mp_raise_ValueError(translate("Missing MISO or MOSI Pin"));
335+
}
299336

300337
LPSPI_SetDummyData(self->spi, 0xFF);
301338

ports/mimxrt10xx/common-hal/busio/SPI.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ typedef struct {
3838
LPSPI_Type *spi;
3939
bool has_lock;
4040
uint32_t baudrate;
41-
const mcu_periph_obj_t *clock_pin;
42-
const mcu_periph_obj_t *mosi_pin;
43-
const mcu_periph_obj_t *miso_pin;
41+
const mcu_periph_obj_t *clock;
42+
const mcu_periph_obj_t *mosi;
43+
const mcu_periph_obj_t *miso;
4444
} busio_spi_obj_t;
4545

46+
void spi_reset(void);
47+
4648
#endif // MICROPY_INCLUDED_MIMXRT10XX_COMMON_HAL_BUSIO_SPI_H

ports/mimxrt10xx/supervisor/port.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "common-hal/pulseio/PulseOut.h"
4242
#include "common-hal/pulseio/PWMOut.h"
4343
#include "common-hal/rtc/RTC.h"
44+
#include "common-hal/busio/SPI.h"
4445

4546
#include "reset.h"
4647
#include "tick.h"
@@ -264,7 +265,7 @@ safe_mode_t port_init(void) {
264265
}
265266

266267
void reset_port(void) {
267-
//reset_sercoms();
268+
spi_reset();
268269

269270
#if CIRCUITPY_AUDIOIO
270271
audio_dma_reset();

0 commit comments

Comments
 (0)