-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Expand file tree
/
Copy pathirq.c
More file actions
157 lines (135 loc) · 4.03 KB
/
Copy pathirq.c
File metadata and controls
157 lines (135 loc) · 4.03 KB
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2006-02-24 Bernard first version
* 2006-05-03 Bernard add IRQ_DEBUG
* 2016-08-09 ArdaFu add interrupt enter and leave hook.
* 2018-11-22 Jesven rt_interrupt_get_nest function add disable irq
* 2021-08-15 Supperthomas fix the comment
* 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to irq.c
* 2022-07-04 Yunjie fix RT_DEBUG_LOG
* 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
* 2024-01-05 Shell Fixup of data racing in rt_interrupt_get_nest
* 2024-01-03 Shell Support for interrupt context
*/
#include <rthw.h>
#include <rtthread.h>
#define DBG_TAG "kernel.irq"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
void (*rt_interrupt_enter_hook)(void);
void (*rt_interrupt_leave_hook)(void);
/**
* @ingroup group_hook
*
* @brief This function set a hook function when the system enter a interrupt
*
* @note The hook function must be simple and never be blocked or suspend.
*
* @param hook the function point to be called
*/
void rt_interrupt_enter_sethook(void (*hook)(void))
{
rt_interrupt_enter_hook = hook;
}
/**
* @ingroup group_hook
*
* @brief This function set a hook function when the system exit a interrupt.
*
* @note The hook function must be simple and never be blocked or suspend.
*
* @param hook the function point to be called
*/
void rt_interrupt_leave_sethook(void (*hook)(void))
{
rt_interrupt_leave_hook = hook;
}
#endif /* RT_USING_HOOK */
/**
* @addtogroup group_kernel_core
*/
/**@{*/
#ifdef RT_USING_SMP
#define rt_interrupt_nest rt_cpu_self()->irq_nest
#else
volatile rt_atomic_t rt_interrupt_nest = 0;
#endif /* RT_USING_SMP */
#ifdef ARCH_USING_IRQ_CTX_LIST
void rt_interrupt_context_push(rt_interrupt_context_t this_ctx)
{
struct rt_cpu *this_cpu = rt_cpu_self();
rt_slist_insert(&this_cpu->irq_ctx_head, &this_ctx->node);
}
void rt_interrupt_context_pop(void)
{
struct rt_cpu *this_cpu = rt_cpu_self();
rt_slist_pop(&this_cpu->irq_ctx_head);
}
void *rt_interrupt_context_get(void)
{
struct rt_cpu *this_cpu = rt_cpu_self();
return rt_slist_first_entry(&this_cpu->irq_ctx_head, struct rt_interrupt_context, node)->context;
}
#endif /* ARCH_USING_IRQ_CTX_LIST */
/**
* @brief This function will be invoked by BSP, when enter interrupt service routine
*
* @note Please don't invoke this routine in application
*
* @see rt_interrupt_leave
*/
rt_weak void rt_interrupt_enter(void)
{
rt_atomic_add(&(rt_interrupt_nest), 1);
RT_OBJECT_HOOK_CALL(rt_interrupt_enter_hook,());
LOG_D("irq has come..., irq current nest:%d",
(rt_int32_t)rt_atomic_load(&(rt_interrupt_nest)));
}
RTM_EXPORT(rt_interrupt_enter);
/**
* @brief This function will be invoked by BSP, when leave interrupt service routine
*
* @note Please don't invoke this routine in application
*
* @see rt_interrupt_enter
*/
rt_weak void rt_interrupt_leave(void)
{
LOG_D("irq is going to leave, irq current nest:%d",
(rt_int32_t)rt_atomic_load(&(rt_interrupt_nest)));
RT_OBJECT_HOOK_CALL(rt_interrupt_leave_hook,());
rt_atomic_sub(&(rt_interrupt_nest), 1);
}
RTM_EXPORT(rt_interrupt_leave);
/**
* @brief This function will return the nest of interrupt.
*
* User application can invoke this function to get whether current
* context is interrupt context.
*
* @return the number of nested interrupts.
*/
rt_weak rt_uint8_t rt_interrupt_get_nest(void)
{
rt_uint8_t ret;
rt_base_t level;
level = rt_hw_local_irq_disable();
ret = rt_atomic_load(&rt_interrupt_nest);
rt_hw_local_irq_enable(level);
return ret;
}
RTM_EXPORT(rt_interrupt_get_nest);
RTM_EXPORT(rt_hw_interrupt_disable);
RTM_EXPORT(rt_hw_interrupt_enable);
rt_weak rt_bool_t rt_hw_interrupt_is_disabled(void)
{
return RT_FALSE;
}
RTM_EXPORT(rt_hw_interrupt_is_disabled);
/**@}*/