1 /*
2  * Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the
12  *       distribution.
13  *    3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
14  *       its contributors may be used to endorse or promote products derived
15  *       from this software without specific prior written permission.
16  *
17  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #ifndef _SYS_INTERRUPT_H_
31 #define _SYS_INTERRUPT_H_
32 
33 #include "compiler.h"
34 
35 #if defined(__CC_ARM)
36 /* ARM Compiler */
37 
38 /*
39  * CPU interrupt mask handling.
40  */
41 #define IRQMASK_REG_NAME_R primask
42 #define IRQMASK_REG_NAME_W primask
43 
44 /*
45  * Save the current interrupt enable state & disable IRQs
46  */
arch_irq_save(void)47 static __always_inline unsigned long arch_irq_save(void)
48 {
49     unsigned long flags;
50 
51     __asm {
52         mrs flags, IRQMASK_REG_NAME_R
53         cpsid   i
54     }
55     return flags;
56 }
57 
58 /*
59  * restore saved IRQ state
60  */
arch_irq_restore(unsigned long flags)61 static __always_inline void arch_irq_restore(unsigned long flags)
62 {
63     __asm { msr IRQMASK_REG_NAME_W, flags }
64 }
65 
66 /*
67  * Enable IRQs
68  */
69 #define arch_irq_enable()   __enable_irq()
70 
71 /*
72  * Disable IRQs
73  */
74 #define arch_irq_disable()  __disable_irq()
75 
76 /*
77  * Enable FIQs
78  */
79 #define arch_fiq_enable()   __enable_fiq()
80 
81 /*
82  * Disable FIQs
83  */
84 #define arch_fiq_disable()  __disable_fiq()
85 
86 #elif defined(__GNUC__)
87 /* GNU Compiler */
88 
89 #ifdef __CONFIG_OS_RTTHREAD
90 
91 /*
92  * Save the current interrupt enable state & disable IRQs
93  */
94 #define arch_irq_save(void) rt_hw_interrupt_disable()
95 
96 /*
97  * restore saved IRQ state
98  */
99 #define arch_irq_restore(flags) rt_hw_interrupt_enable(flags)
100 
101 /*
102  * Enable IRQs
103  */
104 #define arch_irq_enable()   rt_hw_interrupt_enable(__irq_level)
105 
106 /*
107  * Disable IRQs
108  */
109 #define arch_irq_disable()  rt_base_t __irq_level = rt_hw_interrupt_disable()
110 
111 #else /* __CONFIG_OS_RTTHREAD */
112 
113 /*
114  * CPU interrupt mask handling.
115  */
116 #define IRQMASK_REG_NAME_R "primask"
117 #define IRQMASK_REG_NAME_W "primask"
118 
119 /*
120  * Save the current interrupt enable state & disable IRQs
121  */
arch_irq_save(void)122 static __always_inline unsigned long arch_irq_save(void)
123 {
124     unsigned long flags;
125 
126     __asm volatile(
127         "mrs    %0, " IRQMASK_REG_NAME_R "\n"
128         "cpsid  i"
129         : "=r" (flags) : : "memory", "cc");
130     return flags;
131 }
132 
133 /*
134  * restore saved IRQ state
135  */
arch_irq_restore(unsigned long flags)136 static __always_inline void arch_irq_restore(unsigned long flags)
137 {
138     __asm volatile(
139         "msr    " IRQMASK_REG_NAME_W ", %0"
140         :
141         : "r" (flags)
142         : "memory", "cc");
143 }
144 
145 /*
146  * Save the current interrupt enable state.
147  */
arch_irq_get_flags(void)148 static __always_inline unsigned long arch_irq_get_flags(void)
149 {
150     unsigned long flags;
151 
152     __asm volatile(
153         "mrs    %0, " IRQMASK_REG_NAME_R "\n"
154         : "=r" (flags) : : "memory", "cc");
155     return flags;
156 
157 }
158 
159 /*
160  * Enable IRQs
161  */
162 #define arch_irq_enable()   __asm volatile("cpsie i" : : : "memory", "cc")
163 
164 /*
165  * Disable IRQs
166  */
167 #define arch_irq_disable()  __asm volatile("cpsid i" : : : "memory", "cc")
168 
169 /*
170  * Enable FIQs
171  */
172 #define arch_fiq_enable()   __asm volatile("cpsie f" : : : "memory", "cc")
173 
174 /*
175  * Disable FIQs
176  */
177 #define arch_fiq_disable()  __asm volatile("cpsid f" : : : "memory", "cc")
178 
179 #endif /* __CONFIG_OS_RTTHREAD */
180 
181 #else
182 #error "Compiler not supported."
183 #endif
184 
185 #endif /* _SYS_INTERRUPT_H_ */
186