Skip to content

Commit 8628c31

Browse files
author
Owen
authored
fix uart w/ better hal utilization (#111)
fix uart w/ better hal utilization
2 parents dbb1d36 + e776ef1 commit 8628c31

File tree

2 files changed

+62
-69
lines changed

2 files changed

+62
-69
lines changed

cores/arduino/ard_sup/ap3_uart.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ SOFTWARE.
3333
#define AP3_UART_RINGBUFF_SIZE 256
3434
#endif
3535

36+
#ifndef AP3_UART_LINBUFF_SIZE
37+
#define AP3_UART_LINBUFF_SIZE 256
38+
#endif
39+
3640
typedef RingBufferN<AP3_UART_RINGBUFF_SIZE> AP3UartRingBuffer;
3741

3842
extern char ap3_g_prfbuf[AM_PRINTF_BUFSIZE];
@@ -74,10 +78,14 @@ class Uart : public HardwareSerial
7478
operator bool() { return true; } // todo: wait for a serial terminal to be open... probably depends on RTS or CTS...
7579

7680
private:
77-
public: //temporary
81+
public: //temporary
7882
AP3UartRingBuffer _rx_buffer; // These buffers guarantee the lifespan of the data to transmit
7983
AP3UartRingBuffer _tx_buffer; // to allow for asynchronous tranfsers
8084

85+
uint8_t _tx_linbuff[AP3_UART_LINBUFF_SIZE];
86+
uint8_t _rx_linbuff[AP3_UART_LINBUFF_SIZE];
87+
volatile uint32_t _tx_idle;
88+
8189
uint8_t _instance;
8290
void *_handle;
8391
am_hal_uart_config_t _config;

cores/arduino/ard_sup/uart/ap3_uart.cpp

Lines changed: 53 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -117,48 +117,50 @@ size_t Uart::write(const uint8_t data)
117117

118118
size_t Uart::write(const uint8_t *buffer, size_t size)
119119
{
120-
uint32_t ui32BytesWritten = 0;
121-
uint32_t remaining = size;
120+
uint32_t ui32TransferBytesWritten = 0;
121+
uint32_t ui32TotalBytesWritten = 0;
122122

123-
//FIFO on Apollo3 is 32 bytes
124-
125-
//If TX UART is sitting idle, load it. This will start the ISR TX handler as well.
126-
uint32_t uartFlags;
127-
am_hal_uart_flags_get(_handle, &uartFlags);
128-
if (uartFlags & AM_HAL_UART_FR_TX_EMPTY)
123+
//
124+
// Print the string via the UART.
125+
//
126+
am_hal_uart_transfer_t sUartWrite =
127+
{
128+
.ui32Direction = AM_HAL_UART_WRITE,
129+
.pui8Data = NULL,
130+
.ui32NumBytes = 0,
131+
.ui32TimeoutMs = 0,
132+
.pui32BytesTransferred = &ui32TransferBytesWritten,
133+
};
134+
135+
do
129136
{
130-
uint32_t amtToSend = remaining;
131-
if (amtToSend > AM_HAL_UART_FIFO_MAX)
132-
amtToSend = AM_HAL_UART_FIFO_MAX;
137+
while (!_tx_idle)
138+
{
139+
}; // wait for tx to become idle
133140

134-
remaining -= amtToSend;
141+
sUartWrite.pui8Data = (uint8_t *)((uint8_t *)buffer + ui32TotalBytesWritten);
142+
sUartWrite.ui32NumBytes = (size > AP3_UART_LINBUFF_SIZE) ? AP3_UART_LINBUFF_SIZE : size;
143+
am_hal_uart_transfer(_handle, &sUartWrite);
135144

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] = buffer[x];
145+
ui32TotalBytesWritten += ui32TransferBytesWritten;
140146

141-
const am_hal_uart_transfer_t sUartWrite =
142-
{
143-
.ui32Direction = AM_HAL_UART_WRITE,
144-
.pui8Data = (uint8_t *)tempTX,
145-
.ui32NumBytes = amtToSend,
146-
.ui32TimeoutMs = AM_HAL_UART_WAIT_FOREVER,
147-
.pui32BytesTransferred = (uint32_t *)&ui32BytesWritten,
148-
};
149-
am_hal_uart_transfer(_handle, &sUartWrite);
150-
}
147+
} while (ui32TotalBytesWritten < size);
151148

