Skip to content

Commit 5d7fdaf

Browse files
committed
implement suggested changes
- add internal buffering - rtc initialization fix
1 parent b12ccef commit 5d7fdaf

File tree

7 files changed

+107
-66
lines changed

7 files changed

+107
-66
lines changed

locale/circuitpython.pot

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -332,11 +332,8 @@ msgid "All SPI peripherals are in use"
332332
msgstr ""
333333

334334
#: ports/esp32s2/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c
335-
msgid "All UART peripherals are in use"
336-
msgstr ""
337-
338335
#: ports/raspberrypi/common-hal/busio/UART.c
339-
msgid "All UART peripherals in use"
336+
msgid "All UART peripherals are in use"
340337
msgstr ""
341338

342339
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
@@ -947,6 +944,7 @@ msgid "Failed to acquire mutex, err 0x%04x"
947944
msgstr ""
948945

949946
#: ports/mimxrt10xx/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c
947+
#: ports/raspberrypi/common-hal/busio/UART.c
950948
msgid "Failed to allocate RX buffer"
951949
msgstr ""
952950

@@ -1202,7 +1200,8 @@ msgstr ""
12021200
msgid "Invalid bits per value"
12031201
msgstr ""
12041202

1205-
#: ports/nrf/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c
1203+
#: ports/nrf/common-hal/busio/UART.c ports/raspberrypi/common-hal/busio/UART.c
1204+
#: ports/stm/common-hal/busio/UART.c
12061205
msgid "Invalid buffer size"
12071206
msgstr ""
12081207

@@ -1277,8 +1276,7 @@ msgstr ""
12771276
#: ports/esp32s2/common-hal/busio/I2C.c ports/esp32s2/common-hal/busio/SPI.c
12781277
#: ports/esp32s2/common-hal/busio/UART.c ports/esp32s2/common-hal/canio/CAN.c
12791278
#: ports/mimxrt10xx/common-hal/busio/I2C.c
1280-
#: ports/mimxrt10xx/common-hal/busio/SPI.c
1281-
#: ports/mimxrt10xx/common-hal/busio/UART.c ports/nrf/common-hal/busio/I2C.c
1279+
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/nrf/common-hal/busio/I2C.c
12821280
#: ports/raspberrypi/common-hal/busio/I2C.c
12831281
#: ports/raspberrypi/common-hal/busio/SPI.c
12841282
#: ports/raspberrypi/common-hal/busio/UART.c
@@ -1330,7 +1328,8 @@ msgstr ""
13301328
msgid "Invalid wave file"
13311329
msgstr ""
13321330

1333-
#: ports/stm/common-hal/busio/UART.c
1331+
#: ports/mimxrt10xx/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c
1332+
#: ports/raspberrypi/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c
13341333
msgid "Invalid word/bit length"
13351334
msgstr ""
13361335

@@ -1820,7 +1819,7 @@ msgstr ""
18201819
msgid "RNG Init Error"
18211820
msgstr ""
18221821

1823-
#: ports/nrf/common-hal/busio/UART.c
1822+
#: ports/nrf/common-hal/busio/UART.c ports/raspberrypi/common-hal/busio/UART.c
18241823
msgid "RS485 Not yet supported on this device"
18251824
msgstr ""
18261825

@@ -1829,10 +1828,6 @@ msgstr ""
18291828
msgid "RS485 inversion specified when not in RS485 mode"
18301829
msgstr ""
18311830

1832-
#: ports/raspberrypi/common-hal/busio/UART.c
1833-
msgid "RS485 is not supported on this board"
1834-
msgstr ""
1835-
18361831
#: ports/cxd56/common-hal/rtc/RTC.c ports/esp32s2/common-hal/rtc/RTC.c
18371832
#: ports/mimxrt10xx/common-hal/rtc/RTC.c ports/nrf/common-hal/rtc/RTC.c
18381833
#: ports/raspberrypi/common-hal/rtc/RTC.c
@@ -2460,7 +2455,7 @@ msgid "binary op %q not implemented"
24602455
msgstr ""
24612456

24622457
#: shared-bindings/busio/UART.c
2463-
msgid "bits must be between 5 and 8"
2458+
msgid "bits must be in range 5 to 9"
24642459
msgstr ""
24652460

