Skip to content

Commit 4519dde

Browse files
authored
Merge pull request #2841 from hierophect/mimxrt-spi-oneway
mimxrt10xx: add one-directional SPI
2 parents 90625d1 + a133074 commit 4519dde

File tree

4 files changed

+131
-114
lines changed

4 files changed

+131
-114
lines changed

ports/mimxrt10xx/Makefile

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

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

96+
# TODO: add these when -Werror is applied
97+
# Disable some warnings, as do most ports. NXP SDK causes undef, tinyusb causes cast-align
98+
# CFLAGS += -Wno-undef -Wno-cast-align
99+
96100
CFLAGS += \
97101
-mthumb \
98102
-mapcs \

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

Lines changed: 120 additions & 110 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,48 +34,12 @@
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-
//}
78-
79-
static void config_periph_pin(const mcu_periph_obj_t *periph) {
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];
41+
42+
STATIC void config_periph_pin(const mcu_periph_obj_t *periph) {
8043
IOMUXC_SetPinMux(
8144
periph->pin->mux_reg, periph->mux_mode,
8245
periph->input_reg, periph->input_idx,
@@ -97,115 +60,153 @@ 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
105-
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);
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;
10977

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) {
132129
break;
133130
}
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;
145+
break;
146+
}
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+
if (self->clock != NULL && (self->mosi != NULL || self->miso != NULL)) {
157+
self->spi = mcu_spi_banks[self->clock->bank_idx - 1];
139158
} else {
140-
self->spi = mcu_spi_banks[self->clock_pin->bank_idx - 1];
159+
if (spi_taken) {
160+
mp_raise_ValueError(translate("Hardware busy, try alternative pins"));
161+
} else {
162+
mp_raise_ValueError(translate("Invalid SPI pin selection"));
163+
}
141164
}
142165

143-
config_periph_pin(self->mosi_pin);
144-
config_periph_pin(self->miso_pin);
145-
config_periph_pin(self->clock_pin);
166+
config_periph_pin(self->clock);
167+
if (self->mosi != NULL) {
168+
config_periph_pin(self->mosi);
169+
}
170+
if (self->miso != NULL) {
171+
config_periph_pin(self->miso);
172+
}
173+
reserved_spi[self->clock->bank_idx - 1] = true;
146174

147175
lpspi_master_config_t config = { 0 };
148176
LPSPI_MasterGetDefaultConfig(&config);
149177

150178
// Always start at 250khz which is what SD cards need. They are sensitive to
151179
// SPI bus noise before they are put into SPI mode.
152180
config.baudRate = 250000;
153-
154181
LPSPI_MasterInit(self->spi, &config, LPSPI_MASTER_CLK_FREQ);
155-
156182
LPSPI_Enable(self->spi, false);
157183
uint32_t tcrPrescaleValue;
158184
self->baudrate = LPSPI_MasterSetBaudRate(self->spi, config.baudRate, LPSPI_MASTER_CLK_FREQ, &tcrPrescaleValue);
159185
LPSPI_Enable(self->spi, true);
160186

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-
// }
187+
claim_pin(self->clock->pin);
188+
if (self->mosi != NULL) {
189+
claim_pin(self->mosi->pin);
190+
}
191+
if (self->miso != NULL) {
192+
claim_pin(self->miso->pin);
193+
}
182194
}
183195

184196
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);
197+
// TODO
190198
}
191199

192200
bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
193-
return self->clock_pin == NULL;
201+
return self->clock == NULL;
194202
}
195203

196204
void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
197205
if (common_hal_busio_spi_deinited(self)) {
198206
return;
199207
}
200208

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;
209+
self->clock = NULL;
209210
}
210211

211212
bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
@@ -260,6 +261,9 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self,
260261
if (len == 0) {
261262
return true;
262263
}
264+
if (self->mosi == NULL) {
265+
mp_raise_ValueError(translate("No MOSI Pin"));
266+
}
263267

264268
lpspi_transfer_t xfer = { 0 };
265269
xfer.txData = (uint8_t*)data;
@@ -278,6 +282,9 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self,
278282
if (len == 0) {
279283
return true;
280284
}
285+
if (self->miso == NULL) {
286+
mp_raise_ValueError(translate("No MISO Pin"));
287+
}
281288

282289
LPSPI_SetDummyData(self->spi, write_value);
283290

@@ -296,6 +303,9 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
296303
if (len == 0) {
297304
return true;
298305
}
306+
if (self->miso == NULL || self->mosi == NULL) {
307+
mp_raise_ValueError(translate("Missing MISO or MOSI Pin"));
308+
}
299309

300310
LPSPI_SetDummyData(self->spi, 0xFF);
301311

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

@@ -267,7 +268,7 @@ safe_mode_t port_init(void) {
267268
}
268269

269270
void reset_port(void) {
270-
//reset_sercoms();
271+
spi_reset();
271272

272273
#if CIRCUITPY_AUDIOIO
273274
audio_dma_reset();

0 commit comments

Comments
 (0)