1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2006-02-24 Bernard first version
9 * 2006-05-03 Bernard add IRQ_DEBUG
10 * 2016-08-09 ArdaFu add interrupt enter and leave hook.
11 * 2018-11-22 Jesven rt_interrupt_get_nest function add disable irq
12 */
13
14 #include <rthw.h>
15 #include <rtthread.h>
16
17 #ifdef RT_USING_HOOK
18
19 static void (*rt_interrupt_enter_hook)(void);
20 static void (*rt_interrupt_leave_hook)(void);
21
22 /**
23 * @ingroup Hook
24 * This function set a hook function when the system enter a interrupt
25 *
26 * @note the hook function must be simple and never be blocked or suspend.
27 */
rt_interrupt_enter_sethook(void (* hook)(void))28 void rt_interrupt_enter_sethook(void (*hook)(void))
29 {
30 rt_interrupt_enter_hook = hook;
31 }
32 /**
33 * @ingroup Hook
34 * This function set a hook function when the system exit a interrupt.
35 *
36 * @note the hook function must be simple and never be blocked or suspend.
37 */
rt_interrupt_leave_sethook(void (* hook)(void))38 void rt_interrupt_leave_sethook(void (*hook)(void))
39 {
40 rt_interrupt_leave_hook = hook;
41 }
42 #endif
43
44 /* #define IRQ_DEBUG */
45
46 /**
47 * @addtogroup Kernel
48 */
49
50 /**@{*/
51
52 #ifdef RT_USING_SMP
53 #define rt_interrupt_nest rt_cpu_self()->irq_nest
54 #else
55 volatile rt_uint8_t rt_interrupt_nest = 0;
56 #endif
57
58 /**
59 * This function will be invoked by BSP, when enter interrupt service routine
60 *
61 * @note please don't invoke this routine in application
62 *
63 * @see rt_interrupt_leave
64 */
rt_interrupt_enter(void)65 void rt_interrupt_enter(void)
66 {
67 rt_base_t level;
68
69 RT_DEBUG_LOG(RT_DEBUG_IRQ, ("irq coming..., irq nest:%d\n",
70 rt_interrupt_nest));
71
72 level = rt_hw_interrupt_disable();
73 rt_interrupt_nest ++;
74 RT_OBJECT_HOOK_CALL(rt_interrupt_enter_hook,());
75 rt_hw_interrupt_enable(level);
76 }
77 RTM_EXPORT(rt_interrupt_enter);
78
79 /**
80 * This function will be invoked by BSP, when leave interrupt service routine
81 *
82 * @note please don't invoke this routine in application
83 *
84 * @see rt_interrupt_enter
85 */
rt_interrupt_leave(void)86 void rt_interrupt_leave(void)
87 {
88 rt_base_t level;
89
90 RT_DEBUG_LOG(RT_DEBUG_IRQ, ("irq leave, irq nest:%d\n",
91 rt_interrupt_nest));
92
93 level = rt_hw_interrupt_disable();
94 rt_interrupt_nest --;
95 RT_OBJECT_HOOK_CALL(rt_interrupt_leave_hook,());
96 rt_hw_interrupt_enable(level);
97 }
98 RTM_EXPORT(rt_interrupt_leave);
99
100 /**
101 * This function will return the nest of interrupt.
102 *
103 * User application can invoke this function to get whether current
104 * context is interrupt context.
105 *
106 * @return the number of nested interrupts.
107 */
rt_interrupt_get_nest(void)108 rt_uint8_t rt_interrupt_get_nest(void)
109 {
110 rt_uint8_t ret;
111 rt_base_t level;
112
113 level = rt_hw_interrupt_disable();
114 ret = rt_interrupt_nest;
115 rt_hw_interrupt_enable(level);
116 return ret;
117 }
118 RTM_EXPORT(rt_interrupt_get_nest);
119
120 RTM_EXPORT(rt_hw_interrupt_disable);
121 RTM_EXPORT(rt_hw_interrupt_enable);
122
123 /**@}*/
124
125