Skip to content

Commit ced3dc7

Browse files
authored
Merge pull request #4018 from iot49/cp-flow
add uart hardware flow control to nrf port
2 parents db7a962 + 745ba01 commit ced3dc7

File tree

4 files changed

+66
-10
lines changed

4 files changed

+66
-10
lines changed

locale/circuitpython.pot

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1793,6 +1793,10 @@ msgstr ""
17931793
msgid "RNG Init Error"
17941794
msgstr ""
17951795

1796+
#: ports/nrf/common-hal/busio/UART.c
1797+
msgid "RS485 Not yet supported on this device"
1798+
msgstr ""
1799+
17961800
#: ports/esp32s2/common-hal/busio/UART.c
17971801
#: ports/mimxrt10xx/common-hal/busio/UART.c
17981802
msgid "RS485 inversion specified when not in RS485 mode"
@@ -1808,7 +1812,7 @@ msgid "RTC is not supported on this board"
18081812
msgstr ""
18091813

18101814
#: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c
1811-
#: ports/nrf/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c
1815+
#: ports/stm/common-hal/busio/UART.c
18121816
msgid "RTS/CTS/RS485 Not yet supported on this device"
18131817
msgstr ""
18141818

ports/nrf/boards/simmel/mpconfigboard.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ USB_PID = 0xc051
33
USB_PRODUCT = "Simmel"
44
USB_MANUFACTURER = "Betrusted"
55

6+
CIRCUITPY_DEVICES="CDC,MSC,HID"
7+
68
MCU_CHIP = nrf52833
79

810
# SPI_FLASH_FILESYSTEM = 1
@@ -29,6 +31,7 @@ CIRCUITPY_RTC = 1
2931
CIRCUITPY_SDCARDIO = 0
3032
CIRCUITPY_TOUCHIO = 0
3133
CIRCUITPY_ULAB = 0
34+
CIRCUITPY_USB_MIDI = 0
3235
CIRCUITPY_WATCHDOG = 1
3336

3437
# Enable micropython.native

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

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "supervisor/shared/translate.h"
3737

3838
#include "nrfx_uarte.h"
39+
#include "nrf_gpio.h"
3940
#include <string.h>
4041

4142
// expression to examine, and return value in case of failing
@@ -98,10 +99,16 @@ static void uart_callback_irq (const nrfx_uarte_event_t * event, void * context)
9899

99100
switch ( event->type ) {
100101
case NRFX_UARTE_EVT_RX_DONE:
101-
ringbuf_put_n(&self->ringbuf, event->data.rxtx.p_data, event->data.rxtx.bytes);
102+
if (ringbuf_num_empty(&self->ringbuf) >= event->data.rxtx.bytes) {
103+
ringbuf_put_n(&self->ringbuf, event->data.rxtx.p_data, event->data.rxtx.bytes);
104+
// keep receiving
105+
(void) nrfx_uarte_rx(self->uarte, &self->rx_char, 1);
106+
} else {
107+
// receive buffer full, suspend
108+
self->rx_paused = true;
109+
nrf_gpio_pin_write(self->rts_pin_number, true);
110+
}
102111

103-
// keep receiving
104-
(void) nrfx_uarte_rx(self->uarte, &self->rx_char, 1);
105112
break;
106113

107114
case NRFX_UARTE_EVT_TX_DONE:
@@ -137,8 +144,8 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
137144
mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer,
138145
bool sigint_enabled) {
139146

140-
if ((rts != NULL) || (cts != NULL) || (rs485_dir != NULL) || (rs485_invert)) {
141-
mp_raise_ValueError(translate("RTS/CTS/RS485 Not yet supported on this device"));
147+
if ((rs485_dir != NULL) || (rs485_invert)) {
148+
mp_raise_ValueError(translate("RS485 Not yet supported on this device"));
142149
}
143150

144151
// Find a free UART peripheral.
@@ -166,16 +173,18 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
166173
mp_raise_ValueError(translate("Odd parity is not supported"));
167174
}
168175

176+
bool hwfc = rts != NULL || cts != NULL;
177+
169178
nrfx_uarte_config_t config = {
170179
.pseltxd = (tx == NULL) ? NRF_UARTE_PSEL_DISCONNECTED : tx->number,
171180
.pselrxd = (rx == NULL) ? NRF_UARTE_PSEL_DISCONNECTED : rx->number,
172-
.pselcts = NRF_UARTE_PSEL_DISCONNECTED,
173-
.pselrts = NRF_UARTE_PSEL_DISCONNECTED,
181+
.pselcts = (cts == NULL) ? NRF_UARTE_PSEL_DISCONNECTED : cts->number,
182+
.pselrts = (rts == NULL) ? NRF_UARTE_PSEL_DISCONNECTED : rts->number,
174183
.p_context = self,
175184
.baudrate = get_nrf_baud(baudrate),
176185
.interrupt_priority = 7,
177186
.hal_cfg = {
178-
.hwfc = NRF_UARTE_HWFC_DISABLED,
187+
.hwfc = hwfc ? NRF_UARTE_HWFC_ENABLED : NRF_UARTE_HWFC_DISABLED,
179188
.parity = (parity == BUSIO_UART_PARITY_NONE) ? NRF_UARTE_PARITY_EXCLUDED : NRF_UARTE_PARITY_INCLUDED
180189
}
181190
};
@@ -207,9 +216,25 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
207216
self->tx_pin_number = NO_PIN;
208217
}
209218

