diff --git a/cores/arduino/ard_sup/ap3_uart.h b/cores/arduino/ard_sup/ap3_uart.h index a3b34a2f..9358e6a6 100644 --- a/cores/arduino/ard_sup/ap3_uart.h +++ b/cores/arduino/ard_sup/ap3_uart.h @@ -33,6 +33,10 @@ SOFTWARE. #define AP3_UART_RINGBUFF_SIZE 256 #endif +#ifndef AP3_UART_LINBUFF_SIZE +#define AP3_UART_LINBUFF_SIZE 256 +#endif + typedef RingBufferN AP3UartRingBuffer; extern char ap3_g_prfbuf[AM_PRINTF_BUFSIZE]; @@ -74,10 +78,14 @@ class Uart : public HardwareSerial operator bool() { return true; } // todo: wait for a serial terminal to be open... probably depends on RTS or CTS... private: -public: //temporary +public: //temporary AP3UartRingBuffer _rx_buffer; // These buffers guarantee the lifespan of the data to transmit AP3UartRingBuffer _tx_buffer; // to allow for asynchronous tranfsers + uint8_t _tx_linbuff[AP3_UART_LINBUFF_SIZE]; + uint8_t _rx_linbuff[AP3_UART_LINBUFF_SIZE]; + volatile uint32_t _tx_idle; + uint8_t _instance; void *_handle; am_hal_uart_config_t _config; diff --git a/cores/arduino/ard_sup/uart/ap3_uart.cpp b/cores/arduino/ard_sup/uart/ap3_uart.cpp index 02664b47..97983e0b 100644 --- a/cores/arduino/ard_sup/uart/ap3_uart.cpp +++ b/cores/arduino/ard_sup/uart/ap3_uart.cpp @@ -117,48 +117,50 @@ size_t Uart::write(const uint8_t data) size_t Uart::write(const uint8_t *buffer, size_t size) { - uint32_t ui32BytesWritten = 0; - uint32_t remaining = size; + uint32_t ui32TransferBytesWritten = 0; + uint32_t ui32TotalBytesWritten = 0; - //FIFO on Apollo3 is 32 bytes - - //If TX UART is sitting idle, load it. This will start the ISR TX handler as well. - uint32_t uartFlags; - am_hal_uart_flags_get(_handle, &uartFlags); - if (uartFlags & AM_HAL_UART_FR_TX_EMPTY) + // + // Print the string via the UART. + // + am_hal_uart_transfer_t sUartWrite = + { + .ui32Direction = AM_HAL_UART_WRITE, + .pui8Data = NULL, + .ui32NumBytes = 0, + .ui32TimeoutMs = 0, + .pui32BytesTransferred = &ui32TransferBytesWritten, + }; + + do { - uint32_t amtToSend = remaining; - if (amtToSend > AM_HAL_UART_FIFO_MAX) - amtToSend = AM_HAL_UART_FIFO_MAX; + while (!_tx_idle) + { + }; // wait for tx to become idle - remaining -= amtToSend; + sUartWrite.pui8Data = (uint8_t *)((uint8_t *)buffer + ui32TotalBytesWritten); + sUartWrite.ui32NumBytes = (size > AP3_UART_LINBUFF_SIZE) ? AP3_UART_LINBUFF_SIZE : size; + am_hal_uart_transfer(_handle, &sUartWrite); - //Transfer to local buffer - uint8_t tempTX[AM_HAL_UART_FIFO_MAX]; - for (int x = 0; x < amtToSend; x++) - tempTX[x] = buffer[x]; + ui32TotalBytesWritten += ui32TransferBytesWritten; - const am_hal_uart_transfer_t sUartWrite = - { - .ui32Direction = AM_HAL_UART_WRITE, - .pui8Data = (uint8_t *)tempTX, - .ui32NumBytes = amtToSend, - .ui32TimeoutMs = AM_HAL_UART_WAIT_FOREVER, - .pui32BytesTransferred = (uint32_t *)&ui32BytesWritten, - }; - am_hal_uart_transfer(_handle, &sUartWrite); - } + } while (ui32TotalBytesWritten < size); - //Transfer any remaining bytes into ring buffer - for (int x = size - remaining; x < size; x++) + if (ui32TotalBytesWritten != size) { - //If TX ring buffer is full, begin blocking - while (_tx_buffer.availableForStore() == 0) - delay(1); - _tx_buffer.store_char(buffer[x]); + // + // Couldn't send the whole string!! + // + while (1) + { + digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) + delay(50); // wait for a second + digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW + delay(50); + } } - return ui32BytesWritten; //Return number of bytes pushed to UART hardware + return ui32TotalBytesWritten; //Return number of bytes pushed to UART hardware } // Stop Bits @@ -303,6 +305,12 @@ ap3_err_t Uart::_begin(void) am_hal_gpio_pincfg_t pincfg = AP3_GPIO_DEFAULT_PINCFG; uint8_t funcsel = 0; + // Link in the buffers for the HAL + _config.pui8RxBuffer = _rx_linbuff; + _config.pui8TxBuffer = _tx_linbuff; + _config.ui32RxBufferSize = sizeof(_rx_linbuff); + _config.ui32TxBufferSize = sizeof(_tx_linbuff); + // Check for a valid instance // Check pins for compatibility with the selcted instance @@ -403,6 +411,9 @@ ap3_err_t Uart::_begin(void) am_hal_uart_interrupt_enable(_handle, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_TX)); am_hal_interrupt_master_enable(); + // Service interrupts to determine idle state + am_hal_uart_interrupt_service(_handle, 0, (uint32_t *)&_tx_idle); + // Register the class into the local list ap3_uart_handles[_instance] = this; @@ -517,13 +528,12 @@ ap3_err_t ap3_uart_pad_funcsel(uint8_t instance, ap3_uart_pad_type_e type, ap3_g //***************************************************************************** inline void Uart::uart_isr(void) { - uint32_t ui32Status; - // Read the masked interrupt status from the UART. + // Service the FIFOs as necessary, and clear the interrupts. am_hal_uart_interrupt_status_get(_handle, &ui32Status, true); am_hal_uart_interrupt_clear(_handle, ui32Status); - am_hal_uart_interrupt_service(_handle, ui32Status, 0); + am_hal_uart_interrupt_service(_handle, ui32Status, (uint32_t *)&_tx_idle); if (ui32Status & AM_HAL_UART_INT_RX) { @@ -538,40 +548,15 @@ inline void Uart::uart_isr(void) .ui32TimeoutMs = 0, .pui32BytesTransferred = &ui32BytesRead, }; - am_hal_uart_transfer(_handle, &sRead); - if (ui32BytesRead) + do { - _rx_buffer.store_char(rx_c); - } - } - - if (ui32Status & AM_HAL_UART_INT_TX) - { - //If bytes are sitting in TX buffer, load them into UART buffer for transfer - if (_tx_buffer.available()) - { - uint32_t ui32BytesWritten = 0; - - uint32_t amtToSend = _tx_buffer.available(); - if (amtToSend > AM_HAL_UART_FIFO_MAX) - amtToSend = AM_HAL_UART_FIFO_MAX; - - //Transfer to local buffer - uint8_t tempTX[AM_HAL_UART_FIFO_MAX]; - for (int x = 0; x < amtToSend; x++) - tempTX[x] = _tx_buffer.read_char(); - - const am_hal_uart_transfer_t sUartWrite = - { - .ui32Direction = AM_HAL_UART_WRITE, - .pui8Data = (uint8_t *)tempTX, - .ui32NumBytes = (uint32_t)amtToSend, - .ui32TimeoutMs = AM_HAL_UART_WAIT_FOREVER, - .pui32BytesTransferred = (uint32_t *)&ui32BytesWritten, - }; - am_hal_uart_transfer(_handle, &sUartWrite); - } + am_hal_uart_transfer(_handle, &sRead); + if (ui32BytesRead) + { + _rx_buffer.store_char(rx_c); + } + } while (ui32BytesRead); } }