1 /***************************************************************************//**
2  * @file
3  * @brief Core interrupt handling API (Generic)
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 
31 #ifndef EM_CORE_GENERIC_H
32 #define EM_CORE_GENERIC_H
33 
34 #include <stdbool.h>
35 #include <stdint.h>
36 
37 /***************************************************************************//**
38  * @addtogroup core
39  * @{
40  ******************************************************************************/
41 
42 /*******************************************************************************
43  *******************************   DEFINES   ***********************************
44  ******************************************************************************/
45 
46 /** Use PRIMASK register to disable interrupts in ATOMIC sections. */
47 #define CORE_ATOMIC_METHOD_PRIMASK  0
48 
49 /** Use BASEPRI register to disable interrupts in ATOMIC sections. */
50 #define CORE_ATOMIC_METHOD_BASEPRI  1
51 
52 #if !defined(CORE_ATOMIC_BASE_PRIORITY_LEVEL)
53 /** The interrupt priority level disabled within ATOMIC regions. Interrupts
54  *  with priority level equal to or lower than this definition will be disabled
55  *  within ATOMIC regions. */
56 #define CORE_ATOMIC_BASE_PRIORITY_LEVEL  3
57 #endif
58 
59 #ifdef __cplusplus
60 extern "C" {
61 #endif
62 
63 /*******************************************************************************
64  ************************   MACRO API   ***************************************
65  ******************************************************************************/
66 
67 //
68 //  CRITICAL section macro API.
69 //
70 
71 /** Allocate storage for PRIMASK or BASEPRI value for use by
72  *  CORE_ENTER/EXIT_ATOMIC() and CORE_ENTER/EXIT_CRITICAL() macros. */
73 #define CORE_DECLARE_IRQ_STATE        CORE_irqState_t irqState
74 
75 /** CRITICAL style interrupt disable. */
76 #define CORE_CRITICAL_IRQ_DISABLE() CORE_CriticalDisableIrq()
77 
78 /** CRITICAL style interrupt enable. */
79 #define CORE_CRITICAL_IRQ_ENABLE()  CORE_CriticalEnableIrq()
80 
81 /** Convenience macro for implementing a CRITICAL section. */
82 #define CORE_CRITICAL_SECTION(yourcode) \
83   {                                     \
84     CORE_DECLARE_IRQ_STATE;             \
85     CORE_ENTER_CRITICAL();              \
86     {                                   \
87       yourcode                          \
88     }                                   \
89     CORE_EXIT_CRITICAL();               \
90   }
91 
92 /** Enter CRITICAL section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in
93  *  scope. */
94 #define CORE_ENTER_CRITICAL()   irqState = CORE_EnterCritical()
95 
96 /** Exit CRITICAL section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in
97  *  scope. */
98 #define CORE_EXIT_CRITICAL()    CORE_ExitCritical(irqState)
99 
100 /** CRITICAL style yield. */
101 #define CORE_YIELD_CRITICAL()   CORE_YieldCritical()
102 
103 //
104 //  ATOMIC section macro API.
105 //
106 
107 /** ATOMIC style interrupt disable. */
108 #define CORE_ATOMIC_IRQ_DISABLE()   CORE_AtomicDisableIrq()
109 
110 /** ATOMIC style interrupt enable. */
111 #define CORE_ATOMIC_IRQ_ENABLE()    CORE_AtomicEnableIrq()
112 
113 /** Convenience macro for implementing an ATOMIC section. */
114 #define CORE_ATOMIC_SECTION(yourcode) \
115   {                                   \
116     CORE_DECLARE_IRQ_STATE;           \
117     CORE_ENTER_ATOMIC();              \
118     {                                 \
119       yourcode                        \
120     }                                 \
121     CORE_EXIT_ATOMIC();               \
122   }
123 
124 /** Enter ATOMIC section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in
125  *  scope. */
126 #define CORE_ENTER_ATOMIC()   irqState = CORE_EnterAtomic()
127 
128 /** Exit ATOMIC section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in
129  *  scope. */
130 #define CORE_EXIT_ATOMIC()    CORE_ExitAtomic(irqState)
131 
132 /** ATOMIC style yield. */
133 #define CORE_YIELD_ATOMIC()   CORE_YieldAtomic()
134 
135 /** Check if IRQ is disabled. */
136 #define CORE_IRQ_DISABLED()       CORE_IrqIsDisabled()
137 
138 /** Check if inside an IRQ handler. */
139 #define CORE_IN_IRQ_CONTEXT()     CORE_InIrqContext()
140 
141 /*******************************************************************************
142  *************************   TYPEDEFS   ****************************************
143  ******************************************************************************/
144 
145 /** Storage for PRIMASK or BASEPRI value. */
146 typedef uint32_t CORE_irqState_t;
147 
148 /*******************************************************************************
149  *****************************   PROTOTYPES   **********************************
150  ******************************************************************************/
151 
152 void CORE_CriticalDisableIrq(void);
153 void CORE_CriticalEnableIrq(void);
154 void CORE_ExitCritical(CORE_irqState_t irqState);
155 void CORE_YieldCritical(void);
156 CORE_irqState_t CORE_EnterCritical(void);
157 
158 void  CORE_AtomicDisableIrq(void);
159 void  CORE_AtomicEnableIrq(void);
160 void  CORE_ExitAtomic(CORE_irqState_t irqState);
161 void  CORE_YieldAtomic(void);
162 CORE_irqState_t CORE_EnterAtomic(void);
163 
164 bool  CORE_InIrqContext(void);
165 bool  CORE_IrqIsDisabled(void);
166 
167 #ifdef __cplusplus
168 }
169 #endif
170 
171 /** @} (end addtogroup core) */
172 
173 #endif /* EM_CORE_GENERIC_H */
174