33
33
#include "fsl_lpuart.h"
34
34
#include "fsl_iomuxc.h"
35
35
#include CLOCK_CONFIG_H
36
-
37
36
#define DEFAULT_UART_BAUDRATE (115200)
38
37
#define DEFAULT_BUFFER_SIZE (256)
39
38
#define MIN_BUFFER_SIZE (32)
@@ -372,12 +371,27 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin
372
371
lpuart_transfer_t xfer ;
373
372
uint64_t t ;
374
373
size_t remaining = size ;
375
- size_t offset = 0 ;
374
+ size_t first_part_size = 0 ;
375
+ uint32_t block_time ;
376
+ uint32_t timeout_budget = self -> timeout ;
376
377
uint8_t fifo_size = FSL_FEATURE_LPUART_FIFO_SIZEn (0 );
377
378
378
- // First check if a previous transfer is still ongoing,
379
- // then wait at least the number of remaining character times.
380
- t = ticks_us64 () + (uint64_t )(self -> handle .txDataSize + fifo_size ) * (13000000 / self -> config .baudRate_Bps + 1000 );
379
+ // Check if a tansmission is still going on and will block longer than timeout
380
+ // In that case, return immediately
381
+ // For block time estimations, a 11 bit frame size is assumed instead of getting
382
+ // actual frame size, for worst case timeouts a 13 bit frame.
383
+ if (self -> tx_status != kStatus_LPUART_TxIdle ) {
384
+ block_time = (self -> handle .txDataSize + fifo_size ) * 11000 / self -> config .baudRate_Bps ;
385
+ if (timeout_budget < block_time ) {
386
+ * errcode = MP_EAGAIN ;
387
+ return MP_STREAM_ERROR ;
388
+ }
389
+ timeout_budget -= block_time ;
390
+ }
391
+
392
+ // Now wait for the previous transfer to finish, but not longer than the expected
393
+ // transfer time.
394
+ t = ticks_us64 () + (uint64_t )(self -> handle .txDataSize + fifo_size ) * 13000000 / self -> config .baudRate_Bps + 1000 ;
381
395
while (self -> tx_status != kStatus_LPUART_TxIdle ) {
382
396
if (ticks_us64 () > t ) { // timed out, hard error
383
397
* errcode = MP_ETIMEDOUT ;
@@ -388,41 +402,43 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin
388
402
389
403
// Check if the first part has to be sent semi-blocking.
390
404
if (size > self -> txbuf_len ) {
391
- // Send the first block.
392
- xfer .data = (uint8_t * )buf_in ;
393
- offset = xfer .dataSize = size - self -> txbuf_len ;
394
- self -> tx_status = kStatus_LPUART_TxBusy ;
395
- LPUART_TransferSendNonBlocking (self -> lpuart , & self -> handle , & xfer );
396
-
397
- // Wait at least the number of character times for this chunk.
398
- t = ticks_us64 () + (uint64_t )xfer .dataSize * (13000000 / self -> config .baudRate_Bps + 1000 );
399
- while (self -> tx_status != kStatus_LPUART_TxIdle ) {
400
- // Wait for the first/next character to be sent.
401
- if (ticks_us64 () > t ) { // timed out
402
- if (self -> handle .txDataSize >= size ) {
403
- * errcode = MP_ETIMEDOUT ;
404
- return MP_STREAM_ERROR ;
405
- } else {
406
- return size - self -> handle .txDataSize ;
405
+ // check if it blocks shorter than the remaining timeout budget
406
+ block_time = (size - self -> txbuf_len ) * 11000 / self -> config .baudRate_Bps ;
407
+ if (timeout_budget > block_time ) {
408
+ // Send the first block.
409
+ xfer .data = (uint8_t * )buf_in ;
410
+ first_part_size = xfer .dataSize = size - self -> txbuf_len ;
411
+ self -> tx_status = kStatus_LPUART_TxBusy ;
412
+ LPUART_TransferSendNonBlocking (self -> lpuart , & self -> handle , & xfer );
413
+
414
+ // Wait at least the number of character times for this chunk.
415
+ t = ticks_us64 () + (uint64_t )(self -> handle .txDataSize + fifo_size ) *
416
+ 13000000 / self -> config .baudRate_Bps + 1000 ;
417
+ while (self -> tx_status != kStatus_LPUART_TxIdle ) {
418
+ // Wait for the first/next character to be sent.
419
+ if (ticks_us64 () > t ) { // timed out
420
+ if (self -> handle .txDataSize >= first_part_size ) {
421
+ * errcode = MP_ETIMEDOUT ;
422
+ return MP_STREAM_ERROR ;
423
+ } else {
424
+ return first_part_size - self -> handle .txDataSize ;
425
+ }
407
426
}
427
+ MICROPY_EVENT_POLL_HOOK
408
428
}
409
- MICROPY_EVENT_POLL_HOOK
410
429
}
430
+ // In any case, just sent a buffer sized chunk in the next step
411
431
remaining = self -> txbuf_len ;
412
- } else {
413
- // The data fits into the tx buffer.
414
- offset = 0 ;
415
- remaining = size ;
416
432
}
417
433
418
434
// Send the remaining data without waiting for completion.
419
- memcpy (self -> txbuf , (uint8_t * )buf_in + offset , remaining );
435
+ memcpy (self -> txbuf , (uint8_t * )buf_in + first_part_size , remaining );
420
436
xfer .data = self -> txbuf ;
421
437
xfer .dataSize = remaining ;
422
438
self -> tx_status = kStatus_LPUART_TxBusy ;
423
439
LPUART_TransferSendNonBlocking (self -> lpuart , & self -> handle , & xfer );
424
440
425
- return size ;
441
+ return first_part_size + remaining ;
426
442
}
427
443
428
444
STATIC mp_uint_t machine_uart_ioctl (mp_obj_t self_in , mp_uint_t request , mp_uint_t arg , int * errcode ) {
0 commit comments