@@ -119,17 +119,42 @@ size_t Uart::write(const uint8_t *buffer, size_t size)
119
119
{
120
120
uint32_t ui32BytesWritten = 0 ;
121
121
122
- // todo: use a local buffer to guarantee lifespan of data (maybe txbuffer, but maybe not a ring buffer? b/c of efficiency + not breaking up transfers)
122
+ // FIFO on Apollo3 is 32 bytes
123
123
124
- const am_hal_uart_transfer_t sUartWrite =
125
- {
126
- .ui32Direction = AM_HAL_UART_WRITE,
127
- .pui8Data = (uint8_t *)buffer,
128
- .ui32NumBytes = size,
129
- .ui32TimeoutMs = AM_HAL_UART_WAIT_FOREVER,
130
- .pui32BytesTransferred = (uint32_t *)&ui32BytesWritten,
131
- };
132
- am_hal_uart_transfer (_handle, &sUartWrite );
124
+ // If TX UART is sitting idle, load it. This will start the ISR TX handler as well.
125
+ uint32_t uartFlags = 0 ;
126
+ am_hal_uart_flags_get (_handle, &uartFlags);
127
+
128
+ // am_hal_uart_tx_flush(_handle);
129
+ if (uartFlags & AM_HAL_UART_FR_TX_EMPTY)
130
+ // if (1)
131
+ {
132
+ uint32_t amtToSend = size;
133
+ if (amtToSend > AM_HAL_UART_FIFO_MAX)
134
+ amtToSend = AM_HAL_UART_FIFO_MAX;
135
+
136
+ // Transfer to local buffer
137
+ uint8_t tempTX[AM_HAL_UART_FIFO_MAX];
138
+ for (int x = 0 ; x < amtToSend; x++)
139
+ tempTX[x] = _tx_buffer.read_char ();
140
+
141
+ const am_hal_uart_transfer_t sUartWrite =
142
+ {
143
+ .ui32Direction = AM_HAL_UART_WRITE,
144
+ .pui8Data = (uint8_t *)buffer,
145
+ .ui32NumBytes = size,
146
+ .ui32TimeoutMs = 0 , // Use non-blocking xfer
147
+ .pui32BytesTransferred = (uint32_t *)&ui32BytesWritten,
148
+ };
149
+ am_hal_uart_transfer (_handle, &sUartWrite );
150
+ }
151
+ else
152
+ {
153
+ // UART is already sending bytes so load the ring buffer instead
154
+ for (int x = 0 ; x < size; x++)
155
+ _tx_buffer.store_char (buffer[x]);
156
+ ui32BytesWritten = size;
157
+ }
133
158
return ui32BytesWritten;
134
159
}
135
160
@@ -370,9 +395,9 @@ ap3_err_t Uart::_begin(void)
370
395
371
396
UARTn (_instance)->LCRH_b .FEN = 0 ; // Disable that pesky FIFO
372
397
373
- // Enable RX interrupts
398
+ // Enable TX and RX interrupts
374
399
NVIC_EnableIRQ ((IRQn_Type)(UART0_IRQn + _instance));
375
- am_hal_uart_interrupt_enable (_handle, (AM_HAL_UART_INT_RX));
400
+ am_hal_uart_interrupt_enable (_handle, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_TX ));
376
401
am_hal_interrupt_master_enable ();
377
402
378
403
// Register the class into the local list
@@ -517,6 +542,34 @@ inline void Uart::rx_isr(void)
517
542
_rx_buffer.store_char (rx_c);
518
543
}
519
544
}
545
+
546
+ if (ui32Status & AM_HAL_UART_INT_TX)
547
+ {
548
+ // If bytes are sitting in TX buffer, load them into UART buffer for transfer
549
+ if (_tx_buffer.available ())
550
+ {
551
+ uint32_t ui32BytesWritten = 0 ;
552
+
553
+ uint32_t amtToSend = _tx_buffer.available ();
554
+ if (amtToSend > AM_HAL_UART_FIFO_MAX)
555
+ amtToSend = AM_HAL_UART_FIFO_MAX;
556
+
557
+ // Transfer to local buffer
558
+ uint8_t tempTX[AM_HAL_UART_FIFO_MAX];
559
+ for (int x = 0 ; x < amtToSend; x++)
560
+ tempTX[x] = _tx_buffer.read_char ();
561
+
562
+ const am_hal_uart_transfer_t sUartWrite =
563
+ {
564
+ .ui32Direction = AM_HAL_UART_WRITE,
565
+ .pui8Data = (uint8_t *)tempTX,
566
+ .ui32NumBytes = (uint32_t )amtToSend,
567
+ .ui32TimeoutMs = AM_HAL_UART_WAIT_FOREVER,
568
+ .pui32BytesTransferred = (uint32_t *)&ui32BytesWritten,
569
+ };
570
+ am_hal_uart_transfer (_handle, &sUartWrite );
571
+ }
572
+ }
520
573
}
521
574
522
575
// Individual ISR implementations for the two UART peripherals on the Apollo3
0 commit comments