Skip to content

Commit 8848d43

Browse files
committed
Fixed most UART write issues.
- Graceful recovery from timeouts added - Remaining issue still exists where a timeout occurs after a while
1 parent 3608b8c commit 8848d43

File tree

1 file changed

+54
-32
lines changed
  • ports/analog/common-hal/busio

1 file changed

+54
-32
lines changed

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

Lines changed: 54 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
* THE SOFTWARE.
2525
*/
2626

27+
#if CIRCUITPY_BUSIO_UART
28+
2729
#include "shared-bindings/microcontroller/__init__.h"
2830
#include "shared-bindings/microcontroller/Pin.h"
2931
#include "supervisor/shared/tick.h"
@@ -144,18 +146,21 @@ static mxc_uart_parity_t convertParity(busio_uart_parity_t busio_parity)
144146
}
145147
}
146148

147-
// FIXME: Find a better way of doing t his without a for loop
148-
void UartISR(void) {
149-
for (int i=0; i< NUM_UARTS; i++) {
149+
// FIXME: Find a better way of doing this without a for loop
150+
// FIXME: Fixed @ UART0 for TESTING BUGFIXES!!!
151+
void UART0_IRQHandler(void) {
152+
// MXC_UART_AsyncHandler(MXC_UART_GET_UART(0));
153+
for (int i=0; i < NUM_UARTS; i++) {
150154
if (uarts_active & (1 << i) ) {
151155
MXC_UART_AsyncHandler(MXC_UART_GET_UART(i));
152-
uart_status[i] = UART_FREE;
153156
}
154157
}
155158
}
156159

157-
void uartCallback(mxc_uart_req_t *req, int error) {
158-
160+
// Callback gets called when AsyncRequest is COMPLETE
161+
// (e.g. txLen == txCnt)
162+
static volatile void uartCallback(mxc_uart_req_t *req, int error) {
163+
uart_status[MXC_UART_GET_IDX(req->uart)] = UART_FREE;
159164
}
160165

161166
// Construct an underlying UART object.
@@ -256,17 +261,12 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
256261
// Indicate to this module that the UART is active
257262
uarts_active |= (1 << self->uart_id);
258263

259-
MXC_UART_ClearFlags(self->uart_regs, self->uart_regs->int_fl);
260264

261265
/* Enable UART interrupt */
262266
NVIC_ClearPendingIRQ(MXC_UART_GET_IRQ(self->uart_id));
263267
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
264268
NVIC_SetPriority(MXC_UART_GET_IRQ(self->uart_id), UART_PRIORITY);
265-
NVIC_SetVector(MXC_UART_GET_IRQ(self->uart_id), (uint32_t)UartISR);
266-
267-
// FIXME: UART ISRs are NOT WORKING!
268-
// MXC_UART_EnableInt(self->uart_regs, ???)
269-
// NVIC_EnableIRQ(MXC_UART_GET_IRQ(self->uart_id));
269+
NVIC_SetVector(MXC_UART_GET_IRQ(self->uart_id), (uint32_t)&UART0_IRQHandler);
270270

271271
return;
272272
}
@@ -321,23 +321,30 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self,
321321

322322
bytes_remaining = len * 4;
323323

324-
while(bytes_remaining > 0) {
325-
mxc_uart_req_t uart_wr_req;
326-
uart_wr_req.rxCnt = 0;
327-
uart_wr_req.txCnt = 0;
328-
uart_wr_req.rxData = data;
329-
uart_wr_req.txData = NULL;
330-
uart_wr_req.rxLen = (uint32_t)( (bytes_remaining >= 255) ? 255 : bytes_remaining );
331-
uart_wr_req.txLen = 0;
332-
uart_wr_req.uart = self->uart_regs;
324+
MXC_UART_ClearFlags(self->uart_regs, 0xFFFFFFFF);
325+
NVIC_EnableIRQ(MXC_UART_GET_IRQ(self->uart_id));
333326

334-
err = MXC_UART_Transaction(&uart_wr_req);
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);
335339
if (err != E_NO_ERROR) {
336340
*errcode = err;
341+
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
337342
return ((len * 4) - bytes_remaining);
338343
}
339-
bytes_remaining -= uart_wr_req.rxLen;
344+
bytes_remaining -= uart_rd_req.rxLen;
340345
}
346+
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
347+
341348
return len;
342349
}
343350

@@ -350,36 +357,49 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self,
350357
uint32_t start_time=0;
351358
static size_t bytes_remaining;
352359

353-
bytes_remaining = len * 4;
360+
bytes_remaining = len;
361+
362+
MXC_UART_ClearFlags(self->uart_regs, 0xFFFFFFFF);
363+
NVIC_EnableIRQ(MXC_UART_GET_IRQ(self->uart_id));
354364

355365
while(bytes_remaining > 0) {
356366
mxc_uart_req_t uart_wr_req;
357367
uart_wr_req.rxCnt = 0;
358368
uart_wr_req.txCnt = 0;
359369
uart_wr_req.rxData = NULL;
360370
uart_wr_req.txData = data;
361-
uart_wr_req.txLen = (uint32_t)( (bytes_remaining >= 255) ? 255 : bytes_remaining );
371+
uart_wr_req.txLen = bytes_remaining;
362372
uart_wr_req.rxLen = 0;
363373
uart_wr_req.uart = self->uart_regs;
374+
uart_wr_req.callback = (void *)uartCallback;
364375

365376
uart_status[self->uart_id] = UART_BUSY;
366377
start_time = supervisor_ticks_ms64();
367-
err = MXC_UART_Transaction(&uart_wr_req);
378+
err = MXC_UART_TransactionAsync(&uart_wr_req);
368379
if (err != E_NO_ERROR) {
369380
*errcode = err;
370-
return ((len * 4) - bytes_remaining);
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"));
371384
}
372385

373-
// FIXME: NOT ENTERING ISR, NOT HANDLING TIMEOUT
374386
// Wait for transaction completion
375-
// FIXME: Test timeout & status flags
376-
while ( (supervisor_ticks_ms64() - start_time < 500)
377-
&& (uart_status[self->uart_id] != UART_FREE)
387+
while ( (uart_status[self->uart_id] != UART_FREE) &&
388+
(supervisor_ticks_ms64() - start_time < (self->timeout * 1000))
378389
) {};
379390

380-
bytes_remaining -= uart_wr_req.txLen;
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"));
396+
}
397+
398+
bytes_remaining -= uart_wr_req.txCnt;
381399
}
400+
NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id));
382401
return len;
402+
383403
}
384404

385405
uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self)
@@ -438,3 +458,5 @@ void common_hal_busio_uart_never_reset(busio_uart_obj_t *self)
438458
common_hal_never_reset_pin(self->rts_pin);
439459
// uart_never_reset_mask |= ( 1 << (self->uart_id) );
440460
}
461+
462+
#endif // CIRCUITPY_BUSIO_UART

0 commit comments

Comments
 (0)