219+
if ( rts != NULL ) {
220+
self->rts_pin_number = rts->number;
221+
claim_pin(rts);
222+
} else {
223+
self->rts_pin_number = NO_PIN;
224+
}
225+
226+
if ( cts != NULL ) {
227+
self->cts_pin_number = cts->number;
228+
claim_pin(cts);
229+
} else {
230+
self->cts_pin_number = NO_PIN;
231+
}
232+
210233
self->baudrate = baudrate;
211234
self->timeout_ms = timeout * 1000;
212235

236+
self->rx_paused = false;
237+
213238
// Initial wait for incoming byte
214239
_VERIFY_ERR(nrfx_uarte_rx(self->uarte, &self->rx_char, 1));
215240
}
@@ -223,8 +248,12 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
223248
nrfx_uarte_uninit(self->uarte);
224249
reset_pin_number(self->tx_pin_number);
225250
reset_pin_number(self->rx_pin_number);
251+
reset_pin_number(self->rts_pin_number);
252+
reset_pin_number(self->cts_pin_number);
226253
self->tx_pin_number = NO_PIN;
227254
self->rx_pin_number = NO_PIN;
255+
self->rts_pin_number = NO_PIN;
256+
self->cts_pin_number = NO_PIN;
228257
ringbuf_free(&self->ringbuf);
229258
}
230259
}
@@ -237,6 +266,13 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
237266

238267
uint64_t start_ticks = supervisor_ticks_ms64();
239268

269+
// check removed to reduce code size
270+
/*
271+
if (len > ringbuf_capacity(&self->ringbuf)) {
272+
mp_raise_ValueError(translate("Reading >receiver_buffer_size bytes is not supported"));
273+
}
274+
*/
275+
240276
// Wait for all bytes received or timeout
241277
while ( (ringbuf_num_filled(&self->ringbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
242278
RUN_BACKGROUND_TASKS;
@@ -252,6 +288,16 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
252288
// Copy as much received data as available, up to len bytes.
253289
size_t rx_bytes = ringbuf_get_n(&self->ringbuf, data, len);
254290

291+
// restart reader, if stopped
292+
if (self->rx_paused) {
293+
// the character that did not fit in ringbuf is in rx_char
294+
ringbuf_put_n(&self->ringbuf, &self->rx_char, 1);
295+
// keep receiving
296+
(void) nrfx_uarte_rx(self->uarte, &self->rx_char, 1);
297+
nrf_gpio_pin_write(self->rts_pin_number, false);
298+
self->rx_paused = false;
299+
}
300+
255301
NVIC_EnableIRQ(nrfx_get_irq_number(self->uarte->p_reg));
256302

257303
return rx_bytes;

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,13 @@ typedef struct {
4242
uint32_t timeout_ms;
4343

4444
ringbuf_t ringbuf;
45-
uint8_t rx_char; // EasyDMA buf
45+
uint8_t rx_char; // EasyDMA buf
46+
bool rx_paused; // set by irq if no space in rbuf
4647

4748
uint8_t tx_pin_number;
4849
uint8_t rx_pin_number;
50+
uint8_t cts_pin_number;
51+
uint8_t rts_pin_number;
4952
} busio_uart_obj_t;
5053

5154
void uart_reset(void);

0 commit comments

Comments
 (0)