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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-08-15 supperthomas add irq_test
* 2025-11-09 lhxj Add standardized utest documentation block
*/
/**
* Test Case Name: Kernel Core IRQ Test
*
* Test Objectives:
* - Clearly specify the core functional module being validated by this test
* - Validates the core kernel interrupt handling mechanisms.
* - List specific functions or APIs to be tested
* - rt_interrupt_enter_sethook()
* - rt_interrupt_leave_sethook()
* - rt_interrupt_get_nest()
* - rt_hw_interrupt_disable()
* - rt_hw_interrupt_enable()
*
* Test Scenarios:
* - **Scenario 1 (Hook Test / irq_test):**
* 1. Set interrupt enter/leave hooks that increment a counter (`irq_count`).
* 2. Delay the thread (`rt_thread_mdelay`) to allow a SysTick interrupt to occur.
* 3. Check if the hooks were triggered by the interrupt.
* - **Scenario 2 (Global Disable Test / interrupt_test):**
* 1. Set the same interrupt hooks.
* 2. Globally disable CPU interrupts using `rt_hw_interrupt_disable()`.
* 3. Execute a busy-wait loop.
* 4. Check if the hooks were *not* triggered, proving interrupts were masked.
*
* Verification Metrics:
* - List specific pass/fail criteria
* - Expected return values, state changes, resource usage, etc.
* - **Pass (Scenario 1):** `uassert_int_not_equal(0, irq_count)`
* (The hook counter must be non-zero after the delay).
* - **Pass (Scenario 1):** `uassert_int_not_equal(0, max_get_nest_count)`
* (The recorded nesting level must be non-zero).
* - **Pass (Scenario 2):** `uassert_int_equal(0, irq_count)`
* (The hook counter must remain zero while interrupts are disabled).
*
* Dependencies:
* - Hardware requirements (e.g., specific peripherals)
* - Requires a hardware timer to generate the SysTick (system tick) interrupt.
* (This is met by the qemu-virt64-riscv BSP).
* - Software configuration (e.g., kernel options, driver initialization)
* - `RT_USING_UTEST` must be enabled (`RT-Thread Utestcases`).
* - `IRQ Test` must be enabled (`RT-Thread Utestcases` -> `Kernel Core` -> 'IRQ Test').
* - Environmental assumptions
* - Assumes the system is idle enough for `rt_thread_mdelay(2)` to
* be interrupted by at least one SysTick.
* - Run the test case from the msh prompt:
* `utest_run core.irq`
*
* Expected Results:
* - System behavior and performance after test execution
* - The test case completes without errors or failed assertions.
* - Observable outcomes like console output, log records, etc.
* - The utest framework prints:
* `[ PASSED ] [ result ] testcase (core.irq)`
*/
#include <rtthread.h>
#include "utest.h"
#include "rthw.h"
#define UTEST_NAME "irq_tc"
static volatile uint32_t irq_count = 0;
static volatile uint32_t max_get_nest_count = 0;
static void irq_callback()
{
if(rt_interrupt_get_nest() > max_get_nest_count)
{
max_get_nest_count = rt_interrupt_get_nest();
}
irq_count ++;
}
static void irq_test(void)
{
irq_count = 0;
rt_interrupt_enter_sethook(irq_callback);
rt_interrupt_leave_sethook(irq_callback);
rt_thread_mdelay(2);
LOG_D("%s test irq_test! irq_count %d max_get_nest_count %d\n", UTEST_NAME, irq_count, max_get_nest_count);
uassert_int_not_equal(0, irq_count);
uassert_int_not_equal(0, max_get_nest_count);
rt_interrupt_enter_sethook(RT_NULL);
rt_interrupt_leave_sethook(RT_NULL);
LOG_D("irq_test OK!\n");
}
static rt_err_t utest_tc_init(void)
{
irq_count = 0;
max_get_nest_count = 0;
return RT_EOK;
}
static rt_err_t utest_tc_cleanup(void)
{
return RT_EOK;
}
static void interrupt_test(void)
{
rt_base_t level;
uint32_t i = 1000;
rt_interrupt_enter_sethook(irq_callback);
rt_interrupt_leave_sethook(irq_callback);
irq_count = 0;
level = rt_hw_interrupt_disable();
while(i)
{
i --;
}
uassert_int_equal(0, irq_count);
rt_hw_interrupt_enable(level);
rt_interrupt_enter_sethook(RT_NULL);
rt_interrupt_leave_sethook(RT_NULL);
}
static void testcase(void)
{
UTEST_UNIT_RUN(irq_test);
UTEST_UNIT_RUN(interrupt_test);
}
UTEST_TC_EXPORT(testcase, "core.irq", utest_tc_init, utest_tc_cleanup, 10);
|