152-
//Transfer any remaining bytes into ring buffer
153-
for (int x = size - remaining; x < size; x++)
149+
if (ui32TotalBytesWritten != size)
154150
{
155-
//If TX ring buffer is full, begin blocking
156-
while (_tx_buffer.availableForStore() == 0)
157-
delay(1);
158-
_tx_buffer.store_char(buffer[x]);
151+
//
152+
// Couldn't send the whole string!!
153+
//
154+
while (1)
155+
{
156+
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
157+
delay(50); // wait for a second
158+
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
159+
delay(50);
160+
}
159161
}
160162

161-
return ui32BytesWritten; //Return number of bytes pushed to UART hardware
163+
return ui32TotalBytesWritten; //Return number of bytes pushed to UART hardware
162164
}
163165

164166
// Stop Bits
@@ -303,6 +305,12 @@ ap3_err_t Uart::_begin(void)
303305
am_hal_gpio_pincfg_t pincfg = AP3_GPIO_DEFAULT_PINCFG;
304306
uint8_t funcsel = 0;
305307

308+
// Link in the buffers for the HAL
309+
_config.pui8RxBuffer = _rx_linbuff;
310+
_config.pui8TxBuffer = _tx_linbuff;
311+
_config.ui32RxBufferSize = sizeof(_rx_linbuff);
312+
_config.ui32TxBufferSize = sizeof(_tx_linbuff);
313+
306314
// Check for a valid instance
307315
// Check pins for compatibility with the selcted instance
308316

@@ -403,6 +411,9 @@ ap3_err_t Uart::_begin(void)
403411
am_hal_uart_interrupt_enable(_handle, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_TX));
404412
am_hal_interrupt_master_enable();
405413

414+
// Service interrupts to determine idle state
415+
am_hal_uart_interrupt_service(_handle, 0, (uint32_t *)&_tx_idle);
416+
406417
// Register the class into the local list
407418
ap3_uart_handles[_instance] = this;
408419

@@ -517,13 +528,12 @@ ap3_err_t ap3_uart_pad_funcsel(uint8_t instance, ap3_uart_pad_type_e type, ap3_g
517528
//*****************************************************************************
518529
inline void Uart::uart_isr(void)
519530
{
520-
521531
uint32_t ui32Status;
522532

523-
// Read the masked interrupt status from the UART.
533+
// Service the FIFOs as necessary, and clear the interrupts.
524534
am_hal_uart_interrupt_status_get(_handle, &ui32Status, true);
525535
am_hal_uart_interrupt_clear(_handle, ui32Status);
526-
am_hal_uart_interrupt_service(_handle, ui32Status, 0);
536+
am_hal_uart_interrupt_service(_handle, ui32Status, (uint32_t *)&_tx_idle);
527537

528538
if (ui32Status & AM_HAL_UART_INT_RX)
529539
{
@@ -538,40 +548,15 @@ inline void Uart::uart_isr(void)
538548
.ui32TimeoutMs = 0,
539549
.pui32BytesTransferred = &ui32BytesRead,
540550
};
541-
am_hal_uart_transfer(_handle, &sRead);
542551

543-
if (ui32BytesRead)
552+
do
544553
{
545-
_rx_buffer.store_char(rx_c);
546-
}
547-
}
548-
549-
if (ui32Status & AM_HAL_UART_INT_TX)
550-
{
551-
//If bytes are sitting in TX buffer, load them into UART buffer for transfer
552-
if (_tx_buffer.available())
553-
{
554-
uint32_t ui32BytesWritten = 0;
555-
556-
uint32_t amtToSend = _tx_buffer.available();
557-
if (amtToSend > AM_HAL_UART_FIFO_MAX)
558-
amtToSend = AM_HAL_UART_FIFO_MAX;
559-
560-
//Transfer to local buffer
561-
uint8_t tempTX[AM_HAL_UART_FIFO_MAX];
562-
for (int x = 0; x < amtToSend; x++)
563-
tempTX[x] = _tx_buffer.read_char();
564-
565-
const am_hal_uart_transfer_t sUartWrite =
566-
{
567-
.ui32Direction = AM_HAL_UART_WRITE,
568-
.pui8Data = (uint8_t *)tempTX,
569-
.ui32NumBytes = (uint32_t)amtToSend,
570-
.ui32TimeoutMs = AM_HAL_UART_WAIT_FOREVER,
571-
.pui32BytesTransferred = (uint32_t *)&ui32BytesWritten,
572-
};
573-
am_hal_uart_transfer(_handle, &sUartWrite);
574-
}
554+
am_hal_uart_transfer(_handle, &sRead);
555+
if (ui32BytesRead)
556+
{
557+
_rx_buffer.store_char(rx_c);
558+
}
559+
} while (ui32BytesRead);
575560
}
576561
}
577562

0 commit comments

Comments
 (0)