summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--locale/circuitpython.pot22
-rw-r--r--locale/es.po18
-rw-r--r--locale/pt_BR.po17
-rw-r--r--locale/sv.po18
-rw-r--r--ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.mk2
-rw-r--r--ports/mimxrt10xx/common-hal/busio/UART.c8
-rw-r--r--ports/nrf/common-hal/busio/UART.c8
-rw-r--r--ports/raspberrypi/boards/adafruit_feather_rp2040/board.c4
-rw-r--r--ports/raspberrypi/boards/adafruit_feather_rp2040/pins.c7
-rw-r--r--ports/raspberrypi/common-hal/busio/UART.c527
-rw-r--r--ports/raspberrypi/common-hal/busio/UART.h23
-rw-r--r--ports/raspberrypi/common-hal/digitalio/DigitalInOut.c28
-rw-r--r--ports/raspberrypi/common-hal/pwmio/PWMOut.c3
-rw-r--r--ports/raspberrypi/common-hal/rp2pio/StateMachine.c2
-rw-r--r--ports/raspberrypi/supervisor/port.c7
-rwxr-xr-xpy/gc.c2
-rw-r--r--py/malloc.c6
-rw-r--r--py/misc.h8
-rw-r--r--shared-bindings/busio/UART.c11
-rw-r--r--shared-module/displayio/Bitmap.c8
-rw-r--r--supervisor/shared/usb/tusb_config.h2
-rw-r--r--supervisor/shared/usb/usb.c4
-rw-r--r--tests/circuitpython-manual/busio/uart_echo.py18
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
diff --git a/py/gc.c b/py/gc.c
index 69327060f..2aa2668dc 100755
--- a/py/gc.c
+++ b/py/gc.c
@@ -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);
}
diff --git a/py/misc.h b/py/misc.h
index 6ed256e70..0fef7e249 100644
--- a/py/misc.h
+++ b/py/misc.h
@@ -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