Skip to content

Commit ddc48f1

Browse files
committed
Store tx pointers per handle
1 parent e3ce8d1 commit ddc48f1

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
@@ -41,6 +41,7 @@ struct UART_Handle {
4141
UART_Bus bus_id;
4242
CircularBuffer *rx_buffer;
4343
CircularBuffer *tx_buffer;
44+
CircularBuffer *original_tx_buffer; /* Stored during passthrough */
4445
uint32_t volatile rx_dma_head;
4546
UART_RxCallback rx_callback;
4647
uint32_t rx_threshold;
@@ -51,9 +52,6 @@ struct UART_Handle {
5152
/* Global array to keep track of active UART handles */
5253
static UART_Handle *g_active_handles[UART_BUS_COUNT] = { nullptr };
5354

54-
/* Store disabled TX buffers during passthrough */
55-
static CircularBuffer *g_disabled_tx_buffers[2] = { nullptr };
56-
5755
/**
5856
* @brief Get the number of available UART bus instances.
5957
*
@@ -264,6 +262,7 @@ UART_Handle *UART_init(
264262
handle->bus_id = bus_id;
265263
handle->rx_buffer = rx_buffer;
266264
handle->tx_buffer = tx_buffer;
265+
handle->original_tx_buffer = nullptr;
267266
handle->rx_dma_head = 0;
268267
handle->rx_callback = nullptr;
269268
handle->rx_threshold = 0;
@@ -504,22 +503,26 @@ static void passthrough_callback(UART_Handle *handle, uint32_t bytes_available)
504503

505504
void UART_enable_passthrough(UART_Handle *handle1, UART_Handle *handle2)
506505
{
507-
// Only one passthrough pair is allowed at a time
508-
if ((g_disabled_tx_buffers[0] != nullptr) ||
509-
(g_disabled_tx_buffers[1] != nullptr)) {
510-
THROW(ERROR_RESOURCE_BUSY);
511-
}
512-
513506
if (!handle1 || !handle1->initialized || !handle2 ||
514507
!handle2->initialized) {
515508
THROW(ERROR_DEVICE_NOT_READY);
516509
}
517510

511+
// Check that handles are different
512+
if (handle1 == handle2) {
513+
THROW(ERROR_INVALID_ARGUMENT);
514+
}
515+
516+
// Check if either handle is already in passthrough mode
517+
if (handle1->passthrough_target || handle2->passthrough_target) {
518+
THROW(ERROR_RESOURCE_BUSY);
519+
}
520+
518521
// Set up shared buffers:
519-
// - Normal tx_buffers are temporarily disabled
522+
// - Store normal tx_buffers in each handle
520523
// - Redirect each handle's rx_buffer to the other handle's tx_buffer
521-
g_disabled_tx_buffers[0] = handle1->tx_buffer;
522-
g_disabled_tx_buffers[1] = handle2->tx_buffer;
524+
handle1->original_tx_buffer = handle1->tx_buffer;
525+
handle2->original_tx_buffer = handle2->tx_buffer;
523526
handle1->tx_buffer = handle2->rx_buffer;
524527
handle2->tx_buffer = handle1->rx_buffer;
525528

@@ -539,17 +542,17 @@ void UART_disable_passthrough(UART_Handle *handle1, UART_Handle *handle2)
539542
THROW(ERROR_INVALID_ARGUMENT);
540543
}
541544

545+
/* Disable passthrough callbacks */
546+
UART_set_rx_callback(handle1, nullptr, 0);
547+
UART_set_rx_callback(handle2, nullptr, 0);
548+
542549
/* Restore original TX buffers */
543-
handle1->tx_buffer = g_disabled_tx_buffers[0];
544-
handle2->tx_buffer = g_disabled_tx_buffers[1];
545-
g_disabled_tx_buffers[0] = nullptr;
546-
g_disabled_tx_buffers[1] = nullptr;
550+
handle1->tx_buffer = handle1->original_tx_buffer;
551+
handle2->tx_buffer = handle2->original_tx_buffer;
552+
handle1->original_tx_buffer = nullptr;
553+
handle2->original_tx_buffer = nullptr;
547554

548555
/* Clear passthrough targets */
549556
handle1->passthrough_target = nullptr;
550557
handle2->passthrough_target = nullptr;
551-
552-
/* Disable RX callbacks */
553-
UART_set_rx_callback(handle1, nullptr, 0);
554-
UART_set_rx_callback(handle2, nullptr, 0);
555558
}

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
@@ -1050,3 +1050,42 @@ void test_UART_deinit_with_active_passthrough(void)
10501050
UART_deinit(handle1);
10511051
UART_deinit(handle2);
10521052
}
1053+
1054+
void test_UART_enable_passthrough_with_same_handle(void)
1055+
{
1056+
// Arrange - Initialize one UART bus
1057+
CircularBuffer rx_buffer, tx_buffer;
1058+
uint8_t rx_data[256], tx_data[256];
1059+
1060+
circular_buffer_init(&rx_buffer, rx_data, sizeof(rx_data));
1061+
circular_buffer_init(&tx_buffer, tx_data, sizeof(tx_data));
1062+
1063+
// Set up expectations for init
1064+
UART_LL_init_Expect(UART_BUS_0, rx_data, sizeof(rx_data));
1065+
UART_LL_set_idle_callback_Ignore();
1066+
UART_LL_set_rx_complete_callback_Ignore();
1067+
UART_LL_set_tx_complete_callback_Ignore();
1068+
1069+
UART_Handle *handle = UART_init(0, &rx_buffer, &tx_buffer);
1070+
TEST_ASSERT_NOT_NULL(handle);
1071+
1072+
Error caught_error = ERROR_NONE;
1073+
1074+
// Act - Try to enable passthrough with the same handle for both buses
1075+
TRY {
1076+
UART_enable_passthrough(handle, handle);
1077+
} CATCH(caught_error) {
1078+
// Expected to catch an error
1079+
}
1080+
1081+
// Assert
1082+
TEST_ASSERT_EQUAL(ERROR_INVALID_ARGUMENT, caught_error);
1083+
1084+
// Cleanup
1085+
UART_LL_deinit_Ignore();
1086+
UART_LL_set_idle_callback_Ignore();
1087+
UART_LL_set_rx_complete_callback_Ignore();
1088+
UART_LL_set_tx_complete_callback_Ignore();
1089+
1090+
UART_deinit(handle);
1091+
}

0 commit comments

Comments
 (0)