24662461
#: shared-bindings/audiomixer/Mixer.c

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
9393
self->character_bits = bits;
9494
self->timeout_ms = timeout * 1000;
9595

96+
if (self->character_bits != 7 && self->character_bits != 8) {
97+
mp_raise_ValueError(translate("Invalid word/bit length"));
98+
}
99+
96100
// We are transmitting one direction if one pin is NULL and the other isn't.
97101
bool is_onedirection = (rx == NULL) != (tx == NULL);
98102
bool uart_taken = false;
@@ -154,10 +158,6 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
154158
mp_raise_ValueError(translate("Hardware in use, try alternative pins"));
155159
}
156160

157-
if(self->rx == NULL && self->tx == NULL) {
158-
mp_raise_ValueError(translate("Invalid pins"));
159-
}
160-
161161
if (is_onedirection && ((rts != NULL) || (cts != NULL))) {
162162
mp_raise_ValueError(translate("Both RX and TX required for flow control"));
163163
}

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ static uint32_t get_nrf_baud (uint32_t baudrate) {
7070
{ 14400, NRF_UARTE_BAUDRATE_14400 },
7171
{ 19200, NRF_UARTE_BAUDRATE_19200 },
7272
{ 28800, NRF_UARTE_BAUDRATE_28800 },
73-
{ 31250, NRF_UARTE_BAUDRATE_31250 },
73+
{ 31250, NRF_UARTE_BAUDRATE_31250 },
7474
{ 38400, NRF_UARTE_BAUDRATE_38400 },
75-
{ 56000, NRF_UARTE_BAUDRATE_56000 },
75+
{ 56000, NRF_UARTE_BAUDRATE_56000 },
7676
{ 57600, NRF_UARTE_BAUDRATE_57600 },
7777
{ 76800, NRF_UARTE_BAUDRATE_76800 },
7878
{ 115200, NRF_UARTE_BAUDRATE_115200 },
@@ -144,6 +144,10 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
144144
mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer,
145145
bool sigint_enabled) {
146146

147+
if (bits != 8) {
148+
mp_raise_ValueError(translate("Invalid word/bit length"));
149+
}
150+
147151
if ((rs485_dir != NULL) || (rs485_invert)) {
148152
mp_raise_ValueError(translate("RS485 Not yet supported on this device"));
149153
}

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

Lines changed: 74 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,15 @@
3131
#include "py/runtime.h"
3232
#include "supervisor/shared/tick.h"
3333
#include "lib/utils/interrupt_char.h"
34+
#include "common-hal/microcontroller/Pin.h"
3435

36+
#include "src/rp2_common/hardware_irq/include/hardware/irq.h"
3537
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
3638

3739
#define NO_PIN 0xff
3840

3941
#define UART_INST(uart) (((uart) ? uart1 : uart0))
4042

41-
#define TX 0
42-
#define RX 1
43-
#define CTS 2
44-
#define RTS 3
45-
4643
typedef enum {
4744
STATUS_FREE = 0,
4845
STATUS_IN_USE,
@@ -51,7 +48,7 @@ typedef enum {
5148

5249
static uart_status_t uart_status[2];
5350

54-
void uart_reset(void) {
51+
void reset_uart(void) {
5552
for (uint8_t num = 0; num < 2; num++) {
5653
if (uart_status[num] == STATUS_IN_USE) {
5754
uart_status[num] = STATUS_FREE;
@@ -71,7 +68,7 @@ static uint8_t get_free_uart() {
7168
break;
7269
}
7370
if (num) {
74-
mp_raise_RuntimeError(translate("All UART peripherals in use"));
71+
mp_raise_RuntimeError(translate("All UART peripherals are in use"));
7572
}
7673
}
7774
return num;
@@ -84,10 +81,21 @@ static uint8_t pin_init(const uint8_t uart, const mcu_pin_obj_t * pin, const uin
8481
if (!(((pin->number & 3) == pin_type) && ((((pin->number + 4) & 8) >> 3) == uart))) {
8582
mp_raise_ValueError(translate("Invalid pins"));
8683
}
84+
claim_pin(pin);
8785
gpio_set_function(pin->number, GPIO_FUNC_UART);
8886
return pin->number;
8987
}
9088

89+
static ringbuf_t ringbuf[2];
90+
91+
static void uart0_callback(void) {
92+
while (uart_is_readable(uart0) && !ringbuf_put(&ringbuf[0], (uint8_t)uart_get_hw(uart0)->dr)) {}
93+
}
94+
95+
static void uart1_callback(void) {
96+
while (uart_is_readable(uart1) && !ringbuf_put(&ringbuf[1], (uint8_t)uart_get_hw(uart1)->dr)) {}
97+
}
98+
9199
void common_hal_busio_uart_construct(busio_uart_obj_t *self,
92100
const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx,
93101
const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts,
@@ -96,25 +104,56 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
96104
mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer,
97105
bool sigint_enabled) {
98106

107+
if (bits > 8) {
108+
mp_raise_ValueError(translate("Invalid word/bit length"));
109+
}
110+
111+
if (receiver_buffer_size == 0) {
112+
mp_raise_ValueError(translate("Invalid buffer size"));
113+
}
114+
99115
if ((rs485_dir != NULL) || (rs485_invert)) {
100-
mp_raise_NotImplementedError(translate("RS485 is not supported on this board"));
116+
mp_raise_NotImplementedError(translate("RS485 Not yet supported on this device"));
101117
}
102118

103119
uint8_t uart_id = get_free_uart();
104120

105-
self->tx_pin = pin_init(uart_id, tx, TX);
106-
self->rx_pin = pin_init(uart_id, rx, RX);
107-
self->cts_pin = pin_init(uart_id, cts, CTS);
108-
self->rts_pin = pin_init(uart_id, rts, RTS);
121+
self->tx_pin = pin_init(uart_id, tx, 0);
122+
self->rx_pin = pin_init(uart_id, rx, 1);
123+
self->cts_pin = pin_init(uart_id, cts, 2);
124+
self->rts_pin = pin_init(uart_id, rts, 3);
109125

110126
self->uart = UART_INST(uart_id);
127+
self->uart_id = uart_id;
111128
self->baudrate = baudrate;
112129
self->timeout_ms = timeout * 1000;
113130

114131
uart_init(self->uart, self->baudrate);
115-
uart_set_fifo_enabled(self->uart, true);
132+
uart_set_fifo_enabled(self->uart, false);
116133
uart_set_format(self->uart, bits, stop, parity);
117134
uart_set_hw_flow(self->uart, (cts != NULL), (rts != NULL));
135+
136+
if (rx != NULL) {
137+
// Initially allocate the UART's buffer in the long-lived part of the
138+
// heap. UARTs are generally long-lived objects, but the "make long-
139+
// lived" machinery is incapable of moving internal pointers like
140+
// self->buffer, so do it manually. (However, as long as internal
141+
// pointers like this are NOT moved, allocating the buffer
142+
// in the long-lived pool is not strictly necessary)
143+
// (This is a macro.)
144+
if (!ringbuf_alloc(&ringbuf[uart_id], receiver_buffer_size, true)) {
145+
mp_raise_msg(&mp_type_MemoryError, translate("Failed to allocate RX buffer"));
146+
}
147+
if (uart_id) {
148+
self->uart_irq_id = UART1_IRQ;
149+
irq_set_exclusive_handler(self->uart_irq_id, uart1_callback);
150+
} else {
151+
self->uart_irq_id = UART0_IRQ;
152+
irq_set_exclusive_handler(self->uart_irq_id, uart0_callback);
153+
}
154+
irq_set_enabled(self->uart_irq_id, true);
155+
uart_set_irq_enables(self->uart, true, false);
156+
}
118157
}
119158

120159
bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) {
@@ -126,6 +165,7 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
126165
return;
127166
}
128167
uart_deinit(self->uart);
168+
ringbuf_free(&ringbuf[self->uart_id]);
129169
reset_pin_number(self->tx_pin);
130170
reset_pin_number(self->rx_pin);
131171
reset_pin_number(self->cts_pin);
@@ -169,36 +209,25 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
169209
size_t total_read = 0;
170210
uint64_t start_ticks = supervisor_ticks_ms64();
171211

172-
// Busy-wait until timeout or until we've read enough chars.
173-
while (supervisor_ticks_ms64() - start_ticks <= self->timeout_ms) {
174-
if (uart_is_readable(self->uart)) {
175-
// Read and advance.
176-
*data++ = uart_get_hw(self->uart)->dr;
177-
178-
// Decrease how many chars left to read.
179-
len--;
180-
total_read++;
181-
182-
// Reset the timeout on every character read.
212+
// Busy-wait for all bytes received or timeout
213+
while (len > 0 && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms)) {
214+
// Reset the timeout on every character read.
215+
if (ringbuf_num_filled(&ringbuf[self->uart_id])) {
216+
// Prevent conflict with uart irq.
217+
irq_set_enabled(self->uart_irq_id, false);
218+
// Copy as much received data as available, up to len bytes.
219+
size_t num_read = ringbuf_get_n(&ringbuf[self->uart_id], data, len);
220+
// Re-enable irq.
221+
irq_set_enabled(self->uart_irq_id, true);
222+
len-=num_read;
223+
data+=num_read;
224+
total_read+=num_read;
183225
start_ticks = supervisor_ticks_ms64();
184226
}
185-
186227
RUN_BACKGROUND_TASKS;
187-
188228
// Allow user to break out of a timeout with a KeyboardInterrupt.
189229
if (mp_hal_is_interrupted()) {
190-
break;
191-
}
192-
193-
// Don't need to read any more: data buf is full.
194-
if (len == 0) {
195-
break;
196-
}
197-
198-
// If we are zero timeout, make sure we don't loop again (in the event
199-
// we read in under 1ms)
200-
if (self->timeout_ms == 0) {
201-
break;
230+
return 0;
202231
}
203232
}
204233

@@ -228,12 +257,16 @@ void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeou
228257
}
229258

230259
uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) {
231-
return uart_is_readable(self->uart);
260+
return ringbuf_num_filled(&ringbuf[self->uart_id]);
232261
}
233262

234-
void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {}
263+
void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
264+
// Prevent conflict with uart irq.
265+
irq_set_enabled(self->uart_irq_id, false);
266+
ringbuf_clear(&ringbuf[self->uart_id]);
267+
irq_set_enabled(self->uart_irq_id, true);
268+
}
235269

236-
// True if there are no characters still to be written.
237270
bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) {
238271
if (self->tx_pin == NO_PIN) {
239272
return false;

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_BUSIO_UART_H
2929

3030
#include "py/obj.h"
31-
#include "common-hal/microcontroller/Pin.h"
31+
#include "py/ringbuf.h"
3232

3333
#include "src/rp2_common/hardware_uart/include/hardware/uart.h"
3434

@@ -38,12 +38,14 @@ typedef struct {
3838
uint8_t rx_pin;
3939
uint8_t cts_pin;
4040
uint8_t rts_pin;
41+
uint8_t uart_id;
42+
uint8_t uart_irq_id;
4143
uint32_t baudrate;
4244
uint32_t timeout_ms;
4345
uart_inst_t * uart;
4446
} busio_uart_obj_t;
4547

46-
extern void uart_reset(void);
48+
extern void reset_uart(void);
4749
extern void never_reset_uart(uint8_t num);
4850

4951
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_BUSIO_UART_H

ports/raspberrypi/supervisor/port.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
#include "shared-bindings/rtc/__init__.h"
4040
#include "shared-bindings/pwmio/PWMOut.h"
4141

42+
#include "common-hal/rtc/RTC.h"
43+
#include "common-hal/busio/UART.h"
44+
4245
#include "supervisor/shared/safe_mode.h"
4346
#include "supervisor/shared/stack.h"
4447
#include "supervisor/shared/tick.h"
@@ -78,6 +81,9 @@ safe_mode_t port_init(void) {
7881
// Reset everything into a known state before board_init.
7982
reset_port();
8083

84+
// Initialize RTC
85+
common_hal_rtc_init();
86+
8187
// For the tick.
8288
hardware_alarm_claim(0);
8389
hardware_alarm_set_callback(0, _tick_callback);
@@ -95,6 +101,7 @@ void reset_port(void) {
95101
#if CIRCUITPY_BUSIO
96102
reset_i2c();
97103
reset_spi();
104+
reset_uart();
98105
#endif
99106

100107
#if CIRCUITPY_PWMIO

0 commit comments

Comments
 (0)