@@ -90,8 +90,7 @@ int Uart::available()
90
90
91
91
int Uart::availableForWrite ()
92
92
{
93
- // return _tx_buffer.availableForStore();
94
- return 127 ; // todo:
93
+ return _tx_buffer.availableForStore ();
95
94
}
96
95
97
96
int Uart::peek ()
@@ -118,19 +117,47 @@ size_t Uart::write(const uint8_t data)
118
117
size_t Uart::write (const uint8_t *buffer, size_t size)
119
118
{
120
119
uint32_t ui32BytesWritten = 0 ;
120
+ uint32_t remaining = size;
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 );
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
134
161
}
135
162
136
163
// Stop Bits
@@ -370,9 +397,9 @@ ap3_err_t Uart::_begin(void)
370
397
371
398
UARTn (_instance)->LCRH_b .FEN = 0 ; // Disable that pesky FIFO
372
399
373
- // Enable RX interrupts
400
+ // Enable TX and RX interrupts
374
401
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 ));
376
403
am_hal_interrupt_master_enable ();
377
404
378
405
// 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
487
514
// Interrupt handler for the UART.
488
515
//
489
516
// *****************************************************************************
490
- inline void Uart::rx_isr (void )
517
+ inline void Uart::uart_isr (void )
491
518
{
492
519
493
520
uint32_t ui32Status;
@@ -517,21 +544,49 @@ inline void Uart::rx_isr(void)
517
544
_rx_buffer.store_char (rx_c);
518
545
}
519
546
}
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
+ }
520
575
}
521
576
522
577
// Individual ISR implementations for the two UART peripherals on the Apollo3
523
578
extern " C" void am_uart_isr (void )
524
579
{
525
580
if (ap3_uart_handles[0 ] != NULL )
526
581
{
527
- ap3_uart_handles[0 ]->rx_isr ();
582
+ ap3_uart_handles[0 ]->uart_isr ();
528
583
}
529
584
}
530
585
531
586
extern " C" void am_uart1_isr (void )
532
587
{
533
588
if (ap3_uart_handles[1 ] != NULL )
534
589
{
535
- ap3_uart_handles[1 ]->rx_isr ();
590
+ ap3_uart_handles[1 ]->uart_isr ();
536
591
}
537
592
}
0 commit comments