@@ -90,8 +90,7 @@ int Uart::available()
9090
9191int Uart::availableForWrite ()
9292{
93- // return _tx_buffer.availableForStore();
94- return 127 ; // todo:
93+ return _tx_buffer.availableForStore ();
9594}
9695
9796int Uart::peek ()
@@ -118,19 +117,47 @@ size_t Uart::write(const uint8_t data)
118117size_t Uart::write (const uint8_t *buffer, size_t size)
119118{
120119 uint32_t ui32BytesWritten = 0 ;
120+ uint32_t remaining = size;
121121
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
123123
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 );
133- return ui32BytesWritten;
124+ // If TX UART is sitting idle, load it. This will start the ISR TX handler as well.
125+ uint32_t uartFlags;
126+ am_hal_uart_flags_get (_handle, &uartFlags);
127+ if (uartFlags & AM_HAL_UART_FR_TX_EMPTY)
128+ {
129+ uint32_t amtToSend = remaining;
130+ if (amtToSend > AM_HAL_UART_FIFO_MAX)
131+ amtToSend = AM_HAL_UART_FIFO_MAX;
132+
133+ remaining -= amtToSend;
134+
135+ // Transfer to local buffer
136+ uint8_t tempTX[AM_HAL_UART_FIFO_MAX];
137+ for (int x = 0 ; x < amtToSend; x++)
138+ tempTX[x] = buffer[x];
139+
140+ const am_hal_uart_transfer_t sUartWrite =
141+ {
142+ .ui32Direction = AM_HAL_UART_WRITE,
143+ .pui8Data = (uint8_t *)tempTX,
144+ .ui32NumBytes = amtToSend,
145+ .ui32TimeoutMs = AM_HAL_UART_WAIT_FOREVER,
146+ .pui32BytesTransferred = (uint32_t *)&ui32BytesWritten,
147+ };
148+ am_hal_uart_transfer (_handle, &sUartWrite );
149+ }
150+
151+ // Transfer any remaining bytes into ring buffer
152+ for (int x = size - remaining; x < size; x++)
153+ {
154+ // If TX ring buffer is full, begin blocking
155+ while (_tx_buffer.availableForStore () == 0 )
156+ delay (1 );
157+ _tx_buffer.store_char (buffer[x]);
158+ }
159+
160+ return ui32BytesWritten; // Return number of bytes pushed to UART hardware
134161}
135162
136163// Stop Bits
@@ -370,9 +397,9 @@ ap3_err_t Uart::_begin(void)
370397
371398 UARTn (_instance)->LCRH_b .FEN = 0 ; // Disable that pesky FIFO
372399
373- // Enable RX interrupts
400+ // Enable TX and RX interrupts
374401 NVIC_EnableIRQ ((IRQn_Type)(UART0_IRQn + _instance));
375- am_hal_uart_interrupt_enable (_handle, (AM_HAL_UART_INT_RX));
402+ am_hal_uart_interrupt_enable (_handle, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_TX ));
376403 am_hal_interrupt_master_enable ();
377404
378405 // Register the class into the local list
@@ -487,7 +514,7 @@ ap3_err_t ap3_uart_pad_funcsel(uint8_t instance, ap3_uart_pad_type_e type, ap3_g
487514// Interrupt handler for the UART.
488515//
489516// *****************************************************************************
490- inline void Uart::rx_isr (void )
517+ inline void Uart::uart_isr (void )
491518{
492519
493520 uint32_t ui32Status;
@@ -517,21 +544,49 @@ inline void Uart::rx_isr(void)
517544 _rx_buffer.store_char (rx_c);
518545 }
519546 }
547+
548+ if (ui32Status & AM_HAL_UART_INT_TX)
549+ {
550+ // If bytes are sitting in TX buffer, load them into UART buffer for transfer
551+ if (_tx_buffer.available ())
552+ {
553+ uint32_t ui32BytesWritten = 0 ;
554+
555+ uint32_t amtToSend = _tx_buffer.available ();
556+ if (amtToSend > AM_HAL_UART_FIFO_MAX)
557+ amtToSend = AM_HAL_UART_FIFO_MAX;
558+
559+ // Transfer to local buffer
560+ uint8_t tempTX[AM_HAL_UART_FIFO_MAX];
561+ for (int x = 0 ; x < amtToSend; x++)
562+ tempTX[x] = _tx_buffer.read_char ();
563+
564+ const am_hal_uart_transfer_t sUartWrite =
565+ {
566+ .ui32Direction = AM_HAL_UART_WRITE,
567+ .pui8Data = (uint8_t *)tempTX,
568+ .ui32NumBytes = (uint32_t )amtToSend,
569+ .ui32TimeoutMs = AM_HAL_UART_WAIT_FOREVER,
570+ .pui32BytesTransferred = (uint32_t *)&ui32BytesWritten,
571+ };
572+ am_hal_uart_transfer (_handle, &sUartWrite );
573+ }
574+ }
520575}
521576
522577// Individual ISR implementations for the two UART peripherals on the Apollo3
523578extern " C" void am_uart_isr (void )
524579{
525580 if (ap3_uart_handles[0 ] != NULL )
526581 {
527- ap3_uart_handles[0 ]->rx_isr ();
582+ ap3_uart_handles[0 ]->uart_isr ();
528583 }
529584}
530585
531586extern " C" void am_uart1_isr (void )
532587{
533588 if (ap3_uart_handles[1 ] != NULL )
534589 {
535- ap3_uart_handles[1 ]->rx_isr ();
590+ ap3_uart_handles[1 ]->uart_isr ();
536591 }
537592}
0 commit comments