Commit 92e00512 authored by Gustavo Romero's avatar Gustavo Romero Committed by Kumar Gala
Browse files

tests: Add test to check uart_irq_is_pending



Add test to check if uart_irq_is_pending() correctly returns 0 (meaning
there are no more RX and TX pending interrupts) when all RX and TX data
is processed.

Signed-off-by: default avatarGustavo Romero <gustavo.romero@linaro.org>
parent bd0fe17f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -10,3 +10,4 @@ target_sources(app PRIVATE
    src/test_uart_poll.c
    )
target_sources_ifdef(CONFIG_UART_INTERRUPT_DRIVEN app PRIVATE src/test_uart_fifo.c)
target_sources_ifdef(CONFIG_UART_INTERRUPT_DRIVEN app PRIVATE src/test_uart_pending.c)
+10 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ TC_CMD_DEFINE(test_uart_fifo_read)
TC_CMD_DEFINE(test_uart_fifo_fill)
TC_CMD_DEFINE(test_uart_poll_in)
TC_CMD_DEFINE(test_uart_poll_out)
TC_CMD_DEFINE(test_uart_pending)

SHELL_CMD_REGISTER(test_uart_configure, NULL, NULL,
			TC_CMD_ITEM(test_uart_configure));
@@ -33,6 +34,8 @@ SHELL_CMD_REGISTER(test_uart_poll_in, NULL, NULL,
			TC_CMD_ITEM(test_uart_poll_in));
SHELL_CMD_REGISTER(test_uart_poll_out, NULL, NULL,
			TC_CMD_ITEM(test_uart_poll_out));
SHELL_CMD_REGISTER(test_uart_pending, NULL, NULL,
			TC_CMD_ITEM(test_uart_pending));
#endif

#ifndef CONFIG_UART_INTERRUPT_DRIVEN
@@ -45,6 +48,11 @@ void test_uart_fifo_read(void)
{
	ztest_test_skip();
}

void test_uart_pending(void)
{
	ztest_test_skip();
}
#endif

void test_main(void)
@@ -56,7 +64,8 @@ void test_main(void)
			 ztest_unit_test(test_uart_fifo_fill),
			 ztest_unit_test(test_uart_fifo_read),
			 ztest_unit_test(test_uart_poll_in),
			 ztest_unit_test(test_uart_poll_out));
			 ztest_unit_test(test_uart_poll_out),
			 ztest_unit_test(test_uart_pending));
	ztest_run_test_suite(uart_basic_test);
#endif
}
+1 −0
Original line number Diff line number Diff line
@@ -26,5 +26,6 @@ void test_uart_poll_out(void);
void test_uart_fifo_fill(void);
void test_uart_fifo_read(void);
void test_uart_poll_in(void);
void test_uart_pending(void);

#endif /* __TEST_UART_H__ */
+140 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2021 Linaro Limited
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/*
 * @addtogroup t_uart_basic
 * @{
 * @defgroup t_uart_fifo test_uart_pending
 * @brief TestPurpose: test UART uart_irq_is_pending()
 * @details
 *
 * Test if uart_irq_is_pending() correctly returns 0 when there are no
 * more RX and TX pending interrupts.
 *
 * The test consists in disabling TX IRQ so no TX interrupts are
 * generated and the TX IRQ pending flag is never set. At the same time
 * RX IRQ is enabled to let received data cause a RX IRQ and so set the
 * RX IRQ pending flag.
 *
 * Then a message is sent via serial to inform that the test is ready to
 * receive serial data, which will trigger a RX IRQ.
 *
 * Once a RX IRQ happens RX data is read by uart_fifo_read() until there
 * is no more RX data to be popped from FIFO and all IRQs are handled.
 * When that happens uart_irq_is_pending() is called and must return 0,
 * indicating there are no more pending interrupts to be processed. If 0
 * is returned the test passes.
 *
 * In some cases uart_irq_is_pending() does not correctly use the IRQ
 * pending flags to determine if there are pending interrupts, hence
 * even tho there aren't any further RX and TX IRQs to be processed it
 * wrongly returns 1. If 1 is returned the test fails.
 *
 * @}
 */

#include "test_uart.h"

#define MAX_NUM_TRIES 512
#define NOT_READY 0

#define FAILED	0
#define PASSED	1
#define WAIT	2
static int volatile status;

static void uart_pending_callback(const struct device *dev, void *user_data)
{
	ARG_UNUSED(user_data);

	int num_tries = 0;
	char recv_char;

	/*
	 * If the bug is not present uart_fifo_read() will pop all
	 * received data until there is no more RX data, thus
	 * uart_irq_is_pending() must correctly return 0 indicating
	 * that there are no more RX interrupts to be processed.
	 * Otherwise uart_irq_is_pending() never returns 0 even tho
	 * there is no more RX data in the RX buffer to be processed,
	 * so, in that case, the test fails after MAX_NUM_TRIES attempts.
	 */
	status = PASSED;
	while (uart_irq_update(dev) && uart_irq_is_pending(dev)) {
		if (uart_irq_rx_ready(dev) == NOT_READY) {
			if (num_tries < MAX_NUM_TRIES) {
				num_tries++;
				continue;
			} else {
				/*
				 * Bug: no more tries; uart_irq_is_pending()
				 * always returned 1 in spite of having no more
				 * RX data to be read from FIFO and no more TX
				 * data in FIFO to be sent via serial line.
				 * N.B. uart_irq_update() always returns 1, thus
				 * uart_irq_is_pending() got stuck without any
				 * real pending interrupt, i.e. no more RX and
				 * TX data to be popped or pushed from/to FIFO.
				 */
				status = FAILED;
				break;
			}
		}

		while (uart_fifo_read(dev, &recv_char, 1)) {
			/* Echo received char */
			TC_PRINT("%c", recv_char);
		}
	}
}

static int test_pending(void)
{
	const struct device *uart_dev = device_get_binding(UART_DEVICE_NAME);

	/*
	 * Set IRQ callback function to handle RX IRQ.
	 */
	uart_irq_callback_set(uart_dev, uart_pending_callback);

	/*
	 * Disable TX IRQ since transmitted data is not
	 * handled by uart_pending_callback() and we don't
	 * want to trigger any TX IRQ for this test.
	 */
	uart_irq_tx_disable(uart_dev);

	/*
	 * Enable RX IRQ so uart_pending_callback() can
	 * handle input data is available in RX FIFO.
	 */
	uart_irq_rx_enable(uart_dev);

	status = WAIT;

	/* Inform test is ready to receive data */
	TC_PRINT("Please send characters to serial console\n");

	while (status == WAIT) {
		/*
		 * Wait RX handler change 'status' properly:
		 * it will change to PASSED or FAILED after
		 * uart_irq_is_pending() is tested by
		 * uart_pending_callback() upon data reception.
		 */
	}

	if (status == PASSED) {
		return TC_PASS;
	} else {
		return TC_FAIL;
	}
}

void test_uart_pending(void)
{
	zassert_true(test_pending() == TC_PASS, NULL);
}