Skip to content

Commit deca450

Browse files
committed
Store tx pointers per handle
1 parent ebe5341 commit deca450

File tree

4 files changed

+63
-21
lines changed

4 files changed

+63
-21
lines changed

src/system/bus/uart.c

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct UART_Handle {
4545
UART_Bus bus_id;
4646
CircularBuffer *rx_buffer;
4747
CircularBuffer *tx_buffer;
48+
CircularBuffer *original_tx_buffer; /* Stored during passthrough */
4849
uint32_t volatile rx_dma_head;
4950
UART_RxCallback rx_callback;
5051
uint32_t rx_threshold;
@@ -55,9 +56,6 @@ struct UART_Handle {
5556
/* Global array to keep track of active UART handles */
5657
static UART_Handle *g_active_handles[UART_BUS_COUNT] = { nullptr };
5758

58-
/* Store disabled TX buffers during passthrough */
59-
static CircularBuffer *g_disabled_tx_buffers[2] = { nullptr };
60-
6159
/**
6260
* @brief Get the number of available UART bus instances.
6361
*
@@ -276,6 +274,7 @@ UART_Handle *UART_init(
276274
handle->bus_id = bus_id;
277275
handle->rx_buffer = rx_buffer;
278276
handle->tx_buffer = tx_buffer;
277+
handle->original_tx_buffer = nullptr;
279278
handle->rx_dma_head = 0;
280279
handle->rx_callback = nullptr;
281280
handle->rx_threshold = 0;
@@ -516,22 +515,26 @@ static void passthrough_callback(UART_Handle *handle, uint32_t bytes_available)
516515

517516
void UART_enable_passthrough(UART_Handle *handle1, UART_Handle *handle2)
518517
{
519-
// Only one passthrough pair is allowed at a time
520-
if ((g_disabled_tx_buffers[0] != nullptr) ||
521-
(g_disabled_tx_buffers[1] != nullptr)) {
522-
THROW(ERROR_RESOURCE_BUSY);
523-
}
524-
525518
if (!handle1 || !handle1->initialized || !handle2 ||
526519
!handle2->initialized) {
527520
THROW(ERROR_DEVICE_NOT_READY);
528521
}
529522

523+
// Check that handles are different
524+
if (handle1 == handle2) {
525+
THROW(ERROR_INVALID_ARGUMENT);
526+
}
527+
528+
// Check if either handle is already in passthrough mode
529+
if (handle1->passthrough_target || handle2->passthrough_target) {
530+
THROW(ERROR_RESOURCE_BUSY);
531+
}
532+
530533
// Set up shared buffers:
531-
// - Normal tx_buffers are temporarily disabled
534+
// - Store normal tx_buffers in each handle
532535
// - Redirect each handle's rx_buffer to the other handle's tx_buffer
533-
g_disabled_tx_buffers[0] = handle1->tx_buffer;
534-
g_disabled_tx_buffers[1] = handle2->tx_buffer;
536+
handle1->original_tx_buffer = handle1->tx_buffer;
537+
handle2->original_tx_buffer = handle2->tx_buffer;
535538
handle1->tx_buffer = handle2->rx_buffer;
536539
handle2->tx_buffer = handle1->rx_buffer;
537540

@@ -551,17 +554,17 @@ void UART_disable_passthrough(UART_Handle *handle1, UART_Handle *handle2)
551554
THROW(ERROR_INVALID_ARGUMENT);
552555
}
553556

557+
/* Disable passthrough callbacks */
558+
UART_set_rx_callback(handle1, nullptr, 0);
559+
UART_set_rx_callback(handle2, nullptr, 0);
560+
554561
/* Restore original TX buffers */
555-
handle1->tx_buffer = g_disabled_tx_buffers[0];
556-
handle2->tx_buffer = g_disabled_tx_buffers[1];
557-
g_disabled_tx_buffers[0] = nullptr;
558-
g_disabled_tx_buffers[1] = nullptr;
562+
handle1->tx_buffer = handle1->original_tx_buffer;
563+
handle2->tx_buffer = handle2->original_tx_buffer;
564+
handle1->original_tx_buffer = nullptr;
565+
handle2->original_tx_buffer = nullptr;
559566

560567
/* Clear passthrough targets */
561568
handle1->passthrough_target = nullptr;
562569
handle2->passthrough_target = nullptr;
563-
564-
/* Disable RX callbacks */
565-
UART_set_rx_callback(handle1, nullptr, 0);
566-
UART_set_rx_callback(handle2, nullptr, 0);
567570
}

src/system/bus/uart.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,6 @@ bool UART_tx_busy(UART_Handle *handle);
201201
* @warning Do not call UART operations on either handle while passthrough is
202202
* active.
203203
*
204-
* @note Passthrough can only be enabled for one pair of UART buses at a time.
205204
* @note While passthrough is active, neither bus can be deinitialized.
206205
* @note RX callbacks, if any, will be disabled and must be manually re-enabled
207206
* after disabling passthrough.

tests/test_headers/opaque.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct UART_Handle {
2929
UART_Bus bus_id;
3030
CircularBuffer *rx_buffer;
3131
CircularBuffer *tx_buffer;
32+
CircularBuffer *original_tx_buffer; /* Stored during passthrough */
3233
uint32_t volatile rx_dma_head;
3334
UART_RxCallback rx_callback;
3435
uint32_t rx_threshold;

tests/test_uart.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,3 +1073,42 @@ void test_UART_deinit_with_active_passthrough(void)
10731073
UART_deinit(handle1);
10741074
UART_deinit(handle2);
10751075
}
1076+
1077+
void test_UART_enable_passthrough_with_same_handle(void)
1078+
{
1079+
// Arrange - Initialize one UART bus
1080+
CircularBuffer rx_buffer, tx_buffer;
1081+
uint8_t rx_data[256], tx_data[256];
1082+
1083+
circular_buffer_init(&rx_buffer, rx_data, sizeof(rx_data));
1084+
circular_buffer_init(&tx_buffer, tx_data, sizeof(tx_data));
1085+
1086+
// Set up expectations for init
1087+
UART_LL_init_Expect(UART_BUS_0, rx_data, sizeof(rx_data));
1088+
UART_LL_set_idle_callback_Ignore();
1089+
UART_LL_set_rx_complete_callback_Ignore();
1090+
UART_LL_set_tx_complete_callback_Ignore();
1091+
1092+
UART_Handle *handle = UART_init(0, &rx_buffer, &tx_buffer);
1093+
TEST_ASSERT_NOT_NULL(handle);
1094+
1095+
Error caught_error = ERROR_NONE;
1096+
1097+
// Act - Try to enable passthrough with the same handle for both buses
1098+
TRY {
1099+
UART_enable_passthrough(handle, handle);
1100+
} CATCH(caught_error) {
1101+
// Expected to catch an error
1102+
}
1103+
1104+
// Assert
1105+
TEST_ASSERT_EQUAL(ERROR_INVALID_ARGUMENT, caught_error);
1106+
1107+
// Cleanup
1108+
UART_LL_deinit_Ignore();
1109+
UART_LL_set_idle_callback_Ignore();
1110+
UART_LL_set_rx_complete_callback_Ignore();
1111+
UART_LL_set_tx_complete_callback_Ignore();
1112+
1113+
UART_deinit(handle);
1114+
}

0 commit comments

Comments
 (0)