diff options
23 files changed, 361 insertions, 392 deletions
diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 36bfa83de..b50e63b75 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -333,6 +333,7 @@ msgid "All SPI peripherals are in use" msgstr "" #: ports/esp32s2/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c +#: ports/raspberrypi/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "" @@ -952,6 +953,7 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "" #: ports/mimxrt10xx/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c +#: ports/raspberrypi/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "" @@ -1102,7 +1104,7 @@ msgid "Init program size invalid" msgstr "" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c -msgid "Initial set pin direcion conflicts with initial out pin direction" +msgid "Initial set pin direction conflicts with initial out pin direction" msgstr "" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c @@ -1219,7 +1221,8 @@ msgstr "" msgid "Invalid bits per value" msgstr "" -#: ports/nrf/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c +#: ports/nrf/common-hal/busio/UART.c ports/raspberrypi/common-hal/busio/UART.c +#: ports/stm/common-hal/busio/UART.c msgid "Invalid buffer size" msgstr "" @@ -1294,10 +1297,10 @@ msgstr "" #: ports/esp32s2/common-hal/busio/I2C.c ports/esp32s2/common-hal/busio/SPI.c #: ports/esp32s2/common-hal/busio/UART.c ports/esp32s2/common-hal/canio/CAN.c #: ports/mimxrt10xx/common-hal/busio/I2C.c -#: ports/mimxrt10xx/common-hal/busio/SPI.c -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/nrf/common-hal/busio/I2C.c +#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/nrf/common-hal/busio/I2C.c #: ports/raspberrypi/common-hal/busio/I2C.c #: ports/raspberrypi/common-hal/busio/SPI.c +#: ports/raspberrypi/common-hal/busio/UART.c msgid "Invalid pins" msgstr "" @@ -1346,7 +1349,8 @@ msgstr "" msgid "Invalid wave file" msgstr "" -#: ports/stm/common-hal/busio/UART.c +#: ports/mimxrt10xx/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c +#: ports/raspberrypi/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "Invalid word/bit length" msgstr "" @@ -1846,7 +1850,7 @@ msgstr "" msgid "RNG Init Error" msgstr "" -#: ports/nrf/common-hal/busio/UART.c +#: ports/nrf/common-hal/busio/UART.c ports/raspberrypi/common-hal/busio/UART.c msgid "RS485 Not yet supported on this device" msgstr "" @@ -2156,10 +2160,6 @@ msgstr "" msgid "UART Re-init error" msgstr "" -#: ports/raspberrypi/common-hal/busio/UART.c -msgid "UART not yet supported" -msgstr "" - #: ports/stm/common-hal/busio/UART.c msgid "UART write error" msgstr "" @@ -2488,7 +2488,7 @@ msgid "binary op %q not implemented" msgstr "" #: shared-bindings/busio/UART.c -msgid "bits must be 7, 8 or 9" +msgid "bits must be in range 5 to 9" msgstr "" #: shared-bindings/audiomixer/Mixer.c diff --git a/locale/es.po b/locale/es.po index d11003d67..66101a5e4 100644 --- a/locale/es.po +++ b/locale/es.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2021-02-21 22:27+0000\n" +"PO-Revision-Date: 2021-02-26 13:50+0000\n" "Last-Translator: Jose David M <jquintana202020@gmail.com>\n" "Language-Team: \n" "Language: es\n" @@ -473,7 +473,7 @@ msgstr "Por debajo de la tasa mínima de refrescamiento" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must be sequential pins" -msgstr "" +msgstr "Le reloj de bit y de selector de palabra deben ser pines secuenciales" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -518,7 +518,7 @@ msgstr "Búfer + compensado muy pequeños %d %d %d" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" -msgstr "" +msgstr "Los elementos del búfer deben de ser de una longitud de 4 bytes o menos" #: shared-module/usb_hid/Device.c #, c-format @@ -1112,6 +1112,8 @@ msgstr "IV debe tener %d bytes de longitud" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "In buffer elements must be 4 bytes long or less" msgstr "" +"Los elementos del búfer de entrada deben ser de una longitud de 4 bytes o " +"menos" #: py/persistentcode.c msgid "" @@ -1132,10 +1134,14 @@ msgstr "Tamaño del programa Init invalido" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Initial set pin direcion conflicts with initial out pin direction" msgstr "" +"La dirección inicial del pin de configuración esta en conflicto con la " +"dirección de salida inicial del pin" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Initial set pin state conflicts with initial out pin state" msgstr "" +"El estado inicial del pin de configuración esta en conflicto con el estado " +"inicial de salida del pin" #: ports/esp32s2/common-hal/watchdog/WatchDogTimer.c msgid "Initialization failed due to lack of memory" @@ -1576,11 +1582,11 @@ msgstr "Sin soporte de hardware en pin" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "No in in program" -msgstr "" +msgstr "No hay \"in\" en el programa" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "No in or out in program" -msgstr "" +msgstr "No hay \"in\" o \"out\" en el programa" #: shared-bindings/aesio/aes.c msgid "No key was specified" @@ -1726,6 +1732,8 @@ msgstr "Tiempo de espera agotado" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Out buffer elements must be 4 bytes long or less" msgstr "" +"Los elementos del búfer de salida deben ser de una longitud de 4 bytes o " +"menos" #: ports/esp32s2/bindings/espidf/__init__.c ports/esp32s2/esp_error.c msgid "Out of memory" diff --git a/locale/pt_BR.po b/locale/pt_BR.po index 7d8142b98..8058e0d39 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2021-02-21 22:27+0000\n" +"PO-Revision-Date: 2021-02-26 13:50+0000\n" "Last-Translator: Wellington Terumi Uemura <wellingtonuemura@gmail.com>\n" "Language-Team: \n" "Language: pt_BR\n" @@ -473,7 +473,7 @@ msgstr "Abaixo da taxa mínima de quadros" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must be sequential pins" -msgstr "" +msgstr "O Bit clock e o word select devem ser pinos sequenciais" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -520,7 +520,7 @@ msgstr "O buffer + desvio é muito pequeno %d %d %d" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" -msgstr "" +msgstr "Os elementos do buffer devem ter 4 bytes de comprimento ou menos" #: shared-module/usb_hid/Device.c #, c-format @@ -1115,7 +1115,7 @@ msgstr "O IV deve ter %d bytes de comprimento" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "In buffer elements must be 4 bytes long or less" -msgstr "" +msgstr "No buffer, os elementos devem ter 4 bytes ou menos" #: py/persistentcode.c msgid "" @@ -1136,10 +1136,13 @@ msgstr "O tamanho do programa Init é inválido" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Initial set pin direcion conflicts with initial out pin direction" msgstr "" +"A direção do pino inicial está em conflito com a direção inicial do pino" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Initial set pin state conflicts with initial out pin state" msgstr "" +"A definição do estado inicial do pino está em conflito com estado do inicial " +"do pino" #: ports/esp32s2/common-hal/watchdog/WatchDogTimer.c msgid "Initialization failed due to lack of memory" @@ -1576,11 +1579,11 @@ msgstr "Nenhum suporte de hardware no pino" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "No in in program" -msgstr "" +msgstr "Sem entrada no programa" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "No in or out in program" -msgstr "" +msgstr "Sem entrada ou saída no programa" #: shared-bindings/aesio/aes.c msgid "No key was specified" @@ -1726,7 +1729,7 @@ msgstr "A operação expirou" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Out buffer elements must be 4 bytes long or less" -msgstr "" +msgstr "Os elementos da saída do buffer devem ter 4 bytes ou menos" #: ports/esp32s2/bindings/espidf/__init__.c ports/esp32s2/esp_error.c msgid "Out of memory" diff --git a/locale/sv.po b/locale/sv.po index abf892b09..16f3359f5 100644 --- a/locale/sv.po +++ b/locale/sv.po @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2021-02-21 22:27+0000\n" +"PO-Revision-Date: 2021-02-26 13:50+0000\n" "Last-Translator: Jonny Bergdahl <jonny@bergdahl.it>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: sv\n" @@ -466,7 +466,7 @@ msgstr "Under minsta bildfrekvens" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must be sequential pins" -msgstr "" +msgstr "Bitklocka och word select måste vara sekventiella pinnar" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -511,7 +511,7 @@ msgstr "Buffert + offset för liten %d %d %d" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" -msgstr "" +msgstr "Buffertelement måste vara fyra byte långa eller mindre" #: shared-module/usb_hid/Device.c #, c-format @@ -1102,7 +1102,7 @@ msgstr "IV måste vara %d byte lång" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "In buffer elements must be 4 bytes long or less" -msgstr "" +msgstr "Inbuffertelement måste vara 4 byte långa eller mindre" #: py/persistentcode.c msgid "" @@ -1122,11 +1122,13 @@ msgstr "Storlek på init-program ogiltigt" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Initial set pin direcion conflicts with initial out pin direction" -msgstr "" +msgstr "Initial pinn-riktning står i konflikt med initial utpinn-riktning" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Initial set pin state conflicts with initial out pin state" msgstr "" +"Initial inställning av pinntillstånd är i konflikt med initialt " +"utpinntillstånd" #: ports/esp32s2/common-hal/watchdog/WatchDogTimer.c msgid "Initialization failed due to lack of memory" @@ -1562,11 +1564,11 @@ msgstr "Inget hårdvarustöd på pinne" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "No in in program" -msgstr "" +msgstr "Inget in i programmet" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "No in or out in program" -msgstr "" +msgstr "Inget in eller ut i programmet" #: shared-bindings/aesio/aes.c msgid "No key was specified" @@ -1710,7 +1712,7 @@ msgstr "Åtgärden orsakade timeout" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Out buffer elements must be 4 bytes long or less" -msgstr "" +msgstr "Utbuffertelement ska vara max fyra byte långa" #: ports/esp32s2/bindings/espidf/__init__.c ports/esp32s2/esp_error.c msgid "Out of memory" diff --git a/ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.mk b/ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.mk index 892a5371e..b1306f54b 100644 --- a/ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.mk +++ b/ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.mk @@ -11,3 +11,5 @@ LONGINT_IMPL = NONE CIRCUITPY_FULL_BUILD = 0 CIRCUITPY_COUNTIO = 0 CIRCUITPY_ROTARYIO = 0 + +SUPEROPT_GC = 0 diff --git a/ports/mimxrt10xx/common-hal/busio/UART.c b/ports/mimxrt10xx/common-hal/busio/UART.c index 03a6e8f3e..503da14c2 100644 --- a/ports/mimxrt10xx/common-hal/busio/UART.c +++ b/ports/mimxrt10xx/common-hal/busio/UART.c @@ -93,6 +93,10 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, self->character_bits = bits; self->timeout_ms = timeout * 1000; + if (self->character_bits != 7 && self->character_bits != 8) { + mp_raise_ValueError(translate("Invalid word/bit length")); + } + // We are transmitting one direction if one pin is NULL and the other isn't. bool is_onedirection = (rx == NULL) != (tx == NULL); bool uart_taken = false; @@ -154,10 +158,6 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, mp_raise_ValueError(translate("Hardware in use, try alternative pins")); } - if(self->rx == NULL && self->tx == NULL) { - mp_raise_ValueError(translate("Invalid pins")); - } - if (is_onedirection && ((rts != NULL) || (cts != NULL))) { mp_raise_ValueError(translate("Both RX and TX required for flow control")); } diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c index 6ecf7e0ba..491e360e4 100644 --- a/ports/nrf/common-hal/busio/UART.c +++ b/ports/nrf/common-hal/busio/UART.c @@ -70,9 +70,9 @@ static uint32_t get_nrf_baud (uint32_t baudrate) { { 14400, NRF_UARTE_BAUDRATE_14400 }, { 19200, NRF_UARTE_BAUDRATE_19200 }, { 28800, NRF_UARTE_BAUDRATE_28800 }, - { 31250, NRF_UARTE_BAUDRATE_31250 }, + { 31250, NRF_UARTE_BAUDRATE_31250 }, { 38400, NRF_UARTE_BAUDRATE_38400 }, - { 56000, NRF_UARTE_BAUDRATE_56000 }, + { 56000, NRF_UARTE_BAUDRATE_56000 }, { 57600, NRF_UARTE_BAUDRATE_57600 }, { 76800, NRF_UARTE_BAUDRATE_76800 }, { 115200, NRF_UARTE_BAUDRATE_115200 }, @@ -144,6 +144,10 @@ 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) { + if (bits != 8) { + mp_raise_ValueError(translate("Invalid word/bit length")); + } + if ((rs485_dir != NULL) || (rs485_invert)) { mp_raise_ValueError(translate("RS485 Not yet supported on this device")); } diff --git a/ports/raspberrypi/boards/adafruit_feather_rp2040/board.c b/ports/raspberrypi/boards/adafruit_feather_rp2040/board.c index 8686f6d0c..c4021a83e 100644 --- a/ports/raspberrypi/boards/adafruit_feather_rp2040/board.c +++ b/ports/raspberrypi/boards/adafruit_feather_rp2040/board.c @@ -30,10 +30,6 @@ #include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" void board_init(void) { - common_hal_never_reset_pin(&pin_GPIO17); - gpio_init(17); - gpio_set_dir(17, GPIO_OUT); - gpio_put(17, true); } bool board_requests_safe_mode(void) { diff --git a/ports/raspberrypi/boards/adafruit_feather_rp2040/pins.c b/ports/raspberrypi/boards/adafruit_feather_rp2040/pins.c index 1617ac865..a558d7fe6 100644 --- a/ports/raspberrypi/boards/adafruit_feather_rp2040/pins.c +++ b/ports/raspberrypi/boards/adafruit_feather_rp2040/pins.c @@ -14,12 +14,12 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO0) }, { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, - { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO6) }, { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO2) }, { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO3) }, - { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, - { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO8) }, { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11) }, @@ -27,7 +27,6 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO16) }, - { MP_ROM_QSTR(MP_QSTR_NEOPIXEL_POWER), MP_ROM_PTR(&pin_GPIO17) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, diff --git a/ports/raspberrypi/common-hal/busio/UART.c b/ports/raspberrypi/common-hal/busio/UART.c index f9a75b499..1bc121177 100644 --- a/ports/raspberrypi/common-hal/busio/UART.c +++ b/ports/raspberrypi/common-hal/busio/UART.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2021 microDev * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,238 +24,184 @@ * THE SOFTWARE. */ -#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/busio/UART.h" -#include "mpconfigport.h" -#include "lib/utils/interrupt_char.h" -#include "py/gc.h" +#include "py/stream.h" #include "py/mperrno.h" #include "py/runtime.h" -#include "py/stream.h" -#include "supervisor/shared/translate.h" #include "supervisor/shared/tick.h" +#include "lib/utils/interrupt_char.h" +#include "common-hal/microcontroller/Pin.h" -#define UART_DEBUG(...) (void)0 -// #define UART_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__) - -// Do-nothing callback needed so that usart_async code will enable rx interrupts. -// See comment below re usart_async_register_callback() -// static void usart_async_rxc_callback(const struct usart_async_descriptor *const descr) { -// // Nothing needs to be done by us. -// } +#include "src/rp2_common/hardware_irq/include/hardware/irq.h" +#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" #define NO_PIN 0xff +#define UART_INST(uart) (((uart) ? uart1 : uart0)) + +typedef enum { + STATUS_FREE = 0, + STATUS_BUSY, + STATUS_NEVER_RESET +} uart_status_t; + +static uart_status_t uart_status[NUM_UARTS]; + +void reset_uart(void) { + for (uint8_t num = 0; num < NUM_UARTS; num++) { + if (uart_status[num] == STATUS_BUSY) { + uart_status[num] = STATUS_FREE; + uart_deinit(UART_INST(num)); + } + } +} + +void never_reset_uart(uint8_t num) { + uart_status[num] = STATUS_NEVER_RESET; +} + +static uint8_t pin_init(const uint8_t uart, const mcu_pin_obj_t * pin, const uint8_t pin_type) { + if (pin == NULL) { + return NO_PIN; + } + if (!(((pin->number % 4) == pin_type) && ((((pin->number + 4) / 8) % NUM_UARTS) == uart))) { + mp_raise_ValueError(translate("Invalid pins")); + } + claim_pin(pin); + gpio_set_function(pin->number, GPIO_FUNC_UART); + return pin->number; +} + +static busio_uart_obj_t* active_uarts[NUM_UARTS]; + +static void _copy_into_ringbuf(ringbuf_t* r, uart_inst_t* uart) { + while (uart_is_readable(uart) && ringbuf_num_empty(r) > 0) { + ringbuf_put(r, (uint8_t) uart_get_hw(uart)->dr); + } +} + +static void shared_callback(busio_uart_obj_t *self) { + _copy_into_ringbuf(&self->ringbuf, self->uart); + // We always clear the interrupt so it doesn't continue to fire because we + // may not have read everything available. + uart_get_hw(self->uart)->icr = UART_UARTICR_RXIC_BITS; +} + +static void uart0_callback(void) { + shared_callback(active_uarts[0]); +} + +static void uart1_callback(void) { + shared_callback(active_uarts[1]); +} + void common_hal_busio_uart_construct(busio_uart_obj_t *self, - const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, - const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts, - const mcu_pin_obj_t * rs485_dir, bool rs485_invert, - uint32_t baudrate, uint8_t bits, busio_uart_parity_t parity, uint8_t stop, - mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer, - bool sigint_enabled) { - mp_raise_NotImplementedError(translate("UART not yet supported")); - -// Sercom* sercom = NULL; -// uint8_t sercom_index = 255; // Unset index -// uint32_t rx_pinmux = 0; -// uint8_t rx_pad = 255; // Unset pad -// uint32_t tx_pinmux = 0; -// uint8_t tx_pad = 255; // Unset pad - -// if ((rts != NULL) || (cts != NULL) || (rs485_dir != NULL) || (rs485_invert)) { -// mp_raise_ValueError(translate("RTS/CTS/RS485 Not yet supported on this device")); -// } - -// if (bits > 8) { -// mp_raise_NotImplementedError(translate("bytes > 8 bits not supported")); -// } - -// 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; - -// // This assignment is only here because the usart_async routines take a *const argument. -// struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; - -// for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { -// Sercom* potential_sercom = NULL; -// if (have_tx) { -// sercom_index = tx->sercom[i].index; -// if (sercom_index >= SERCOM_INST_NUM) { -// continue; -// } -// potential_sercom = sercom_insts[sercom_index]; -// #ifdef SAMD21 -// if (potential_sercom->USART.CTRLA.bit.ENABLE != 0 || -// !(tx->sercom[i].pad == 0 || -// tx->sercom[i].pad == 2)) { -// continue; -// } -// #endif -// #ifdef SAM_D5X_E5X -// if (potential_sercom->USART.CTRLA.bit.ENABLE != 0 || -// !(tx->sercom[i].pad == 0)) { -// continue; -// } -// #endif -// tx_pinmux = PINMUX(tx->number, (i == 0) ? MUX_C : MUX_D); -// tx_pad = tx->sercom[i].pad; -// if (rx == NULL) { -// sercom = potential_sercom; -// break; -// } -// } -// for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { -// if (((!have_tx && rx->sercom[j].index < SERCOM_INST_NUM && -// sercom_insts[rx->sercom[j].index]->USART.CTRLA.bit.ENABLE == 0) || -// sercom_index == rx->sercom[j].index) && -// rx->sercom[j].pad != tx_pad) { -// rx_pinmux = PINMUX(rx->number, (j == 0) ? MUX_C : MUX_D); -// rx_pad = rx->sercom[j].pad; -// sercom = sercom_insts[rx->sercom[j].index]; -// sercom_index = rx->sercom[j].index; -// break; -// } -// } -// if (sercom != NULL) { -// break; -// } -// } -// if (sercom == NULL) { -// mp_raise_ValueError(translate("Invalid pins")); -// } -// if (!have_tx) { -// tx_pad = 0; -// if (rx_pad == 0) { -// tx_pad = 2; -// } -// } -// if (!have_rx) { -// rx_pad = (tx_pad + 1) % 4; -// } - -// // Set up clocks on SERCOM. -// samd_peripherals_sercom_clock_init(sercom, sercom_index); - -// if (rx && receiver_buffer_size > 0) { -// self->buffer_length = receiver_buffer_size; -// // Initially allocate the UART's buffer in the long-lived part of the -// // heap. UARTs are generally long-lived objects, but the "make long- -// // lived" machinery is incapable of moving internal pointers like -// // self->buffer, so do it manually. (However, as long as internal -// // pointers like this are NOT moved, allocating the buffer -// // in the long-lived pool is not strictly necessary) -// self->buffer = (uint8_t *) gc_alloc(self->buffer_length * sizeof(uint8_t), false, true); -// if (self->buffer == NULL) { -// common_hal_busio_uart_deinit(self); -// mp_raise_msg_varg(&mp_type_MemoryError, translate("Failed to allocate RX buffer of %d bytes"), self->buffer_length * sizeof(uint8_t)); -// } -// } else { -// self->buffer_length = 0; -// self->buffer = NULL; -// } - -// if (usart_async_init(usart_desc_p, sercom, self->buffer, self->buffer_length, NULL) != ERR_NONE) { -// mp_raise_ValueError(translate("Could not initialize UART")); -// } - -// // usart_async_init() sets a number of defaults based on a prototypical SERCOM -// // which don't necessarily match what we need. After calling it, set the values -// // specific to this instantiation of UART. - -// // Set pads computed for this SERCOM. -// // TXPO: -// // 0x0: TX pad 0; no RTS/CTS -// // 0x1: TX pad 2; no RTS/CTS -// // 0x2: TX pad 0; RTS: pad 2, CTS: pad 3 (not used by us right now) -// // So divide by 2 to map pad to value. -// // RXPO: -// // 0x0: RX pad 0 -// // 0x1: RX pad 1 -// // 0x2: RX pad 2 -// // 0x3: RX pad 3 - -// // Doing a group mask and set of the registers saves 60 bytes over setting the bitfields individually. - -// sercom->USART.CTRLA.reg &= ~(SERCOM_USART_CTRLA_TXPO_Msk | -// SERCOM_USART_CTRLA_RXPO_Msk | -// SERCOM_USART_CTRLA_FORM_Msk); -// sercom->USART.CTRLA.reg |= SERCOM_USART_CTRLA_TXPO(tx_pad / 2) | -// SERCOM_USART_CTRLA_RXPO(rx_pad) | -// (parity == BUSIO_UART_PARITY_NONE ? 0 : SERCOM_USART_CTRLA_FORM(1)); - -// // Enable tx and/or rx based on whether the pins were specified. -// // CHSIZE is 0 for 8 bits, 5, 6, 7 for 5, 6, 7 bits. 1 for 9 bits, but we don't support that. -// sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_TXEN | -// SERCOM_USART_CTRLB_RXEN | -// SERCOM_USART_CTRLB_PMODE | -// SERCOM_USART_CTRLB_SBMODE | -// SERCOM_USART_CTRLB_CHSIZE_Msk); -// sercom->USART.CTRLB.reg |= (have_tx ? SERCOM_USART_CTRLB_TXEN : 0) | -// (have_rx ? SERCOM_USART_CTRLB_RXEN : 0) | -// (parity == BUSIO_UART_PARITY_ODD ? SERCOM_USART_CTRLB_PMODE : 0) | -// (stop > 1 ? SERCOM_USART_CTRLB_SBMODE : 0) | -// SERCOM_USART_CTRLB_CHSIZE(bits % 8); - -// // Set baud rate -// common_hal_busio_uart_set_baudrate(self, baudrate); - -// // Turn on rx interrupt handling. The UART async driver has its own set of internal callbacks, -// // which are set up by uart_async_init(). These in turn can call user-specified callbacks. -// // In fact, the actual interrupts are not enabled unless we set up a user-specified callback. -// // This is confusing. It's explained in the Atmel START User Guide -> Implementation Description -> -// // Different read function behavior in some asynchronous drivers. As of this writing: -// // http://start.atmel.com/static/help/index.html?GUID-79201A5A-226F-4FBB-B0B8-AB0BE0554836 -// // Look at the ASFv4 code example for async USART. -// usart_async_register_callback(usart_desc_p, USART_ASYNC_RXC_CB, usart_async_rxc_callback); - - -// if (have_tx) { -// gpio_set_pin_direction(tx->number, GPIO_DIRECTION_OUT); -// gpio_set_pin_pull_mode(tx->number, GPIO_PULL_OFF); -// gpio_set_pin_function(tx->number, tx_pinmux); -// self->tx_pin = tx->number; -// claim_pin(tx); -// } else { -// self->tx_pin = NO_PIN; -// } - -// if (have_rx) { -// gpio_set_pin_direction(rx->number, GPIO_DIRECTION_IN); -// gpio_set_pin_pull_mode(rx->number, GPIO_PULL_OFF); -// gpio_set_pin_function(rx->number, rx_pinmux); -// self->rx_pin = rx->number; -// claim_pin(rx); -// } else { -// self->rx_pin = NO_PIN; -// } - -// usart_async_enable(usart_desc_p); + const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, + const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts, + const mcu_pin_obj_t * rs485_dir, bool rs485_invert, + uint32_t baudrate, uint8_t bits, busio_uart_parity_t parity, uint8_t stop, + mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer, + bool sigint_enabled) { + + if (bits > 8) { + mp_raise_ValueError(translate("Invalid word/bit length")); + } + + if (receiver_buffer_size == 0) { + mp_raise_ValueError(translate("Invalid buffer size")); + } + + if ((rs485_dir != NULL) || (rs485_invert)) { + mp_raise_NotImplementedError(translate("RS485 Not yet supported on this device")); + } + + uint8_t uart_id = ((((tx != NULL) ? tx->number : rx->number) + 4) / 8) % NUM_UARTS; + + if (uart_status[uart_id] != STATUS_FREE) { + mp_raise_RuntimeError(translate("All UART peripherals are in use")); + } else { + uart_status[uart_id] = STATUS_BUSY; + } + + self->tx_pin = pin_init(uart_id, tx, 0); + self->rx_pin = pin_init(uart_id, rx, 1); + self->cts_pin = pin_init(uart_id, cts, 2); + self->rts_pin = pin_init(uart_id, rts, 3); + + self->uart = UART_INST(uart_id); + self->uart_id = uart_id; + self->baudrate = baudrate; + self->timeout_ms = timeout * 1000; + + uart_init(self->uart, self->baudrate); + uart_set_fifo_enabled(self->uart, true); + uart_set_format(self->uart, bits, stop, parity); + uart_set_hw_flow(self->uart, (cts != NULL), (rts != NULL)); + + if (rx != NULL) { + // Initially allocate the UART's buffer in the long-lived part of the + // heap. UARTs are generally long-lived objects, but the "make long- + // lived" machinery is incapable of moving internal pointers like + // self->buffer, so do it manually. (However, as long as internal + // pointers like this are NOT moved, allocating the buffer + // in the long-lived pool is not strictly necessary) + // (This is a macro.) + if (!ringbuf_alloc(&self->ringbuf, receiver_buffer_size, true)) { + mp_raise_msg(&mp_type_MemoryError, translate("Failed to allocate RX buffer")); + } + active_uarts[uart_id] = self; + if (uart_id == 1) { + self->uart_irq_id = UART1_IRQ; + irq_set_exclusive_handler(self->uart_irq_id, uart1_callback); + } else { + self->uart_irq_id = UART0_IRQ; + irq_set_exclusive_handler(self->uart_irq_id, uart0_callback); + } + irq_set_enabled(self->uart_irq_id, true); + uart_set_irq_enables(self->uart, true /* rx has data */, false /* tx needs data */); + } } bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) { - return self->rx_pin == NO_PIN && self->tx_pin == NO_PIN; + return self->tx_pin == NO_PIN && self->rx_pin == NO_PIN; } void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { if (common_hal_busio_uart_deinited(self)) { return; } - // This assignment is only here because the usart_async routines take a *const argument. - // struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; - // usart_async_disable(usart_desc_p); - // usart_async_deinit(usart_desc_p); - reset_pin_number(self->rx_pin); + uart_deinit(self->uart); + ringbuf_free(&self->ringbuf); + active_uarts[self->uart_id] = NULL; + uart_status[self->uart_id] = STATUS_FREE; reset_pin_number(self->tx_pin); - self->rx_pin = NO_PIN; + reset_pin_number(self->rx_pin); + reset_pin_number(self->cts_pin); + reset_pin_number(self->rts_pin); self->tx_pin = NO_PIN; + self->rx_pin = NO_PIN; + self->cts_pin = NO_PIN; + self->rts_pin = NO_PIN; +} + +// 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 == NO_PIN) { + mp_raise_ValueError(translate("No TX pin")); + } + + while (len > 0) { + while (uart_is_writable(self->uart) && len > 0) { + // Write and advance. + uart_get_hw(self->uart)->dr = *data++; + // Decrease how many chars left to write. + len--; + } + RUN_BACKGROUND_TASKS; + } + + return len; } // Read characters. @@ -264,87 +210,56 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t mp_raise_ValueError(translate("No RX pin")); } - // This assignment is only here because the usart_async routines take a *const argument. - // struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; - if (len == 0) { // Nothing to read. return 0; } - // struct io_descriptor *io; - // usart_async_get_io_descriptor(usart_desc_p, &io); - - size_t total_read = 0; - // uint64_t start_ticks = supervisor_ticks_ms64(); - - // // Busy-wait until timeout or until we've read enough chars. - // while (supervisor_ticks_ms64() - start_ticks <= self->timeout_ms) { - // // Read as many chars as we can right now, up to len. - // size_t num_read = io_read(io, data, len); - - // // Advance pointer in data buffer, and decrease how many chars left to read. - // data += num_read; - // len -= num_read; - // total_read += num_read; - // if (len == 0) { - // // Don't need to read any more: data buf is full. - // break; - // } - // if (num_read > 0) { - // // Reset the timeout on every character read. - // start_ticks = supervisor_ticks_ms64(); - // } - // RUN_BACKGROUND_TASKS; - // // Allow user to break out of a timeout with a KeyboardInterrupt. - // if (mp_hal_is_interrupted()) { - // break; - // } - // // If we are zero timeout, make sure we don't loop again (in the event - // // we read in under 1ms) - // if (self->timeout_ms == 0) { - // break; - // } - // } - - // if (total_read == 0) { - // *errcode = EAGAIN; - // return MP_STREAM_ERROR; - // } + // Prevent conflict with uart irq. + irq_set_enabled(self->uart_irq_id, false); + + // Copy as much received data as available, up to len bytes. + size_t total_read = ringbuf_get_n(&self->ringbuf, data, len); + + // Check if we still need to read more data. + if (len > total_read) { + len-=total_read; + uint64_t start_ticks = supervisor_ticks_ms64(); + // Busy-wait until timeout or until we've read enough chars. + while (len > 0 && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms)) { + if (uart_is_readable(self->uart)) { + // Read and advance. + data[total_read] = uart_get_hw(self->uart)->dr; + + // Adjust the counters. + len--; + total_read++; + + // Reset the timeout on every character read. + start_ticks = supervisor_ticks_ms64(); + } + RUN_BACKGROUND_TASKS; + // Allow user to break out of a timeout with a KeyboardInterrupt. + if (mp_hal_is_interrupted()) { + break; + } + } + } - return total_read; -} + // Now that we've emptied the ringbuf some, fill it up with anything in the + // FIFO. This ensures that we'll empty the FIFO as much as possible and + // reset the interrupt when we catch up. + _copy_into_ringbuf(&self->ringbuf, self->uart); -// 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 == NO_PIN) { - mp_raise_ValueError(translate("No TX pin")); - } + // Re-enable irq. + irq_set_enabled(self->uart_irq_id, true); - // This assignment is only here because the usart_async routines take a *const argument. - // struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; - - // struct io_descriptor *io; - // usart_async_get_io_descriptor(usart_desc_p, &io); - - // // Start writing characters. This is non-blocking and will - // // return immediately after setting up the write. - // if (io_write(io, data, len) < 0) { - // *errcode = MP_EAGAIN; - // return MP_STREAM_ERROR; - // } - - // // Busy-wait until all characters transmitted. - // struct usart_async_status async_status; - // while (true) { - // usart_async_get_status(usart_desc_p, &async_status); - // if (async_status.txcnt >= len) { - // break; - // } - // RUN_BACKGROUND_TASKS; - // } + if (total_read == 0) { + *errcode = EAGAIN; + return MP_STREAM_ERROR; + } - return len; + return total_read; } uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) { @@ -352,18 +267,8 @@ uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) { } void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate) { - // This assignment is only here because the usart_async routines take a *const argument. - // struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; - // usart_async_set_baud_rate(usart_desc_p, - // // Samples and ARITHMETIC vs FRACTIONAL must correspond to USART_SAMPR in - // // hpl_sercom_config.h. - // _usart_async_calculate_baud_rate(baudrate, // e.g. 9600 baud - // PROTOTYPE_SERCOM_USART_ASYNC_CLOCK_FREQUENCY, - // 16, // samples - // USART_BAUDRATE_ASYNCH_ARITHMETIC, - // 0 // fraction - not used for ARITHMETIC - // )); self->baudrate = baudrate; + uart_set_baudrate(self->uart, baudrate); } mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) { @@ -375,30 +280,30 @@ void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeou } uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { - // This assignment is only here because the usart_async routines take a *const argument. - // struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; - // struct usart_async_status async_status; - // usart_async_get_status(usart_desc_p, &async_status); - // return async_status.rxcnt; - return 0; + // Prevent conflict with uart irq. + irq_set_enabled(self->uart_irq_id, false); + // The UART only interrupts after a threshold so make sure to copy anything + // out of its FIFO before measuring how many bytes we've received. + _copy_into_ringbuf(&self->ringbuf, self->uart); + irq_set_enabled(self->uart_irq_id, false); + return ringbuf_num_filled(&self->ringbuf); } void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) { - // This assignment is only here because the usart_async routines take a *const argument. - // struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; - // usart_async_flush_rx_buffer(usart_desc_p); + // Prevent conflict with uart irq. + irq_set_enabled(self->uart_irq_id, false); + ringbuf_clear(&self->ringbuf); + // Throw away the FIFO contents too. + while (uart_is_readable(self->uart)) { + (void) uart_get_hw(self->uart)->dr; + } + irq_set_enabled(self->uart_irq_id, true); } -// True if there are no characters still to be written. bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) { if (self->tx_pin == NO_PIN) { return false; } - return false; - // // This assignment is only here because the usart_async routines take a *const argument. - // struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; - // struct usart_async_status async_status; - // usart_async_get_status(usart_desc_p, &async_status); - // return !(async_status.flags & USART_ASYNC_STATUS_BUSY); + return uart_is_writable(self->uart); } diff --git a/ports/raspberrypi/common-hal/busio/UART.h b/ports/raspberrypi/common-hal/busio/UART.h index 43ed9bee0..4c07de240 100644 --- a/ports/raspberrypi/common-hal/busio/UART.h +++ b/ports/raspberrypi/common-hal/busio/UART.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2021 microDev * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,21 +27,26 @@ #ifndef MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_BUSIO_UART_H #define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_BUSIO_UART_H -#include "common-hal/microcontroller/Pin.h" - #include "py/obj.h" +#include "py/ringbuf.h" + +#include "src/rp2_common/hardware_uart/include/hardware/uart.h" typedef struct { mp_obj_base_t base; - // struct usart_async_descriptor usart_desc; - uint8_t rx_pin; uint8_t tx_pin; - uint8_t character_bits; - bool rx_error; + uint8_t rx_pin; + uint8_t cts_pin; + uint8_t rts_pin; + uint8_t uart_id; + uint8_t uart_irq_id; uint32_t baudrate; uint32_t timeout_ms; - uint32_t buffer_length; - uint8_t* buffer; + uart_inst_t * uart; + ringbuf_t ringbuf; } busio_uart_obj_t; +extern void reset_uart(void); +extern void never_reset_uart(uint8_t num); + #endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_BUSIO_UART_H diff --git a/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c b/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c index b0bc1b96e..a1a23b9ab 100644 --- a/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c +++ b/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c @@ -43,6 +43,7 @@ digitalinout_result_t common_hal_digitalio_digitalinout_construct( self->output = false; self->open_drain = false; + // Set to input. No output value. gpio_init(pin->number); return DIGITALINOUT_OK; } @@ -75,11 +76,17 @@ digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_output( digitalio_digitalinout_obj_t* self, bool value, digitalio_drive_mode_t drive_mode) { const uint8_t pin = self->pin->number; - gpio_set_dir(pin, GPIO_OUT); - // TODO: Turn on "strong" pin driving (more current available). + gpio_disable_pulls(pin); + + // Turn on "strong" pin driving (more current available). + hw_write_masked(&padsbank0_hw->io[pin], + PADS_BANK0_GPIO0_DRIVE_VALUE_12MA << PADS_BANK0_GPIO0_DRIVE_LSB, + PADS_BANK0_GPIO0_DRIVE_BITS); self->output = true; - common_hal_digitalio_digitalinout_set_drive_mode(self, drive_mode); + self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN; + + // Pin direction is ultimately set in set_value. We don't need to do it here. common_hal_digitalio_digitalinout_set_value(self, value); return DIGITALINOUT_OK; } @@ -92,10 +99,18 @@ digitalio_direction_t common_hal_digitalio_digitalinout_get_direction( void common_hal_digitalio_digitalinout_set_value( digitalio_digitalinout_obj_t* self, bool value) { const uint8_t pin = self->pin->number; - if (self->open_drain) { - gpio_set_dir(pin, value ? GPIO_IN : GPIO_OUT); + if (self->open_drain && value) { + // If true and open-drain, set the direction -before- setting + // the pin value, to to avoid a high glitch on the pin before + // switching from output to input for open-drain. + gpio_set_dir(pin, GPIO_IN); + gpio_put(pin, value); } else { + // Otherwise set the direction -after- setting the pin value, + // to avoid a glitch which might occur if the old value was + // different and the pin was previously set to input. gpio_put(pin, value); + gpio_set_dir(pin, GPIO_OUT); } } @@ -110,9 +125,6 @@ digitalinout_result_t common_hal_digitalio_digitalinout_set_drive_mode( const uint8_t pin = self->pin->number; bool value = common_hal_digitalio_digitalinout_get_value(self); self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN; - if (self->open_drain) { - gpio_put(pin, false); - } // True is implemented differently between modes so reset the value to make // sure it's correct for the new mode. if (value) { diff --git a/ports/raspberrypi/common-hal/pwmio/PWMOut.c b/ports/raspberrypi/common-hal/pwmio/PWMOut.c index f83da3014..9ca31a35e 100644 --- a/ports/raspberrypi/common-hal/pwmio/PWMOut.c +++ b/ports/raspberrypi/common-hal/pwmio/PWMOut.c @@ -162,6 +162,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self, common_hal_pwmio_pwmout_set_frequency(self, frequency); pwm_set_enabled(slice, true); } else { + common_hal_pwmio_pwmout_set_frequency(self, frequency); common_hal_pwmio_pwmout_set_duty_cycle(self, duty); } @@ -179,7 +180,7 @@ void pwmout_free(uint8_t slice, uint8_t channel) { uint32_t channel_mask = _mask(slice, channel); channel_use &= ~channel_mask; never_reset_channel &= ~channel_mask; - uint32_t slice_mask = ((1 << CHANNELS_PER_SLICE) - 1) << (slice * CHANNELS_PER_SLICE + channel); + uint32_t slice_mask = ((1 << CHANNELS_PER_SLICE) - 1) << (slice * CHANNELS_PER_SLICE); if ((channel_use & slice_mask) == 0) { target_slice_frequencies[slice] = 0; slice_variable_frequency &= ~(1 << slice); diff --git a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c index 7d2385064..5625a1b29 100644 --- a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c +++ b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c @@ -426,7 +426,7 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, mp_raise_ValueError(translate("Initial set pin state conflicts with initial out pin state")); } if ((initial_pin_direction & set_out_overlap) != (initial_set_pin_direction & set_out_overlap)) { - mp_raise_ValueError(translate("Initial set pin direcion conflicts with initial out pin direction")); + mp_raise_ValueError(translate("Initial set pin direction conflicts with initial out pin direction")); } initial_pin_state |= initial_set_pin_state; initial_pin_direction |= initial_set_pin_direction; diff --git a/ports/raspberrypi/supervisor/port.c b/ports/raspberrypi/supervisor/port.c index 10651d36b..501a0c5ce 100644 --- a/ports/raspberrypi/supervisor/port.c +++ b/ports/raspberrypi/supervisor/port.c @@ -39,6 +39,9 @@ #include "shared-bindings/rtc/__init__.h" #include "shared-bindings/pwmio/PWMOut.h" +#include "common-hal/rtc/RTC.h" +#include "common-hal/busio/UART.h" + #include "supervisor/shared/safe_mode.h" #include "supervisor/shared/stack.h" #include "supervisor/shared/tick.h" @@ -78,6 +81,9 @@ safe_mode_t port_init(void) { // Reset everything into a known state before board_init. reset_port(); + // Initialize RTC + common_hal_rtc_init(); + // For the tick. hardware_alarm_claim(0); hardware_alarm_set_callback(0, _tick_callback); @@ -95,6 +101,7 @@ void reset_port(void) { #if CIRCUITPY_BUSIO reset_i2c(); reset_spi(); + reset_uart(); #endif #if CIRCUITPY_PWMIO @@ -192,7 +192,7 @@ void gc_init(void *start, void *end) { } void gc_deinit(void) { - // Run any finalizers before we stop using the heap. + // Run any finalisers before we stop using the heap. gc_sweep_all(); MP_STATE_MEM(gc_pool_start) = 0; diff --git a/py/malloc.c b/py/malloc.c index 8d5141ee0..c923e89a6 100644 --- a/py/malloc.c +++ b/py/malloc.c @@ -57,7 +57,7 @@ #undef free #undef realloc #define malloc_ll(b, ll) gc_alloc((b), false, (ll)) -#define malloc_with_finaliser(b) gc_alloc((b), true, false) +#define malloc_with_finaliser(b, ll) gc_alloc((b), true, (ll)) #define free gc_free #define realloc(ptr, n) gc_realloc(ptr, n, true) #define realloc_ext(ptr, n, mv) gc_realloc(ptr, n, mv) @@ -103,8 +103,8 @@ void *m_malloc_maybe(size_t num_bytes, bool long_lived) { } #if MICROPY_ENABLE_FINALISER -void *m_malloc_with_finaliser(size_t num_bytes) { - void *ptr = malloc_with_finaliser(num_bytes); +void *m_malloc_with_finaliser(size_t num_bytes, bool long_lived) { + void *ptr = malloc_with_finaliser(num_bytes, long_lived); if (ptr == NULL && num_bytes != 0) { m_malloc_fail(num_bytes); } @@ -72,11 +72,13 @@ typedef unsigned int uint; #define m_new_obj_var_maybe(obj_type, var_type, var_num) ((obj_type*)m_malloc_maybe(sizeof(obj_type) + sizeof(var_type) * (var_num), false)) #define m_new_ll_obj_var_maybe(obj_type, var_type, var_num) ((obj_type*)m_malloc_maybe(sizeof(obj_type) + sizeof(var_type) * (var_num), true)) #if MICROPY_ENABLE_FINALISER -#define m_new_obj_with_finaliser(type) ((type*)(m_malloc_with_finaliser(sizeof(type)))) -#define m_new_obj_var_with_finaliser(type, var_type, var_num) ((type*)m_malloc_with_finaliser(sizeof(type) + sizeof(var_type) * (var_num))) +#define m_new_obj_with_finaliser(type) ((type*)(m_malloc_with_finaliser(sizeof(type), false))) +#define m_new_obj_var_with_finaliser(type, var_type, var_num) ((type*)m_malloc_with_finaliser(sizeof(type) + sizeof(var_type) * (var_num), false)) +#define m_new_ll_obj_with_finaliser(type) ((type*)(m_malloc_with_finaliser(sizeof(type), true))) #else #define m_new_obj_with_finaliser(type) m_new_obj(type) #define m_new_obj_var_with_finaliser(type, var_type, var_num) m_new_obj_var(type, var_type, var_num) +#define m_new_ll_obj_with_finaliser(type) m_new_ll_obj(type) #endif #if MICROPY_MALLOC_USES_ALLOCATED_SIZE #define m_renew(type, ptr, old_num, new_num) ((type*)(m_realloc((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num)))) @@ -93,7 +95,7 @@ typedef unsigned int uint; void *m_malloc(size_t num_bytes, bool long_lived); void *m_malloc_maybe(size_t num_bytes, bool long_lived); -void *m_malloc_with_finaliser(size_t num_bytes); +void *m_malloc_with_finaliser(size_t num_bytes, bool long_lived); void *m_malloc0(size_t num_bytes, bool long_lived); #if MICROPY_MALLOC_USES_ALLOCATED_SIZE void *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes); diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index f48109fde..06647e779 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -55,7 +55,7 @@ //| :param ~microcontroller.Pin rs485_dir: the output pin for rs485 direction setting, or ``None`` if rs485 not in use. //| :param bool rs485_invert: rs485_dir pin active high when set. Active low otherwise. //| :param int baudrate: the transmit and receive speed. -//| :param int bits: the number of bits per byte, 7, 8 or 9. +//| :param int bits: the number of bits per byte, 5 to 9. //| :param Parity parity: the parity used for error checking. //| :param int stop: the number of stop bits, 1 or 2. //| :param float timeout: the timeout in seconds to wait for the first character and between subsequent characters when reading. Raises ``ValueError`` if timeout >100 seconds. @@ -82,7 +82,7 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co // This is needed to avoid crashes with certain UART implementations which // cannot accomodate being moved after creation. (See // https://github.com/adafruit/circuitpython/issues/1056) - busio_uart_obj_t *self = m_new_ll_obj(busio_uart_obj_t); + busio_uart_obj_t *self = m_new_ll_obj_with_finaliser(busio_uart_obj_t); self->base.type = &busio_uart_type; enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_timeout, ARG_receiver_buffer_size, ARG_rts, ARG_cts, ARG_rs485_dir,ARG_rs485_invert}; @@ -110,10 +110,10 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co mp_raise_ValueError(translate("tx and rx cannot both be None")); } - uint8_t bits = args[ARG_bits].u_int; - if (bits < 7 || bits > 9) { - mp_raise_ValueError(translate("bits must be 7, 8 or 9")); + if (args[ARG_bits].u_int < 5 || args[ARG_bits].u_int > 9) { + mp_raise_ValueError(translate("bits must be in range 5 to 9")); } + uint8_t bits = args[ARG_bits].u_int; busio_uart_parity_t parity = BUSIO_UART_PARITY_NONE; if (args[ARG_parity].u_obj == &busio_uart_parity_even_obj) { @@ -387,6 +387,7 @@ const mp_obj_type_t busio_uart_parity_type = { }; STATIC const mp_rom_map_elem_t busio_uart_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&busio_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&busio_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&busio_uart___exit___obj) }, diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c index cf34f2d35..c9ea83428 100644 --- a/shared-module/displayio/Bitmap.c +++ b/shared-module/displayio/Bitmap.c @@ -130,14 +130,14 @@ void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16 // simplest version - use internal functions for get/set pixels for (int16_t i=0; i < (x2-x1); i++) { - const int xs_index = x_reverse ? ( (x2 - 1) - i ) : x1+i; // x-index into the source bitmap - const int xd_index = x_reverse ? ((x + (x2-x1)) - i ) : x+i; // x-index into the destination bitmap + const int xs_index = x_reverse ? ( (x2) - i - 1) : x1+i; // x-index into the source bitmap + const int xd_index = x_reverse ? ((x + (x2-x1)) - i - 1) : x+i; // x-index into the destination bitmap if ( (xd_index >= 0) && (xd_index < self->width) ) { for (int16_t j=0; j < (y2-y1) ; j++){ - const int ys_index = y_reverse ? ( (y2 - 1) - j ) : y1+j ; // y-index into the source bitmap - const int yd_index = y_reverse ? ((y + (y2-y1)) - j ) : y+j ; // y-index into the destination bitmap + const int ys_index = y_reverse ? ( (y2 ) - j - 1) : y1+j ; // y-index into the source bitmap + const int yd_index = y_reverse ? ((y + (y2-y1)) - j - 1) : y+j ; // y-index into the destination bitmap if ((yd_index >= 0) && (yd_index < self->height) ) { uint32_t value = common_hal_displayio_bitmap_get_pixel(source, xs_index, ys_index); diff --git a/supervisor/shared/usb/tusb_config.h b/supervisor/shared/usb/tusb_config.h index bff7bd6b5..676810119 100644 --- a/supervisor/shared/usb/tusb_config.h +++ b/supervisor/shared/usb/tusb_config.h @@ -70,7 +70,7 @@ #define CFG_TUD_CDC 1 #endif -#define CFG_TUD_MSC 1 +#define CFG_TUD_MSC CIRCUITPY_USB_MSC #define CFG_TUD_HID CIRCUITPY_USB_HID #define CFG_TUD_MIDI CIRCUITPY_USB_MIDI #define CFG_TUD_VENDOR CIRCUITPY_USB_VENDOR diff --git a/supervisor/shared/usb/usb.c b/supervisor/shared/usb/usb.c index aa35b95e6..614bf85e0 100644 --- a/supervisor/shared/usb/usb.c +++ b/supervisor/shared/usb/usb.c @@ -131,12 +131,16 @@ void usb_irq_handler(void) { // Invoked when device is mounted void tud_mount_cb(void) { +#if CIRCUITPY_USB_MSC usb_msc_mount(); +#endif } // Invoked when device is unmounted void tud_umount_cb(void) { +#if CIRCUITPY_USB_MSC usb_msc_umount(); +#endif } // Invoked when usb bus is suspended diff --git a/tests/circuitpython-manual/busio/uart_echo.py b/tests/circuitpython-manual/busio/uart_echo.py new file mode 100644 index 000000000..f55d4db9e --- /dev/null +++ b/tests/circuitpython-manual/busio/uart_echo.py @@ -0,0 +1,18 @@ +import busio +import board +import time + +i = 0 + +u = busio.UART(tx=board.TX, rx=board.RX) + +while True: + u.write(str(i).encode("utf-8")) + time.sleep(0.1) + print(i, u.in_waiting) # should be the number of digits + time.sleep(0.1) + print(i, u.in_waiting) # should be the number of digits + r = u.read(64 + 10) + print(i, u.in_waiting) # should be 0 + print(len(r), r) + i += 1 |
