Skip to content

Commit 0f9ea29

Browse files
committed
Correct ringbuffer code for ports/analog BUSIO
- Add correct ringbuffer handling code to ports/analog/common-hal/UART.c Signed-off-by: Brandon Hurst <[email protected]>
1 parent deda980 commit 0f9ea29

File tree

2 files changed

+63
-48
lines changed

2 files changed

+63
-48
lines changed

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

Lines changed: 59 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,27 @@
2424
* THE SOFTWARE.
2525
*/
2626

27+
/** TODO:
28+
* - Fix readline issue
29+
*
30+
*/
31+
2732
#if CIRCUITPY_BUSIO_UART
2833

34+
#include "mpconfigport.h"
35+
#include "supervisor/shared/tick.h"
36+
2937
#include "shared-bindings/microcontroller/__init__.h"
3038
#include "shared-bindings/microcontroller/Pin.h"
31-
#include "supervisor/shared/tick.h"
3239
#include "shared-bindings/busio/UART.h"
33-
3440
#include "shared-bindings/microcontroller/Pin.h"
35-
36-
#include "mpconfigport.h"
3741
#include "shared/readline/readline.h"
3842
#include "shared/runtime/interrupt_char.h"
43+
3944
#include "py/gc.h"
45+
#include "py/ringbuf.h"
4046
#include "py/mperrno.h"
47+
#include "py/mpprint.h"
4148
#include "py/runtime.h"
4249

4350
#include "max32_port.h"
@@ -47,29 +54,6 @@
4754
// UART IRQ Priority
4855
#define UART_PRIORITY 1
4956

50-
/**
51-
*
52-
// Define a struct for what BUSIO.UART should contain
53-
typedef struct {
54-
mp_obj_base_t base;
55-
int uart_id;
56-
mxc_uart_regs_t* uart_regs;
57-
58-
const mcu_pin_obj_t *rx_pin;
59-
const mcu_pin_obj_t *tx_pin;
60-
const mcu_pin_obj_t *rts_pin;
61-
const mcu_pin_obj_t *cts_pin;
62-
63-
uint8_t bits;
64-
uint32_t baudrate;
65-
bool parity;
66-
uint8_t stop_bits;
67-
68-
uint32_t timeout_ms;
69-
bool error;
70-
} busio_uart_obj_t;
71-
*/
72-
7357
typedef enum {
7458
UART_9600 = 9600,
7559
UART_14400 = 14400,
@@ -82,7 +66,6 @@ typedef enum {
8266
UART_921600 = 921600,
8367
} uart_valid_baudrates;
8468

85-
8669
typedef enum {
8770
UART_FREE = 0,
8871
UART_BUSY,
@@ -97,6 +80,7 @@ static uint8_t uarts_active = 0;
9780
static uart_status_t uart_status[NUM_UARTS];
9881
static volatile int uart_err;
9982
static uint8_t uart_never_reset_mask = 0;
83+
static busio_uart_obj_t *context;
10084

10185
static int isValidBaudrate(uint32_t baudrate) {
10286
switch (baudrate) {
@@ -159,6 +143,10 @@ void uart_isr(void) {
159143
static volatile void uartCallback(mxc_uart_req_t *req, int error) {
160144
uart_status[MXC_UART_GET_IDX(req->uart)] = UART_FREE;
161145
uart_err = error;
146+
147+
MXC_SYS_Crit_Enter();
148+
ringbuf_put_n(context->ringbuf, req->rxData, req->rxLen);
149+
MXC_SYS_Crit_Exit();
162150
}
163151

164152
// Construct an underlying UART object.
@@ -183,9 +171,15 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
183171
self->uart_id = temp;
184172
self->uart_regs = MXC_UART_GET_UART(temp);
185173
}
186-
187174
assert((self->uart_id >= 0) && (self->uart_id < NUM_UARTS));
188175

176+
// Check for size of ringbuffer, desire powers of 2
177+
// At least use 1 byte if no size is given
178+
assert((receiver_buffer_size & (receiver_buffer_size - 1)) == 0);
179+
if (receiver_buffer_size == 0) {
180+
receiver_buffer_size += 1;
181+
}
182+
189183
// Indicate RS485 not implemented
190184
if ((rs485_dir != NULL) || (rs485_invert)) {
191185
mp_raise_NotImplementedError(MP_ERROR_TEXT("RS485"));
@@ -246,12 +240,31 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
246240
self->timeout = timeout;
247241
}
248242

249-
/* Setup UART interrupt */
243+
// Initialize ringbuffer
244+
if (receiver_buffer == NULL) {
245+
self->ringbuf = gc_alloc(receiver_buffer_size, false);
246+
if (!ringbuf_alloc(self->ringbuf, receiver_buffer_size)) {
247+
m_malloc_fail(receiver_buffer_size);
248+
mp_raise_RuntimeError(MP_ERROR_TEXT("ERR: Could not init ringbuffer\n"));
249+
}
250+
} else {
251+
if (!(ringbuf_init(self->ringbuf, receiver_buffer, receiver_buffer_size))) {
252+
mp_raise_RuntimeError(MP_ERROR_TEXT("ERR: Could not init ringbuffer\n"));
253+
}
254+
;
255+
}
256+
257+
context = self;
258+
259+
// Setup UART interrupt
260+
250261
NVIC_ClearPendingIRQ(MXC_UART_GET_IRQ(self->uart_id));
251262
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
252263
NVIC_SetPriority(MXC_UART_GET_IRQ(self->uart_id), UART_PRIORITY);
253264
NVIC_SetVector(MXC_UART_GET_IRQ(self->uart_id), (uint32_t)uart_isr);
254265

266+
NVIC_EnableIRQ(MXC_UART_GET_IRQ(self->uart_id));
267+
255268
return;
256269
}
257270

@@ -260,7 +273,7 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
260273

261274
if (!common_hal_busio_uart_deinited(self)) {
262275
// First disable the ISR to avoid pre-emption
263-
NVIC_DisableIRQ(UART0_IRQn);
276+
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
264277

265278
// Shutdown the UART Controller
266279
MXC_UART_Shutdown(self->uart_regs);
@@ -280,6 +293,8 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
280293
self->cts_pin = NULL;
281294
self->rts_pin = NULL;
282295

296+
ringbuf_deinit(self->ringbuf);
297+
283298
// Indicate to this module that the UART is not active
284299
uarts_active &= ~(1 << self->uart_id);
285300
}
@@ -306,8 +321,6 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self,
306321
uart_status[self->uart_id] = UART_BUSY;
307322
bytes_remaining = len;
308323

309-
NVIC_EnableIRQ(MXC_UART_GET_IRQ(self->uart_id));
310-
311324
mxc_uart_req_t uart_rd_req;
312325
uart_rd_req.rxCnt = 0;
313326
uart_rd_req.txCnt = 0;
@@ -341,13 +354,16 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self,
341354
}
342355
// Check for errors from the callback
343356
else if (uart_err != E_NO_ERROR) {
357+
mp_printf(&mp_sys_stdout_print, "MAX32 ERR: %d\n", uart_err);
344358
MXC_UART_AbortAsync(self->uart_regs);
345-
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
346-
mp_raise_RuntimeError_varg(MP_ERROR_TEXT("MAX32 ERR: %d\n"), uart_err);
347359
}
348360

349-
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
350-
return len;
361+
// Copy the data from the ringbuf (or return error)
362+
MXC_SYS_Crit_Enter();
363+
err = ringbuf_get_n(context->ringbuf, data, len);
364+
MXC_SYS_Crit_Exit();
365+
366+
return err;
351367
}
352368

353369
// Write characters. len is in characters NOT bytes!
@@ -391,11 +407,10 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self,
391407
(supervisor_ticks_ms64() - start_time < (self->timeout * 1000))) {
392408

393409
// Call the handler and abort if errors
394-
uart_err = MXC_UART_AsyncHandler(MXC_UART_GET_UART(0));
410+
uart_err = MXC_UART_AsyncHandler(self->uart_regs);
395411
if (uart_err != E_NO_ERROR) {
396-
MXC_UART_AbortAsync(MXC_UART_GET_UART(0));
397-
NVIC_DisableIRQ(MXC_UART_GET_IRQ(0));
398-
mp_raise_RuntimeError_varg(MP_ERROR_TEXT("MAX32 ERR: %d\n"), uart_err);
412+
mp_printf(&mp_sys_stdout_print, "MAX32 ERR: %d\n", uart_err);
413+
MXC_UART_AbortAsync(self->uart_regs);
399414
}
400415
}
401416

