/*************************************************************************** * Copyright (c) 2026 Eclipse ThreadX contributors * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at * https://opensource.org/licenses/MIT. * * AI Disclosure: This file was largely AI-generated by Codex (GPT-6-Sol). * The AI-generated portions may be considered public domain (CC0-1.0) * and not subject to the project's licence. The human contributor has * reviewed and verified that the code is correct. * * SPDX-License-Identifier: MIT and CC0-1.0 ***************************************************************************/ #include "tx_api.h" #include "csr.h" #include "hwtimer.h" #include "plic.h" #include "uart.h" #define TEST_TIMER_INTERVAL 8u #define TEST_REQUIRED_INTERRUPTS 10000u static TX_THREAD test_thread; static UCHAR test_stack[2048]; volatile unsigned int test_irq_count; volatile unsigned int test_expected_bit; /* Run the kernel with the board's normal interrupt setup. */ int main(void) { tx_kernel_enter(); return 0; } /* Compare the PLIC word and the ISR's expected bit atomically. */ static int test_bit_matches(void) { int enabled = riscv_mintr_save(); /* MISRA C:2012 Rule 11.4 deviation: the PLIC has a fixed MMIO address. */ uint32_t actual = *(volatile uint32_t *)PLIC_MENABLE(0u) & (1u << 2); unsigned int expected = test_expected_bit; riscv_mintr_restore(enabled); return actual == (expected != 0u ? (1u << 2) : 0u); } /* Change source 1 while the timer ISR changes source 2. */ static void test_entry(ULONG input) { (void)input; /* MISRA C:2012 Rule 11.4 deviation: the timer has a fixed MMIO address. */ *(volatile uint64_t *)ERBIUM_MTIMECMP = *(volatile uint64_t *)ERBIUM_MTIME + TEST_TIMER_INTERVAL; while (test_irq_count < TEST_REQUIRED_INTERRUPTS) { plic_irq_enable(1); if (!test_bit_matches()) { uart_puts("TEST_PLIC_LOST_UPDATE"); for (;;) { } } plic_irq_disable(1); if (!test_bit_matches()) { uart_puts("TEST_PLIC_LOST_UPDATE"); for (;;) { } } } uart_puts("TEST_PLIC_NO_LOST_UPDATE"); for (;;) { } } /* Start one test thread. */ void tx_application_define(void *first_unused_memory) { (void)first_unused_memory; (void)tx_thread_create(&test_thread, "plic test", test_entry, 0u, test_stack, sizeof(test_stack), 1u, 1u, TX_NO_TIME_SLICE, TX_AUTO_START); }