diff --git a/ports/mimxrt10xx/common-hal/busio/SPI.c b/ports/mimxrt10xx/common-hal/busio/SPI.c index 15c320140a..54c8d001db 100644 --- a/ports/mimxrt10xx/common-hal/busio/SPI.c +++ b/ports/mimxrt10xx/common-hal/busio/SPI.c @@ -91,10 +91,10 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, || (mcu_spi_sck_list[i].bank_idx != mcu_spi_miso_list[k].bank_idx)) { continue; } - //keep looking if the SPI is taken, edge case + // if SPI is taken, break (pins never have >1 periph) if (reserved_spi[mcu_spi_sck_list[i].bank_idx - 1]) { spi_taken = true; - continue; + break; } //store pins if not self->clock = &mcu_spi_sck_list[i]; @@ -102,11 +102,11 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, self->miso = &mcu_spi_miso_list[k]; break; } - if (self->clock != NULL) { + if (self->clock != NULL || spi_taken) { break; // Multi-level break to pick lowest peripheral } } - if (self->clock != NULL) { + if (self->clock != NULL || spi_taken) { break; } // if just MISO, reduce search @@ -118,14 +118,13 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, } if (reserved_spi[mcu_spi_sck_list[i].bank_idx - 1]) { spi_taken = true; - continue; + break; } self->clock = &mcu_spi_sck_list[i]; - self->mosi = NULL; self->miso = &mcu_spi_miso_list[j]; break; } - if (self->clock != NULL) { + if (self->clock != NULL || spi_taken) { break; } // if just MOSI, reduce search @@ -137,14 +136,13 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, } if (reserved_spi[mcu_spi_sck_list[i].bank_idx - 1]) { spi_taken = true; - continue; + break; } self->clock = &mcu_spi_sck_list[i]; self->mosi = &mcu_spi_mosi_list[j]; - self->miso = NULL; break; } - if (self->clock != NULL) { + if (self->clock != NULL || spi_taken) { break; } } else { diff --git a/ports/mimxrt10xx/common-hal/busio/UART.c b/ports/mimxrt10xx/common-hal/busio/UART.c index fbb45eeea4..af4328c74b 100644 --- a/ports/mimxrt10xx/common-hal/busio/UART.c +++ b/ports/mimxrt10xx/common-hal/busio/UART.c @@ -39,7 +39,9 @@ #include "fsl_lpuart.h" -// TODO +//arrays use 0 based numbering: UART is stored at index 0 +#define MAX_UART 8 +STATIC bool reserved_uart[MAX_UART]; #define UART_CLOCK_FREQ (CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6U) / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U) @@ -79,109 +81,161 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer, bool sigint_enabled) { - // TODO: Allow none rx or tx - - bool have_tx = tx != NULL; - bool have_rx = rx != NULL; - if (!have_tx && !have_rx) { - mp_raise_ValueError(translate("tx and rx cannot both be None")); - } - self->baudrate = baudrate; self->character_bits = bits; self->timeout_ms = timeout * 1000; - const uint32_t rx_count = sizeof(mcu_uart_rx_list) / sizeof(mcu_periph_obj_t); - const uint32_t tx_count = sizeof(mcu_uart_tx_list) / sizeof(mcu_periph_obj_t); + bool is_onedirection = false; + if (!rx != !tx) { + is_onedirection = true; + } + bool uart_taken = false; - for (uint32_t i = 0; i < rx_count; ++i) { - if (mcu_uart_rx_list[i].pin != rx) - continue; + const uint32_t rx_count = MP_ARRAY_SIZE(mcu_uart_rx_list); + const uint32_t tx_count = MP_ARRAY_SIZE(mcu_uart_tx_list); - for (uint32_t j = 0; j < tx_count; ++j) { - if (mcu_uart_tx_list[j].pin != tx) + // RX loop handles rx only, or both rx and tx + if (rx != NULL) { + for (uint32_t i = 0; i < rx_count; ++i) { + if (mcu_uart_rx_list[i].pin != rx) { continue; - - if (mcu_uart_tx_list[j].bank_idx != mcu_uart_rx_list[i].bank_idx) + } + // If TX is on, keep looking, else stop + if (tx != NULL) { + for (uint32_t j = 0; j < tx_count; ++j) { + if (mcu_uart_tx_list[j].pin != tx || + mcu_uart_tx_list[j].bank_idx != mcu_uart_rx_list[i].bank_idx) { + continue; + } + // If UART is taken, break (pins never have >1 periph) + if (reserved_uart[mcu_uart_rx_list[i].bank_idx - 1]) { + uart_taken = true; + break; + } + self->rx = &mcu_uart_rx_list[i]; + self->tx = &mcu_uart_tx_list[j]; + break; + } + if (self->tx != NULL || uart_taken) { + break; + } + } else { + if (reserved_uart[mcu_uart_rx_list[i].bank_idx - 1]) { + uart_taken = true; + break; + } + self->rx = &mcu_uart_rx_list[i]; + } + } + } else if (tx != NULL) { + // TX only case + for (uint32_t i = 0; i < tx_count; ++i) { + if (mcu_uart_tx_list[i].pin != tx) { continue; - - self->rx_pin = &mcu_uart_rx_list[i]; - self->tx_pin = &mcu_uart_tx_list[j]; - + } + if (reserved_uart[mcu_uart_tx_list[i].bank_idx - 1]) { + uart_taken = true; + break; + } + self->tx = &mcu_uart_tx_list[i]; break; } + } else { + mp_raise_ValueError(translate("Supply at least one UART pin")); } - if(self->rx_pin == NULL || self->tx_pin == NULL) { + if (uart_taken) { + mp_raise_RuntimeError(translate("UART peripheral is already in use")); + } + + if(self->rx == NULL && self->tx == NULL) { mp_raise_RuntimeError(translate("Invalid UART pin selection")); } + if (is_onedirection && ((rts != NULL) || (cts != NULL))) { + mp_raise_RuntimeError(translate("Both RX and TX required for flow control")); + } + // Filter for sane settings for RS485 if (rs485_dir != NULL) { - if ((rts != NULL) || (cts != NULL)) { - mp_raise_ValueError(translate("Cannot specify RTS or CTS in RS485 mode")); - } - // For IMXRT the RTS pin is used for RS485 direction - rts = rs485_dir; + if ((rts != NULL) || (cts != NULL)) { + mp_raise_ValueError(translate("Cannot specify RTS or CTS in RS485 mode")); + } + // For IMXRT the RTS pin is used for RS485 direction + rts = rs485_dir; } else { - if (rs485_invert) { - mp_raise_ValueError(translate("RS485 inversion specified when not in RS485 mode")); - } + if (rs485_invert) { + mp_raise_ValueError(translate("RS485 inversion specified when not in RS485 mode")); + } } // Now check for RTS/CTS (or overloaded RS485 direction) pin(s) - const uint32_t rts_count = sizeof(mcu_uart_rts_list) / sizeof(mcu_periph_obj_t); - const uint32_t cts_count = sizeof(mcu_uart_cts_list) / sizeof(mcu_periph_obj_t); + const uint32_t rts_count = MP_ARRAY_SIZE(mcu_uart_rts_list); + const uint32_t cts_count = MP_ARRAY_SIZE(mcu_uart_cts_list); if (rts != NULL) { - for (uint32_t i=0; i < rts_count; ++i) { - if (mcu_uart_rts_list[i].bank_idx == self->rx_pin->bank_idx) { - if (mcu_uart_rts_list[i].pin == rts) { - self->rts_pin = &mcu_uart_rts_list[i]; - break; - } + for (uint32_t i=0; i < rts_count; ++i) { + if (mcu_uart_rts_list[i].bank_idx == self->rx->bank_idx) { + if (mcu_uart_rts_list[i].pin == rts) { + self->rts = &mcu_uart_rts_list[i]; + break; + } + } + } + if (self->rts == NULL){ + mp_raise_ValueError(translate("Selected RTS pin not valid")); } - } - if (self->rts_pin == NULL) - mp_raise_ValueError(translate("Selected RTS pin not valid")); } if (cts != NULL) { - for (uint32_t i=0; i < cts_count; ++i) { - if (mcu_uart_cts_list[i].bank_idx == self->rx_pin->bank_idx) { - if (mcu_uart_cts_list[i].pin == cts) { - self->cts_pin = &mcu_uart_cts_list[i]; - break; - } + for (uint32_t i=0; i < cts_count; ++i) { + if (mcu_uart_cts_list[i].bank_idx == self->rx->bank_idx) { + if (mcu_uart_cts_list[i].pin == cts) { + self->cts = &mcu_uart_cts_list[i]; + break; + } + } + } + if (self->cts == NULL){ + mp_raise_ValueError(translate("Selected CTS pin not valid")); } - } - if (self->cts_pin == NULL) - mp_raise_ValueError(translate("Selected CTS pin not valid")); } - self->uart = mcu_uart_banks[self->tx_pin->bank_idx - 1]; + if (self->rx) { + self->uart = mcu_uart_banks[self->rx->bank_idx - 1]; + } else { + self->uart = mcu_uart_banks[self->tx->bank_idx - 1]; + } - config_periph_pin(self->rx_pin); - config_periph_pin(self->tx_pin); - if (self->rts_pin) - config_periph_pin(self->rts_pin); - if (self->cts_pin) - config_periph_pin(self->cts_pin); + if (self->rx) { + config_periph_pin(self->rx); + } + if (self->tx) { + config_periph_pin(self->tx); + } + if (self->rts) { + config_periph_pin(self->rts); + } + if (self->cts) { + config_periph_pin(self->cts); + } lpuart_config_t config = { 0 }; LPUART_GetDefaultConfig(&config); config.dataBitsCount = self->character_bits == 8 ? kLPUART_EightDataBits : kLPUART_SevenDataBits; config.baudRate_Bps = self->baudrate; - config.enableTx = self->tx_pin != NULL; - config.enableRx = self->rx_pin != NULL; - config.enableRxRTS = self->rts_pin != NULL; - config.enableTxCTS = self->cts_pin != NULL; - if (self->rts_pin != NULL) - claim_pin(self->rts_pin->pin); - if (self->cts_pin != NULL) - claim_pin(self->cts_pin->pin); + config.enableTx = self->tx != NULL; + config.enableRx = self->rx != NULL; + config.enableRxRTS = self->rts != NULL; + config.enableTxCTS = self->cts != NULL; + if (self->rts != NULL) { + claim_pin(self->rts->pin); + } + if (self->cts != NULL) { + claim_pin(self->cts->pin); + } LPUART_Init(self->uart, &config, UART_CLOCK_FREQ); @@ -189,16 +243,18 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, // ..unfortunately this isn't done by the driver library uint32_t modir = (self->uart->MODIR) & ~(LPUART_MODIR_TXRTSPOL_MASK | LPUART_MODIR_TXRTSE_MASK); if (rs485_dir != NULL) { - modir |= LPUART_MODIR_TXRTSE_MASK; - if (rs485_invert) - modir |= LPUART_MODIR_TXRTSPOL_MASK; + modir |= LPUART_MODIR_TXRTSE_MASK; + if (rs485_invert) { + modir |= LPUART_MODIR_TXRTSPOL_MASK; + } } self->uart->MODIR = modir; - if (self->tx_pin != NULL) - claim_pin(self->tx_pin->pin); + if (self->tx != NULL) { + claim_pin(self->tx->pin); + } - if (self->rx_pin != NULL) { + if (self->rx != NULL) { // The LPUART ring buffer wastes one byte to distinguish between full and empty. self->ringbuf = gc_alloc(receiver_buffer_size + 1, false, true /*long-lived*/); @@ -212,12 +268,12 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, // the capacity is one less than the size. LPUART_TransferStartRingBuffer(self->uart, &self->handle, self->ringbuf, receiver_buffer_size + 1); - claim_pin(self->rx_pin->pin); + claim_pin(self->rx->pin); } } bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) { - return self->rx_pin == NULL && self->tx_pin == NULL; + return self->rx == NULL && self->tx == NULL; } 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) { gc_free(self->ringbuf); -// reset_pin_number(self->rx_pin); -// reset_pin_number(self->tx_pin); +// reset_pin_number(self->rx); +// reset_pin_number(self->tx); - self->rx_pin = NULL; - self->tx_pin = NULL; + self->rx = NULL; + self->tx = NULL; } // Read characters. size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t len, int *errcode) { - if (self->rx_pin == NULL) { + if (self->rx == NULL) { mp_raise_ValueError(translate("No RX pin")); } @@ -284,7 +340,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t // Write characters. size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, size_t len, int *errcode) { - if (self->tx_pin == NULL) { + if (self->tx == NULL) { mp_raise_ValueError(translate("No TX pin")); } @@ -320,7 +376,7 @@ void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) { } bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) { - if (self->tx_pin == NULL) { + if (self->tx == NULL) { return false; } diff --git a/ports/mimxrt10xx/common-hal/busio/UART.h b/ports/mimxrt10xx/common-hal/busio/UART.h index 3a326eb3a4..94a5fb02c0 100644 --- a/ports/mimxrt10xx/common-hal/busio/UART.h +++ b/ports/mimxrt10xx/common-hal/busio/UART.h @@ -45,10 +45,10 @@ typedef struct { uint32_t baudrate; uint8_t character_bits; uint32_t timeout_ms; - const mcu_periph_obj_t *rx_pin; - const mcu_periph_obj_t *tx_pin; - const mcu_periph_obj_t *cts_pin; - const mcu_periph_obj_t *rts_pin; + const mcu_periph_obj_t *rx; + const mcu_periph_obj_t *tx; + const mcu_periph_obj_t *cts; + const mcu_periph_obj_t *rts; } busio_uart_obj_t; #endif // MICROPY_INCLUDED_MIMXRT10XX_COMMON_HAL_BUSIO_UART_H diff --git a/ports/stm/common-hal/busio/UART.c b/ports/stm/common-hal/busio/UART.c index c83479126a..0dc10c4e4c 100644 --- a/ports/stm/common-hal/busio/UART.c +++ b/ports/stm/common-hal/busio/UART.c @@ -259,7 +259,7 @@ void common_hal_busio_uart_never_reset(busio_uart_obj_t *self) { } bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) { - return self->tx->pin == NULL; + return (self->tx->pin == NULL && self->rx->pin == NULL); } void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { @@ -272,10 +272,15 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { } } - reset_pin_number(self->tx->pin->port,self->tx->pin->number); - reset_pin_number(self->rx->pin->port,self->rx->pin->number); - self->tx = NULL; - self->rx = NULL; + if (self->tx) { + reset_pin_number(self->tx->pin->port,self->tx->pin->number); + self->tx = NULL; + } + if (self->rx) { + reset_pin_number(self->rx->pin->port,self->rx->pin->number); + self->rx = NULL; + } + ringbuf_free(&self->ringbuf); }