Skip to content

Commit 872e81c

Browse files
committed
Fix issues with UART reads and unreliable UART writes.
- No ISR for UART writes, but uses timeouts - Reads use ISRs, but also incorporate timeouts
1 parent 8848d43 commit 872e81c

File tree

1 file changed

+98
-64
lines changed
  • ports/analog/common-hal/busio

1 file changed

+98
-64
lines changed

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

Lines changed: 98 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ static uint32_t timeout_ms=0;
9595
// will be checked by ISR Handler for which ones to call
9696
static uint8_t uarts_active = 0;
9797
static uart_status_t uart_status[NUM_UARTS];
98+
static volatile int uart_err;
9899
// static uint8_t uart_never_reset_mask = 0;
99100

100101
static int isValidBaudrate(uint32_t baudrate) {
@@ -146,12 +147,9 @@ static mxc_uart_parity_t convertParity(busio_uart_parity_t busio_parity)
146147
}
147148
}
148149

149-
// FIXME: Find a better way of doing this without a for loop
150-
// FIXME: Fixed @ UART0 for TESTING BUGFIXES!!!
151150
void UART0_IRQHandler(void) {
152-
// MXC_UART_AsyncHandler(MXC_UART_GET_UART(0));
153-
for (int i=0; i < NUM_UARTS; i++) {
154-
if (uarts_active & (1 << i) ) {
151+
for (int i = 0; i < NUM_UARTS; i++) {
152+
if (uarts_active & (1 << i)) {
155153
MXC_UART_AsyncHandler(MXC_UART_GET_UART(i));
156154
}
157155
}
@@ -161,6 +159,7 @@ void UART0_IRQHandler(void) {
161159
// (e.g. txLen == txCnt)
162160
static volatile void uartCallback(mxc_uart_req_t *req, int error) {
163161
uart_status[MXC_UART_GET_IDX(req->uart)] = UART_FREE;
162+
uart_err = error;
164163
}
165164

166165
// Construct an underlying UART object.
@@ -262,7 +261,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
262261
uarts_active |= (1 << self->uart_id);
263262

264263

265-
/* Enable UART interrupt */
264+
/* Setup UART interrupt */
266265
NVIC_ClearPendingIRQ(MXC_UART_GET_IRQ(self->uart_id));
267266
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
268267
NVIC_SetPriority(MXC_UART_GET_IRQ(self->uart_id), UART_PRIORITY);
@@ -311,95 +310,130 @@ bool common_hal_busio_uart_deinited(busio_uart_obj_t *self)
311310
};
312311
}
313312

314-
// todo: test
315313
// Read characters. len is in characters NOT bytes!
316314
size_t common_hal_busio_uart_read(busio_uart_obj_t *self,
317315
uint8_t *data, size_t len, int *errcode)
318316
{
319317
int err;
318+
uint32_t start_time=0;
320319
static size_t bytes_remaining;
321320

322-
bytes_remaining = len * 4;
321+
// Setup globals & status tracking
322+
uart_err = E_NO_ERROR;
323+
uarts_active |= (1 << self->uart_id);
324+
uart_status[self->uart_id] = UART_BUSY;
325+
bytes_remaining = len;
323326

324-
MXC_UART_ClearFlags(self->uart_regs, 0xFFFFFFFF);
325327
NVIC_EnableIRQ(MXC_UART_GET_IRQ(self->uart_id));
326328

327-
while(bytes_remaining > 0) {
328-
mxc_uart_req_t uart_rd_req;
329-
uart_rd_req.rxCnt = 0;
330-
uart_rd_req.txCnt = 0;
331-
uart_rd_req.rxData = data;
332-
uart_rd_req.txData = NULL;
333-
uart_rd_req.rxLen = (uint32_t)( (bytes_remaining >= 255) ? 255 : bytes_remaining );
334-
uart_rd_req.txLen = 0;
335-
uart_rd_req.uart = self->uart_regs;
336-
uart_rd_req.callback = (void *)uartCallback;
337-
338-
err = MXC_UART_TransactionAsync(&uart_rd_req);
339-
if (err != E_NO_ERROR) {
340-
*errcode = err;
341-
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
342-
return ((len * 4) - bytes_remaining);
343-
}
344-
bytes_remaining -= uart_rd_req.rxLen;
329+
mxc_uart_req_t uart_rd_req;
330+
uart_rd_req.rxCnt = 0;
331+
uart_rd_req.txCnt = 0;
332+
uart_rd_req.rxData = data;
333+
uart_rd_req.txData = NULL;
334+
uart_rd_req.rxLen = bytes_remaining;
335+
uart_rd_req.txLen = 0;
336+
uart_rd_req.uart = self->uart_regs;
337+
uart_rd_req.callback = (void *)uartCallback;
338+
339+
// Initiate the read transaction
340+
start_time = supervisor_ticks_ms64();
341+
err = MXC_UART_TransactionAsync(&uart_rd_req);
342+
if (err != E_NO_ERROR) {
343+
*errcode = err;
344+
MXC_UART_AbortAsync(self->uart_regs);
345+
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
346+
mp_raise_RuntimeError_varg(MP_ERROR_TEXT("\nERR: Error starting trasaction: %d\n"), err);
345347
}
346-
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
347348

349+
// Wait for transaction completion or timeout
350+
while ( (uart_status[self->uart_id] != UART_FREE) &&
351+
(supervisor_ticks_ms64() - start_time < (self->timeout * 1000))) {
352+
}
353+
354+
// If the timeout gets hit, abort and error out
355+
if (uart_status[self->uart_id] != UART_FREE) {
356+
MXC_UART_AbortAsync(self->uart_regs);
357+
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
358+
mp_raise_RuntimeError(MP_ERROR_TEXT("\nERR: Uart transaction timed out.\n"));
359+
}
360+
361+
// Check for errors from the callback
362+
else if (uart_err != E_NO_ERROR) {
363+
MXC_UART_AbortAsync(self->uart_regs);
364+
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
365+
mp_raise_RuntimeError_varg(MP_ERROR_TEXT("MAX32 ERR: %d\n"), uart_err);
366+
}
367+
368+
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
348369
return len;
349370
}
350371

351-
//todo: test
352372
// Write characters. len is in characters NOT bytes!
373+
// This function blocks until the timeout finishes
353374
size_t common_hal_busio_uart_write(busio_uart_obj_t *self,
354375
const uint8_t *data, size_t len, int *errcode)
355376
{
356377
int err;
357378
uint32_t start_time=0;
358379
static size_t bytes_remaining;
359380

381+
// Setup globals & status tracking
382+
uart_err = E_NO_ERROR;
383+
uarts_active |= (1 << self->uart_id);
384+
uart_status[self->uart_id] = UART_BUSY;
360385
bytes_remaining = len;
361386

362-
MXC_UART_ClearFlags(self->uart_regs, 0xFFFFFFFF);
363-
NVIC_EnableIRQ(MXC_UART_GET_IRQ(self->uart_id));
364-
365-
while(bytes_remaining > 0) {
366-
mxc_uart_req_t uart_wr_req;
367-
uart_wr_req.rxCnt = 0;
368-
uart_wr_req.txCnt = 0;
369-
uart_wr_req.rxData = NULL;
370-
uart_wr_req.txData = data;
371-
uart_wr_req.txLen = bytes_remaining;
372-
uart_wr_req.rxLen = 0;
373-
uart_wr_req.uart = self->uart_regs;
374-
uart_wr_req.callback = (void *)uartCallback;
375-
376-
uart_status[self->uart_id] = UART_BUSY;
377-
start_time = supervisor_ticks_ms64();
378-
err = MXC_UART_TransactionAsync(&uart_wr_req);
379-
if (err != E_NO_ERROR) {
380-
*errcode = err;
381-
MXC_UART_AbortAsync(self->uart_regs);
382-
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
383-
mp_raise_ConnectionError(MP_ERROR_TEXT("\nERR: Requested bus is busy\n"));
384-
}
387+
mxc_uart_req_t uart_wr_req = {};
388+
389+
// Setup transaction
390+
uart_wr_req.rxCnt = 0;
391+
uart_wr_req.txCnt = 0;
392+
uart_wr_req.rxData = NULL;
393+
uart_wr_req.txData = data;
394+
uart_wr_req.txLen = bytes_remaining;
395+
uart_wr_req.rxLen = 0;
396+
uart_wr_req.uart = self->uart_regs;
397+
uart_wr_req.callback = (void *)uartCallback;
398+
399+
// Start the transaction
400+
start_time = supervisor_ticks_ms64();
401+
err = MXC_UART_TransactionAsync(&uart_wr_req);
402+
if (err != E_NO_ERROR) {
403+
*errcode = err;
404+
MXC_UART_AbortAsync(self->uart_regs);
405+
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
406+
mp_raise_ConnectionError(MP_ERROR_TEXT("\nERR: Requested bus is busy\n"));
407+
}
385408

386-
// Wait for transaction completion
387-
while ( (uart_status[self->uart_id] != UART_FREE) &&
388-
(supervisor_ticks_ms64() - start_time < (self->timeout * 1000))
389-
) {};
409+
// Wait for transaction completion or timeout
410+
while ( (uart_status[self->uart_id] != UART_FREE) &&
411+
(supervisor_ticks_ms64() - start_time < (self->timeout * 1000))) {
390412

391-
// If the timeout gets hit, abort and error out
392-
if (uart_status[self->uart_id] != UART_FREE) {
393-
MXC_UART_AbortAsync(self->uart_regs);
394-
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
395-
mp_raise_ConnectionError(MP_ERROR_TEXT("\nERR: Uart transaction timed out.\n"));
413+
// Call the handler and abort if errors
414+
uart_err = MXC_UART_AsyncHandler(MXC_UART_GET_UART(0));
415+
if (uart_err != E_NO_ERROR) {
416+
MXC_UART_AbortAsync(MXC_UART_GET_UART(0));
417+
NVIC_DisableIRQ(MXC_UART_GET_IRQ(0));
418+
mp_raise_RuntimeError_varg(MP_ERROR_TEXT("MAX32 ERR: %d\n"), uart_err);
396419
}
420+
}
397421

398-
bytes_remaining -= uart_wr_req.txCnt;
422+
// If the timeout gets hit, abort and error out
423+
if (uart_status[self->uart_id] != UART_FREE) {
424+
MXC_UART_AbortAsync(self->uart_regs);
425+
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
426+
mp_raise_ConnectionError(MP_ERROR_TEXT("\nERR: Uart transaction timed out.\n"));
399427
}
400-
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
401-
return len;
402428

429+
// Check for errors from the callback
430+
else if (uart_err != E_NO_ERROR) {
431+
MXC_UART_AbortAsync(self->uart_regs);
432+
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
433+
mp_raise_RuntimeError_varg(MP_ERROR_TEXT("MAX32 ERR: %d\n"), uart_err);
434+
}
435+
436+
return len;
403437
}
404438

405439
uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self)

0 commit comments

Comments
 (0)