@@ -407,9 +422,8 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self,
407422
}
408423
// Check for errors from the callback
409424
else if (uart_err != E_NO_ERROR) {
425+
mp_printf(&mp_sys_stdout_print, "MAX32 ERR: %d\n", uart_err);
410426
MXC_UART_AbortAsync(self->uart_regs);
411-
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
412-
mp_raise_RuntimeError_varg(MP_ERROR_TEXT("MAX32 ERR: %d\n"), uart_err);
413427
}
414428

415429
return len;
@@ -444,11 +458,12 @@ void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeou
444458
}
445459

446460
uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) {
447-
return MXC_UART_GetRXFIFOAvailable(self->uart_regs);
461+
return ringbuf_num_filled(self->ringbuf);
448462
}
449463

450464
void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
451465
MXC_UART_ClearRXFIFO(self->uart_regs);
466+
ringbuf_clear(self->ringbuf);
452467
}
453468

454469
bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) {

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,25 @@
99

1010
#include "common-hal/microcontroller/Pin.h"
1111
#include "py/obj.h"
12+
#include "py/ringbuf.h"
1213

1314
#include "max32_port.h"
1415

1516
// Define a struct for what BUSIO.UART should contain
1617
typedef struct {
1718
mp_obj_base_t base;
19+
int error;
20+
float timeout;
1821

1922
int uart_id;
2023
int uart_map;
2124
mxc_uart_regs_t *uart_regs;
22-
25+
ringbuf_t *ringbuf;
2326
bool parity;
2427
uint8_t bits;
2528
uint8_t stop_bits;
2629
uint32_t baudrate;
2730

28-
int error;
29-
float timeout;
30-
3131
const mcu_pin_obj_t *rx_pin;
3232
const mcu_pin_obj_t *tx_pin;
3333
const mcu_pin_obj_t *rts_pin;

0 commit comments

Comments
 (0)