Skip to content

Commit 66c09ef

Browse files
committed
Add UART one-way instance search, fix bugs in stm32 implementation
1 parent 916ca9f commit 66c09ef

File tree

4 files changed

+159
-100
lines changed

4 files changed

+159
-100
lines changed

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,22 +91,22 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
9191
|| (mcu_spi_sck_list[i].bank_idx != mcu_spi_miso_list[k].bank_idx)) {
9292
continue;
9393
}
94-
//keep looking if the SPI is taken, edge case
94+
// if SPI is taken, break (pins never have >1 periph)
9595
if (reserved_spi[mcu_spi_sck_list[i].bank_idx - 1]) {
9696
spi_taken = true;
97-
continue;
97+
break;
9898
}
9999
//store pins if not
100100
self->clock = &mcu_spi_sck_list[i];
101101
self->mosi = &mcu_spi_mosi_list[j];
102102
self->miso = &mcu_spi_miso_list[k];
103103
break;
104104
}
105-
if (self->clock != NULL) {
105+
if (self->clock != NULL || spi_taken) {
106106
break; // Multi-level break to pick lowest peripheral
107107
}
108108
}
109-
if (self->clock != NULL) {
109+
if (self->clock != NULL || spi_taken) {
110110
break;
111111
}
112112
// if just MISO, reduce search
@@ -118,14 +118,13 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
118118
}
119119
if (reserved_spi[mcu_spi_sck_list[i].bank_idx - 1]) {
120120
spi_taken = true;
121-
continue;
121+
break;
122122
}
123123
self->clock = &mcu_spi_sck_list[i];
124-
self->mosi = NULL;
125124
self->miso = &mcu_spi_miso_list[j];
126125
break;
127126
}
128-
if (self->clock != NULL) {
127+
if (self->clock != NULL || spi_taken) {
129128
break;
130129
}
131130
// if just MOSI, reduce search
@@ -137,14 +136,13 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
137136
}
138137
if (reserved_spi[mcu_spi_sck_list[i].bank_idx - 1]) {
139138
spi_taken = true;
140-
continue;
139+
break;
141140
}
142141
self->clock = &mcu_spi_sck_list[i];
143142
self->mosi = &mcu_spi_mosi_list[j];
144-
self->miso = NULL;
145143
break;
146144
}
147-
if (self->clock != NULL) {
145+
if (self->clock != NULL || spi_taken) {
148146
break;
149147
}
150148
} else {

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

Lines changed: 137 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@
3939

4040
#include "fsl_lpuart.h"
4141

42-
// TODO
42+
//arrays use 0 based numbering: UART is stored at index 0
43+
#define MAX_UART 8
44+
STATIC bool reserved_uart[MAX_UART];
4345

4446
#define UART_CLOCK_FREQ (CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6U) / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U)
4547

@@ -79,126 +81,180 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
7981
mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer,
8082
bool sigint_enabled) {
8183

82-
// TODO: Allow none rx or tx
83-
84-
bool have_tx = tx != NULL;
85-
bool have_rx = rx != NULL;
86-
if (!have_tx && !have_rx) {
87-
mp_raise_ValueError(translate("tx and rx cannot both be None"));
88-
}
89-
9084
self->baudrate = baudrate;
9185
self->character_bits = bits;
9286
self->timeout_ms = timeout * 1000;
9387

94-
const uint32_t rx_count = sizeof(mcu_uart_rx_list) / sizeof(mcu_periph_obj_t);
95-
const uint32_t tx_count = sizeof(mcu_uart_tx_list) / sizeof(mcu_periph_obj_t);
88+
bool is_onedirection = false;
89+
if (!rx != !tx) {
90+
is_onedirection = true;
91+
}
92+
bool uart_taken = false;
9693

97-
for (uint32_t i = 0; i < rx_count; ++i) {
98-
if (mcu_uart_rx_list[i].pin != rx)
99-
continue;
94+
const uint32_t rx_count = MP_ARRAY_SIZE(mcu_uart_rx_list);
95+
const uint32_t tx_count = MP_ARRAY_SIZE(mcu_uart_tx_list);
10096

101-
for (uint32_t j = 0; j < tx_count; ++j) {
102-
if (mcu_uart_tx_list[j].pin != tx)
97+
// RX loop handles rx only, or both rx and tx
98+
if (rx != NULL) {
99+
for (uint32_t i = 0; i < rx_count; ++i) {
100+
if (mcu_uart_rx_list[i].pin != rx) {
103101
continue;
104-
105-
if (mcu_uart_tx_list[j].bank_idx != mcu_uart_rx_list[i].bank_idx)
102+
}
103+
// If TX is on, keep looking, else stop
104+
if (tx != NULL) {
105+
for (uint32_t j = 0; j < tx_count; ++j) {
106+
if (mcu_uart_tx_list[j].pin != tx ||
107+
mcu_uart_tx_list[j].bank_idx != mcu_uart_rx_list[i].bank_idx) {
108+
continue;
109+
}
110+
// If UART is taken, break (pins never have >1 periph)
111+
if (reserved_uart[mcu_uart_rx_list[i].bank_idx - 1]) {
112+
uart_taken = true;
113+
break;
114+
}
115+
self->rx = &mcu_uart_rx_list[i];
116+
self->tx = &mcu_uart_tx_list[j];
117+
break;
118+
}
119+
if (self->tx != NULL || uart_taken) {
120+
break;
121+
}
122+
} else {
123+
if (reserved_uart[mcu_uart_rx_list[i].bank_idx - 1]) {
124+
uart_taken = true;
125+
break;
126+
}
127+
self->rx = &mcu_uart_rx_list[i];
128+
}
129+
}
130+
} else if (tx != NULL) {
131+
// TX only case
132+
for (uint32_t i = 0; i < tx_count; ++i) {
133+
if (mcu_uart_tx_list[i].pin != tx) {
106134
continue;
107-
108-
self->rx_pin = &mcu_uart_rx_list[i];
109-
self->tx_pin = &mcu_uart_tx_list[j];
110-
135+
}
136+
if (reserved_uart[mcu_uart_tx_list[i].bank_idx - 1]) {
137+
uart_taken = true;
138+
break;
139+
}
140+
self->tx = &mcu_uart_tx_list[i];
111141
break;
112142
}
143+
} else {
144+
mp_raise_ValueError(translate("Supply at least one UART pin"));
145+
}
146+
147+
if (uart_taken) {
148+
mp_raise_RuntimeError(translate("UART peripheral is already in use"));
113149
}
114150

115-
if(self->rx_pin == NULL || self->tx_pin == NULL) {
151+
if(self->rx == NULL && self->tx == NULL) {
116152
mp_raise_RuntimeError(translate("Invalid UART pin selection"));
117153
}
118154

155+
if (is_onedirection && ((rts != NULL) || (cts != NULL))) {
156+
mp_raise_RuntimeError(translate("Both RX and TX required for flow control"));
157+
}
158+
119159
// Filter for sane settings for RS485
120160
if (rs485_dir != NULL) {
121-
if ((rts != NULL) || (cts != NULL)) {
122-
mp_raise_ValueError(translate("Cannot specify RTS or CTS in RS485 mode"));
123-
}
124-
// For IMXRT the RTS pin is used for RS485 direction
125-
rts = rs485_dir;
161+
if ((rts != NULL) || (cts != NULL)) {
162+
mp_raise_ValueError(translate("Cannot specify RTS or CTS in RS485 mode"));
163+
}
164+
// For IMXRT the RTS pin is used for RS485 direction
165+
rts = rs485_dir;
126166
}
127167
else {
128-
if (rs485_invert) {
129-
mp_raise_ValueError(translate("RS485 inversion specified when not in RS485 mode"));
130-
}
168+
if (rs485_invert) {
169+
mp_raise_ValueError(translate("RS485 inversion specified when not in RS485 mode"));
170+
}
131171
}
132172

133173
// Now check for RTS/CTS (or overloaded RS485 direction) pin(s)
134-
const uint32_t rts_count = sizeof(mcu_uart_rts_list) / sizeof(mcu_periph_obj_t);
135-
const uint32_t cts_count = sizeof(mcu_uart_cts_list) / sizeof(mcu_periph_obj_t);
174+
const uint32_t rts_count = MP_ARRAY_SIZE(mcu_uart_rts_list);
175+
const uint32_t cts_count = MP_ARRAY_SIZE(mcu_uart_cts_list);
136176

137177
if (rts != NULL) {
138-
for (uint32_t i=0; i < rts_count; ++i) {
139-
if (mcu_uart_rts_list[i].bank_idx == self->rx_pin->bank_idx) {
140-
if (mcu_uart_rts_list[i].pin == rts) {
141-
self->rts_pin = &mcu_uart_rts_list[i];
142-
break;
143-
}
178+
for (uint32_t i=0; i < rts_count; ++i) {
179+
if (mcu_uart_rts_list[i].bank_idx == self->rx->bank_idx) {
180+
if (mcu_uart_rts_list[i].pin == rts) {
181+
self->rts = &mcu_uart_rts_list[i];
182+
break;
183+
}
184+
}
185+
}
186+
if (self->rts == NULL){
187+
mp_raise_ValueError(translate("Selected RTS pin not valid"));
144188
}
145-
}
146-
if (self->rts_pin == NULL)
147-
mp_raise_ValueError(translate("Selected RTS pin not valid"));
148189
}
149190

150191
if (cts != NULL) {
151-
for (uint32_t i=0; i < cts_count; ++i) {
152-
if (mcu_uart_cts_list[i].bank_idx == self->rx_pin->bank_idx) {
153-
if (mcu_uart_cts_list[i].pin == cts) {
154-
self->cts_pin = &mcu_uart_cts_list[i];
155-
break;
156-
}
192+
for (uint32_t i=0; i < cts_count; ++i) {
193+
if (mcu_uart_cts_list[i].bank_idx == self->rx->bank_idx) {
194+
if (mcu_uart_cts_list[i].pin == cts) {
195+
self->cts = &mcu_uart_cts_list[i];
196+
break;
197+
}
198+
}
199+
}
200+
if (self->cts == NULL){
201+
mp_raise_ValueError(translate("Selected CTS pin not valid"));
157202
}
158-
}
159-
if (self->cts_pin == NULL)
160-
mp_raise_ValueError(translate("Selected CTS pin not valid"));
161203
}
162204

163-
self->uart = mcu_uart_banks[self->tx_pin->bank_idx - 1];
205+
if (self->rx) {
206+
self->uart = mcu_uart_banks[self->rx->bank_idx - 1];
207+
} else {
208+
self->uart = mcu_uart_banks[self->tx->bank_idx - 1];
209+
}
164210

165-
config_periph_pin(self->rx_pin);
166-
config_periph_pin(self->tx_pin);
167-
if (self->rts_pin)
168-
config_periph_pin(self->rts_pin);
169-
if (self->cts_pin)
170-
config_periph_pin(self->cts_pin);
211+
if (self->rx) {
212+
config_periph_pin(self->rx);
213+
}
214+
if (self->tx) {
215+
config_periph_pin(self->tx);
216+
}
217+
if (self->rts) {
218+
config_periph_pin(self->rts);
219+
}
220+
if (self->cts) {
221+
config_periph_pin(self->cts);
222+
}
171223

172224
lpuart_config_t config = { 0 };
173225
LPUART_GetDefaultConfig(&config);
174226

175227
config.dataBitsCount = self->character_bits == 8 ? kLPUART_EightDataBits : kLPUART_SevenDataBits;
176228
config.baudRate_Bps = self->baudrate;
177-
config.enableTx = self->tx_pin != NULL;
178-
config.enableRx = self->rx_pin != NULL;
179-
config.enableRxRTS = self->rts_pin != NULL;
180-
config.enableTxCTS = self->cts_pin != NULL;
181-
if (self->rts_pin != NULL)
182-
claim_pin(self->rts_pin->pin);
183-
if (self->cts_pin != NULL)
184-
claim_pin(self->cts_pin->pin);
229+
config.enableTx = self->tx != NULL;
230+
config.enableRx = self->rx != NULL;
231+
config.enableRxRTS = self->rts != NULL;
232+
config.enableTxCTS = self->cts != NULL;
233+
if (self->rts != NULL) {
234+
claim_pin(self->rts->pin);
235+
}
236+
if (self->cts != NULL) {
237+
claim_pin(self->cts->pin);
238+
}
185239

186240
LPUART_Init(self->uart, &config, UART_CLOCK_FREQ);
187241

188242
// Before we init, setup RS485 direction pin
189243
// ..unfortunately this isn't done by the driver library
190244
uint32_t modir = (self->uart->MODIR) & ~(LPUART_MODIR_TXRTSPOL_MASK | LPUART_MODIR_TXRTSE_MASK);
191245
if (rs485_dir != NULL) {
192-
modir |= LPUART_MODIR_TXRTSE_MASK;
193-
if (rs485_invert)
194-
modir |= LPUART_MODIR_TXRTSPOL_MASK;
246+
modir |= LPUART_MODIR_TXRTSE_MASK;
247+
if (rs485_invert) {
248+
modir |= LPUART_MODIR_TXRTSPOL_MASK;
249+
}
195250
}
196251
self->uart->MODIR = modir;
197252

198-
if (self->tx_pin != NULL)
199-
claim_pin(self->tx_pin->pin);
253+
if (self->tx != NULL) {
254+
claim_pin(self->tx->pin);
255+
}
200256

201-
if (self->rx_pin != NULL) {
257+
if (self->rx != NULL) {
202258
// The LPUART ring buffer wastes one byte to distinguish between full and empty.
203259
self->ringbuf = gc_alloc(receiver_buffer_size + 1, false, true /*long-lived*/);
204260

@@ -212,12 +268,12 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
212268
// the capacity is one less than the size.
213269
LPUART_TransferStartRingBuffer(self->uart, &self->handle, self->ringbuf, receiver_buffer_size + 1);
214270

215-
claim_pin(self->rx_pin->pin);
271+
claim_pin(self->rx->pin);
216272
}
217273
}
218274

219275
bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) {
220-
return self->rx_pin == NULL && self->tx_pin == NULL;
276+
return self->rx == NULL && self->tx == NULL;
221277
}
222278

223279
void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
@@ -229,16 +285,16 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
229285

230286
gc_free(self->ringbuf);
231287

232-
// reset_pin_number(self->rx_pin);
233-
// reset_pin_number(self->tx_pin);
288+
// reset_pin_number(self->rx);
289+
// reset_pin_number(self->tx);
234290

235-
self->rx_pin = NULL;
236-
self->tx_pin = NULL;
291+
self->rx = NULL;
292+
self->tx = NULL;
237293
}
238294

239295
// Read characters.
240296
size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t len, int *errcode) {
241-
if (self->rx_pin == NULL) {
297+
if (self->rx == NULL) {
242298
mp_raise_ValueError(translate("No RX pin"));
243299
}
244300

@@ -284,7 +340,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
284340

285341
// Write characters.
286342
size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, size_t len, int *errcode) {
287-
if (self->tx_pin == NULL) {
343+
if (self->tx == NULL) {
288344
mp_raise_ValueError(translate("No TX pin"));
289345
}
290346

@@ -320,7 +376,7 @@ void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
320376
}
321377

322378
bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) {
323-
if (self->tx_pin == NULL) {
379+
if (self->tx == NULL) {
324380
return false;
325381
}
326382

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ typedef struct {
4545
uint32_t baudrate;
4646
uint8_t character_bits;
4747
uint32_t timeout_ms;
48-
const mcu_periph_obj_t *rx_pin;
49-
const mcu_periph_obj_t *tx_pin;
50-
const mcu_periph_obj_t *cts_pin;
51-
const mcu_periph_obj_t *rts_pin;
48+
const mcu_periph_obj_t *rx;
49+
const mcu_periph_obj_t *tx;
50+
const mcu_periph_obj_t *cts;
51+
const mcu_periph_obj_t *rts;
5252
} busio_uart_obj_t;
5353

5454
#endif // MICROPY_INCLUDED_MIMXRT10XX_COMMON_HAL_BUSIO_UART_H

0 commit comments

Comments
 (0)