From b9c44e48df58fa9f5eac9f8ad1ae495a1dc87f83 Mon Sep 17 00:00:00 2001 From: Jeremy Kongs Date: Wed, 2 Oct 2024 15:00:24 -0500 Subject: [PATCH 1/3] Prevent HART buffer indexing issues Interrupts could occur while manually loading the FIFO resulting in bogus data being transmitted in some cases. --- Libraries/PeriphDrivers/Source/AFE/hart_uart.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Libraries/PeriphDrivers/Source/AFE/hart_uart.c b/Libraries/PeriphDrivers/Source/AFE/hart_uart.c index ed1533ae0d9..ba3c2819c80 100644 --- a/Libraries/PeriphDrivers/Source/AFE/hart_uart.c +++ b/Libraries/PeriphDrivers/Source/AFE/hart_uart.c @@ -1009,6 +1009,9 @@ int hart_uart_load_tx_fifo(void) return 0; } + // Ensure accurate index, dont allow uart interrupt while we manually load the fifo + MXC_UART_DisableInt(HART_UART_INSTANCE, (MXC_F_UART_INT_FL_TX_HE | MXC_F_UART_INT_FL_TX_OB)); + num_written = MXC_UART_WriteTXFIFO( HART_UART_INSTANCE, (const unsigned char *)(hart_buf + hart_uart_transmission_byte_index), load_num); @@ -1017,6 +1020,9 @@ int hart_uart_load_tx_fifo(void) // This should always equal load_num though. hart_uart_transmission_byte_index += num_written; + // Restore interrupts + MXC_UART_EnableInt(HART_UART_INSTANCE, (MXC_F_UART_INT_FL_TX_HE | MXC_F_UART_INT_FL_TX_OB)); + // Return the number actually written in case someone is interested. return num_written; } From c574d4766fc95ae6e55d2d52f2a4b6d495d87c6c Mon Sep 17 00:00:00 2001 From: Jeremy Kongs Date: Wed, 2 Oct 2024 15:01:50 -0500 Subject: [PATCH 2/3] Use APB Clock for HART UART Use of APB clock instead of ERFO prevents case of interrupts not working when system/peripheral clock is slower than UART clock. --- Libraries/PeriphDrivers/Source/AFE/hart_uart.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Libraries/PeriphDrivers/Source/AFE/hart_uart.c b/Libraries/PeriphDrivers/Source/AFE/hart_uart.c index ba3c2819c80..2258f71512e 100644 --- a/Libraries/PeriphDrivers/Source/AFE/hart_uart.c +++ b/Libraries/PeriphDrivers/Source/AFE/hart_uart.c @@ -212,6 +212,14 @@ static int hart_uart_init(mxc_uart_regs_t *uart, unsigned int baud, mxc_uart_clo } // Set RX threshold to 1 byte + // Note, to meet HART TPDLL needs, each received byte must be handled singularly, to verify + // it for (vertical: parity bit) parity, framing errors, and gap error. + // This HART UART driver currently checks parity, and framing errors, but gap must be + // handled by TPDLL or application code. + // + // To increase threshold would require restructuring of the receiver to monitor gaps + // and to parse when and if comm errors occur, as there could be multiple bytes in + // the FIFO, and the errors would only apply to the most recent. retval = MXC_UART_SetRXThreshold(uart, 1); if (retval != E_NO_ERROR) { return retval; @@ -934,7 +942,12 @@ int hart_uart_setup(uint32_t test_mode) } else { hart_rts_receive_mode(); - retval = hart_uart_init(HART_UART_INSTANCE, 1200, MXC_UART_ERFO_CLK); + // + // NOTE: Need to use APB clock here instead of ERFO. + // Otherwise in a case for ERFO clock is faster than the System/Peripheral + // clock UART interrupts will not or only partially work. + // + retval = hart_uart_init(HART_UART_INSTANCE, 1200, MXC_UART_APB_CLK); if (retval != E_NO_ERROR) { return E_COMM_ERR; } From 036cc303e460a4f22998e148cbdc985e55aba9be Mon Sep 17 00:00:00 2001 From: Jeremy Kongs Date: Tue, 19 Dec 2023 15:09:55 -0600 Subject: [PATCH 3/3] Code Review feedback corrections --- Libraries/PeriphDrivers/Source/AFE/afe.c | 4 ++-- Libraries/PeriphDrivers/Source/AFE/hart_uart.c | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Libraries/PeriphDrivers/Source/AFE/afe.c b/Libraries/PeriphDrivers/Source/AFE/afe.c index 2356519986a..d64d3a5c7a6 100644 --- a/Libraries/PeriphDrivers/Source/AFE/afe.c +++ b/Libraries/PeriphDrivers/Source/AFE/afe.c @@ -65,7 +65,7 @@ // // Enabling this will use the afe timer to timeout polling of the AFE. -// This avoid any chance of the blocking function afe_spi_transceive from never returning. +// This avoids any chance of the blocking function afe_spi_transceive from never returning. // However, as this low level function can be called several times for even a single // AFE register read, it decreases throughput to and from the AFE. // When running at lower system clock frequencies this can be more of a concern. @@ -524,7 +524,7 @@ static int afe_spi_transceive(uint8_t *data, int byte_length) #else // Not AFE_SPI_TRANSCEIVE_SAFE_BUT_SLOWER // -// This function blocks until transceive is completed, or times out +// This function blocks until transceive is completed // This version does not use the afe timer to interrupt potential infinite polling. // static int afe_spi_transceive(uint8_t *data, int byte_length) diff --git a/Libraries/PeriphDrivers/Source/AFE/hart_uart.c b/Libraries/PeriphDrivers/Source/AFE/hart_uart.c index 2258f71512e..c1782bae8ec 100644 --- a/Libraries/PeriphDrivers/Source/AFE/hart_uart.c +++ b/Libraries/PeriphDrivers/Source/AFE/hart_uart.c @@ -487,7 +487,7 @@ static int hart_uart_pins_external_test_mode_state(void) int retval = 0; mxc_gpio_cfg_t hart_pin; - // RTS Input to AFE, LOW is transmit mode, so Pulling Up + // HART_RTS Input to AFE, LOW is transmit mode, so Pulling Up hart_pin.port = HART_RTS_GPIO_PORT; hart_pin.mask = HART_RTS_GPIO_PIN; hart_pin.pad = MXC_GPIO_PAD_PULL_UP; @@ -498,30 +498,33 @@ static int hart_uart_pins_external_test_mode_state(void) return retval; } - // CD output from AFE, Tristate + // HART_CD output from AFE, Tristate hart_pin.port = HART_CD_GPIO_PORT; hart_pin.mask = HART_CD_GPIO_PIN; hart_pin.pad = MXC_GPIO_PAD_NONE; + hart_pin.func = MXC_GPIO_FUNC_IN; retval = MXC_AFE_GPIO_Config(&hart_pin); if (retval != E_NO_ERROR) { return retval; } - // IN input to AFE, pulling Up + // HART_IN input to AFE, pulling Up hart_pin.port = HART_IN_GPIO_PORT; hart_pin.mask = HART_IN_GPIO_PIN; hart_pin.pad = MXC_GPIO_PAD_PULL_UP; + hart_pin.func = MXC_GPIO_FUNC_IN; retval = MXC_AFE_GPIO_Config(&hart_pin); if (retval != E_NO_ERROR) { return retval; } - // IN output from AFE, Tristate + // HART_OUT output from AFE, Tristate hart_pin.port = HART_OUT_GPIO_PORT; hart_pin.mask = HART_OUT_GPIO_PIN; hart_pin.pad = MXC_GPIO_PAD_NONE; + hart_pin.func = MXC_GPIO_FUNC_IN; retval = MXC_AFE_GPIO_Config(&hart_pin); if (retval != E_NO_ERROR) {