summaryrefslogtreecommitdiff
path: root/ports/risc-v64/gnu/example_build/erbium/test/test_plic_race.c
blob: d6f2a3b579883d823944b0f8c98b6575cfd35b4d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/***************************************************************************
 * 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);
}