1 /*
2  * FreeRTOS Kernel V11.1.0
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28 
29 #ifndef PORTMACRO_H
30 #define PORTMACRO_H
31 
32 /* *INDENT-OFF* */
33 #ifdef __cplusplus
34     extern "C" {
35 #endif
36 /* *INDENT-ON* */
37 
38 /*-----------------------------------------------------------
39  * Port specific definitions.
40  *
41  * The settings in this file configure FreeRTOS correctly for the given hardware
42  * and compiler.
43  *
44  * These settings should not be altered.
45  *-----------------------------------------------------------
46  */
47 
48 /* Type definitions. */
49 #define portCHAR          char
50 #define portFLOAT         float
51 #define portDOUBLE        double
52 #define portLONG          long
53 #define portSHORT         short
54 #define portSTACK_TYPE    uint32_t
55 #define portBASE_TYPE     long
56 
57 typedef portSTACK_TYPE   StackType_t;
58 typedef long             BaseType_t;
59 typedef unsigned long    UBaseType_t;
60 
61 typedef uint32_t         TickType_t;
62 #define portMAX_DELAY    ( ( TickType_t ) 0xffffffffUL )
63 
64 /*-----------------------------------------------------------*/
65 
66 /* Hardware specifics. */
67 #define portSTACK_GROWTH      ( -1 )
68 #define portTICK_PERIOD_MS    ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
69 #define portBYTE_ALIGNMENT    32
70 
71 /*-----------------------------------------------------------*/
72 
73 /* Task utilities. */
74 
75 /* The interrupt priority (for vectors 16 to 255) is determined using vector/16.
76  * The quotient is rounded to the nearest integer with 1 being the lowest priority
77  * and 15 is the highest.  Therefore the following two interrupts are at the lowest
78  * priority.  *NOTE 1* If the yield vector is changed then it must also be changed
79  * in the portYIELD_INTERRUPT definition immediately below. */
80 #define portAPIC_TIMER_INT_VECTOR       ( 0x21 )
81 #define portAPIC_YIELD_INT_VECTOR       ( 0x20 )
82 
83 /* Build yield interrupt instruction. */
84 #define portYIELD_INTERRUPT             "int $0x20"
85 
86 /* APIC register addresses. */
87 #define portAPIC_EOI                    ( *( ( volatile uint32_t * ) 0xFEE000B0UL ) )
88 
89 /* APIC bit definitions. */
90 #define portAPIC_ENABLE_BIT             ( 1UL << 8UL )
91 #define portAPIC_TIMER_PERIODIC         ( 1UL << 17UL )
92 #define portAPIC_DISABLE                ( 1UL << 16UL )
93 #define portAPIC_NMI                    ( 4 << 8 )
94 #define portAPIC_DIV_16                 ( 0x03 )
95 
96 /* Define local API register addresses. */
97 #define portAPIC_ID_REGISTER            ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x20UL ) ) )
98 #define portAPIC_SPURIOUS_INT           ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xF0UL ) ) )
99 #define portAPIC_LVT_TIMER              ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x320UL ) ) )
100 #define portAPIC_TIMER_INITIAL_COUNT    ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x380UL ) ) )
101 #define portAPIC_TIMER_CURRENT_COUNT    ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x390UL ) ) )
102 #define portAPIC_TASK_PRIORITY          ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x80UL ) ) )
103 #define portAPIC_LVT_ERROR              ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x370UL ) ) )
104 #define portAPIC_ERROR_STATUS           ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x280UL ) ) )
105 #define portAPIC_LDR                    ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xD0UL ) ) )
106 #define portAPIC_TMRDIV                 ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x3E0UL ) ) )
107 #define portAPIC_LVT_PERF               ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x340UL ) ) )
108 #define portAPIC_LVT_LINT0              ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x350UL ) ) )
109 #define portAPIC_LVT_LINT1              ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x360UL ) ) )
110 
111 /* Don't yield if inside a critical section - instead hold the yield pending
112  * so it is performed when the critical section is exited. */
113 #define portYIELD()                                  \
114     {                                                \
115         extern volatile uint32_t ulCriticalNesting;  \
116         extern volatile uint32_t ulPortYieldPending; \
117         if( ulCriticalNesting != 0 )                 \
118         {                                            \
119             ulPortYieldPending = pdTRUE;             \
120         }                                            \
121         else                                         \
122         {                                            \
123             __asm volatile ( portYIELD_INTERRUPT );  \
124         }                                            \
125     }
126 
127 /* Called at the end of an ISR that can cause a context switch - pend a yield if
128  * xSwitchRequired is not false. */
129 #define portEND_SWITCHING_ISR( xSwitchRequired )     \
130     {                                                \
131         extern volatile uint32_t ulPortYieldPending; \
132         if( xSwitchRequired != pdFALSE )             \
133         {                                            \
134             ulPortYieldPending = 1;                  \
135         }                                            \
136     }
137 
138 /* Same as portEND_SWITCHING_ISR() - take your pick which name to use. */
139 #define portYIELD_FROM_ISR( x )    portEND_SWITCHING_ISR( x )
140 
141 /*-----------------------------------------------------------
142 * Critical section control
143 *----------------------------------------------------------*/
144 
145 /* Critical sections for use in interrupts. */
146 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulPortSetInterruptMask()
147 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vPortClearInterruptMask( x )
148 
149 extern void vPortEnterCritical( void );
150 extern void vPortExitCritical( void );
151 extern uint32_t ulPortSetInterruptMask( void );
152 extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
153 
154 /* These macros do not globally disable/enable interrupts.  They do mask off
155  * interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
156 #define portENTER_CRITICAL()        vPortEnterCritical()
157 #define portEXIT_CRITICAL()         vPortExitCritical()
158 #define portDISABLE_INTERRUPTS()    __asm volatile ( "cli" )
159 #define portENABLE_INTERRUPTS()     __asm volatile ( "sti" )
160 
161 /*-----------------------------------------------------------*/
162 
163 /* Task function macros as described on the FreeRTOS.org WEB site.  These are
164  * not required for this port but included in case common demo code that uses these
165  * macros is used. */
166 #define portTASK_FUNCTION_PROTO( vFunction, pvParameters )    void vFunction( void * pvParameters )
167 #define portTASK_FUNCTION( vFunction, pvParameters )          void vFunction( void * pvParameters )
168 
169 /* Architecture specific optimisations. */
170 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
171 
172 /* Store/clear the ready priorities in a bit map. */
173     #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \
174     __asm volatile ( "bsr %1, %0\n\t"                                    \
175                      : "=r" ( uxTopPriority ) : "rm" ( uxReadyPriorities ) : "cc" )
176 
177     #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities )    ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
178     #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities )     ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
179 
180 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
181 
182 #define portNOP()    __asm volatile ( "NOP" )
183 
184 /*-----------------------------------------------------------
185 * Misc
186 *----------------------------------------------------------*/
187 
188 #define portNUM_VECTORS     256
189 #define portMAX_PRIORITY    15
190 typedef void ( * ISR_Handler_t ) ( void );
191 
192 /* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
193  * before any floating point instructions are executed. */
194 #ifndef configSUPPORT_FPU
195     #define configSUPPORT_FPU    0
196 #endif
197 
198 #if configSUPPORT_FPU == 1
199     void vPortTaskUsesFPU( void );
200     #define portTASK_USES_FLOATING_POINT()    vPortTaskUsesFPU()
201 #endif
202 
203 /* See the comments under the configUSE_COMMON_INTERRUPT_ENTRY_POINT definition
204  * below. */
205 BaseType_t xPortRegisterCInterruptHandler( ISR_Handler_t pxHandler,
206                                            uint32_t ulVectorNumber );
207 BaseType_t xPortInstallInterruptHandler( ISR_Handler_t pxHandler,
208                                          uint32_t ulVectorNumber );
209 
210 #ifndef configAPIC_BASE
211 
212 /* configAPIC_BASE_ADDRESS sets the base address of the local APIC.  It can
213  * be overridden in FreeRTOSConfig.h should it not be constant. */
214     #define configAPIC_BASE    0xFEE00000UL
215 #endif
216 
217 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
218 
219 /* The FreeRTOS scheduling algorithm selects the task that will enter the
220  * Running state.  configUSE_PORT_OPTIMISED_TASK_SELECTION is used to set how
221  * that is done.
222  *
223  * If configUSE_PORT_OPTIMISED_TASK_SELECTION is set to 0 then the task to
224  * enter the Running state is selected using a portable algorithm written in
225  * C.  This is the slowest method, but the algorithm does not restrict the
226  * maximum number of unique RTOS task priorities that are available.
227  *
228  * If configUSE_PORT_OPTIMISED_TASK_SELECTION is set to 1 then the task to
229  * enter the Running state is selected using a single assembly instruction.
230  * This is the fastest method, but restricts the maximum number of unique RTOS
231  * task priorities to 32 (the same task priority can be assigned to any number
232  * of RTOS tasks). */
233     #warning configUSE_PORT_OPTIMISED_TASK_SELECTION was not defined in FreeRTOSConfig.h and has been defaulted to 1
234     #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
235 #endif
236 
237 #ifndef configUSE_COMMON_INTERRUPT_ENTRY_POINT
238 
239 /* There are two ways of implementing interrupt handlers:
240  *
241  *  1) As standard C functions -
242  *
243  *  This method can only be used if configUSE_COMMON_INTERRUPT_ENTRY_POINT
244  *  is set to 1.  The C function is installed using
245  *  xPortRegisterCInterruptHandler().
246  *
247  *  This is the simplest of the two methods but incurs a slightly longer
248  *  interrupt entry time.
249  *
250  *  2) By using an assembly stub that wraps the handler in the FreeRTOS
251  *     portFREERTOS_INTERRUPT_ENTRY and portFREERTOS_INTERRUPT_EXIT macros.
252  *
253  *  This method can always be used.  It is slightly more complex than
254  *  method 1 but benefits from a faster interrupt entry time. */
255     #warning configUSE_COMMON_INTERRUPT_ENTRY_POINT was not defined in FreeRTOSConfig.h and has been defaulted to 1.
256     #define configUSE_COMMON_INTERRUPT_ENTRY_POINT    1
257 #endif
258 
259 #ifndef configISR_STACK_SIZE
260 
261 /* Interrupt entry code will switch the stack in use to a dedicated system
262  * stack.
263  *
264  * configISR_STACK_SIZE defines the number of 32-bit values that can be stored
265  * on the system stack, and must be large enough to hold a potentially nested
266  * interrupt stack frame. */
267 
268     #error configISR_STACK_SIZE was not defined in FreeRTOSConfig.h.
269 #endif
270 
271 #ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
272 
273 /* Interrupt safe FreeRTOS functions (those that end in "FromISR" must not
274  * be called from an interrupt that has a priority above that set by
275  * configMAX_API_CALL_INTERRUPT_PRIORITY.  */
276     #warning configMAX_API_CALL_INTERRUPT_PRIORITY was not defined in FreeRTOSConfig.h and has been defaulted to 10
277     #define configMAX_API_CALL_INTERRUPT_PRIORITY    10
278 #endif
279 
280 #ifndef configSUPPORT_FPU
281     #warning configSUPPORT_FPU was not defined in FreeRTOSConfig.h and has been defaulted to 0
282     #define configSUPPORT_FPU    0
283 #endif
284 
285 /* The value written to the task priority register to raise the interrupt mask
286  * to the maximum from which FreeRTOS API calls can be made. */
287 #define portAPIC_PRIORITY_SHIFT        ( 4UL )
288 #define portAPIC_MAX_SUB_PRIORITY      ( 0x0fUL )
289 #define portMAX_API_CALL_PRIORITY      ( ( configMAX_API_CALL_INTERRUPT_PRIORITY << portAPIC_PRIORITY_SHIFT ) | portAPIC_MAX_SUB_PRIORITY )
290 
291 /* Asserts if interrupt safe FreeRTOS functions are called from a priority
292  * above the max system call interrupt priority. */
293 #define portAPIC_PROCESSOR_PRIORITY    ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xA0UL ) ) )
294 #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()    configASSERT( ( portAPIC_PROCESSOR_PRIORITY ) <= ( portMAX_API_CALL_PRIORITY ) )
295 
296 /* *INDENT-OFF* */
297 #ifdef __cplusplus
298     }
299 #endif
300 /* *INDENT-ON* */
301 
302 #endif /* PORTMACRO_H */
303