]> begriffs open source - freertos/blob - portable/ThirdParty/GCC/RP2040/include/portmacro.h
SMP version (#401)
[freertos] / portable / ThirdParty / GCC / RP2040 / include / portmacro.h
1 /*\r
2  * FreeRTOS Kernel V202110.00\r
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  * Copyright (c) 2021 Raspberry Pi (Trading) Ltd.\r
5  *\r
6  * SPDX-License-Identifier: MIT AND BSD-3-Clause\r
7  *\r
8  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
9  * this software and associated documentation files (the "Software"), to deal in\r
10  * the Software without restriction, including without limitation the rights to\r
11  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
12  * the Software, and to permit persons to whom the Software is furnished to do so,\r
13  * subject to the following conditions:\r
14  *\r
15  * The above copyright notice and this permission notice shall be included in all\r
16  * copies or substantial portions of the Software.\r
17  *\r
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
20  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
21  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
22  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
24  *\r
25  * https://www.FreeRTOS.org\r
26  * https://github.com/FreeRTOS\r
27  *\r
28  */\r
29 \r
30 #ifndef PORTMACRO_H\r
31     #define PORTMACRO_H\r
32 \r
33     #ifdef __cplusplus\r
34         extern "C" {\r
35     #endif\r
36 \r
37     #include "pico.h"\r
38     #include "hardware/sync.h"\r
39 \r
40 /*-----------------------------------------------------------\r
41  * Port specific definitions.\r
42  *\r
43  * The settings in this file configure FreeRTOS correctly for the\r
44  * given hardware and compiler.\r
45  *\r
46  * These settings should not be altered.\r
47  *-----------------------------------------------------------\r
48  */\r
49 \r
50 /* Type definitions. */\r
51     #define portCHAR          char\r
52     #define portFLOAT         float\r
53     #define portDOUBLE        double\r
54     #define portLONG          long\r
55     #define portSHORT         short\r
56     #define portSTACK_TYPE    uint32_t\r
57     #define portBASE_TYPE     long\r
58 \r
59     typedef portSTACK_TYPE    StackType_t;\r
60     typedef int32_t           BaseType_t;\r
61     typedef uint32_t          UBaseType_t;\r
62 \r
63     #if ( configUSE_16_BIT_TICKS == 1 )\r
64         typedef uint16_t     TickType_t;\r
65         #define portMAX_DELAY              ( TickType_t ) 0xffff\r
66     #else\r
67         typedef uint32_t     TickType_t;\r
68         #define portMAX_DELAY              ( TickType_t ) 0xffffffffUL\r
69 \r
70 /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do\r
71  * not need to be guarded with a critical section. */\r
72         #define portTICK_TYPE_IS_ATOMIC    1\r
73     #endif\r
74 /*-----------------------------------------------------------*/\r
75 \r
76 /* Architecture specifics. */\r
77     #define portSTACK_GROWTH      ( -1 )\r
78     #define portTICK_PERIOD_MS    ( ( TickType_t ) 1000 / configTICK_RATE_HZ )\r
79     #define portBYTE_ALIGNMENT    8\r
80     #define portDONT_DISCARD      __attribute__( ( used ) )\r
81     /* We have to use PICO_DIVIDER_DISABLE_INTERRUPTS as the source of truth rathern than our config,\r
82      * as our FreeRTOSConfig.h header cannot be included by ASM code - which is what this affects in the SDK */\r
83     #define portUSE_DIVIDER_SAVE_RESTORE !PICO_DIVIDER_DISABLE_INTERRUPTS\r
84     #if portUSE_DIVIDER_SAVE_RESTORE\r
85         #define portSTACK_LIMIT_PADDING 4\r
86     #endif\r
87 \r
88 /*-----------------------------------------------------------*/\r
89 \r
90 \r
91 /* Scheduler utilities. */\r
92     extern void vPortYield( void );\r
93     #define portNVIC_INT_CTRL_REG     ( *( ( volatile uint32_t * ) 0xe000ed04 ) )\r
94     #define portNVIC_PENDSVSET_BIT    ( 1UL << 28UL )\r
95     #define portYIELD()                                 vPortYield()\r
96     #define portEND_SWITCHING_ISR( xSwitchRequired )    if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT\r
97     #define portYIELD_FROM_ISR( x )                     portEND_SWITCHING_ISR( x )\r
98 \r
99 /*-----------------------------------------------------------*/\r
100 \r
101 /* Exception handlers */\r
102     #if (configUSE_DYNAMIC_EXCEPTION_HANDLERS == 0)\r
103         /* We only need to override the SDK's weak functions if we want to replace them at compile time */\r
104         #define vPortSVCHandler isr_svcall\r
105         #define xPortPendSVHandler isr_pendsv\r
106         #define xPortSysTickHandler isr_systick\r
107     #endif\r
108 \r
109 /*-----------------------------------------------------------*/\r
110 \r
111 /* Multi-core */\r
112     #define portSUPPORT_SMP 1 /* this is an SMP build which means configNUM_CORES is relevant */\r
113     #define portMAX_CORE_COUNT            2\r
114     #ifndef configNUM_CORES\r
115     #define configNUM_CORES               2\r
116     #endif\r
117 \r
118     /* Requires for SMP */\r
119     #define portCRITICAL_NESTING_IN_TCB   1\r
120 \r
121     /*-----------------------------------------------------------*/\r
122 \r
123 \r
124     /* Check validity of number of cores specified in config */\r
125     #if ( configNUM_CORES < 1 || portMAX_CORE_COUNT < configNUM_CORES )\r
126     #error "Invalid number of cores specified in config!"\r
127     #endif\r
128 \r
129     #if ( configTICK_CORE < 0 || configTICK_CORE > configNUM_CORES )\r
130     #error "Invalid tick core specified in config!"\r
131     #endif\r
132 \r
133     /* FreeRTOS core id is always zero based, so always 0 if we're running on only one core */\r
134     #if configNUM_CORES == portMAX_CORE_COUNT\r
135     #define portGET_CORE_ID() get_core_num()\r
136     #else\r
137     #define portGET_CORE_ID() 0\r
138     #endif\r
139 \r
140     #define portCHECK_IF_IN_ISR() ({ \\r
141         uint32_t ulIPSR;                                                  \\r
142        __asm volatile ("mrs %0, IPSR" : "=r" (ulIPSR)::);             \\r
143        ((uint8_t)ulIPSR)>0;})\r
144 \r
145     void vYieldCore(int xCoreID);\r
146     #define portYIELD_CORE(a) vYieldCore(a)\r
147     #define portRESTORE_INTERRUPTS(ulState) __asm volatile ("msr PRIMASK,%0"::"r" (ulState) : )\r
148 \r
149 /*-----------------------------------------------------------*/\r
150 \r
151 /* Critical section management. */\r
152 \r
153     #define portSET_INTERRUPT_MASK_FROM_ISR()         ({ uint32_t ulStateISR = portDISABLE_INTERRUPTS(); vTaskEnterCritical(); ulStateISR; })\r
154     #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    do { vTaskExitCritical(); portRESTORE_INTERRUPTS( x ); } while (0)\r
155 \r
156     #define portDISABLE_INTERRUPTS()                  ({                  \\r
157        uint32_t ulState;                                                  \\r
158        __asm volatile ("mrs %0, PRIMASK" : "=r" (ulState)::);             \\r
159        __asm volatile ( " cpsid i " ::: "memory" );                       \\r
160        ulState;})\r
161 \r
162     extern void vPortEnableInterrupts();\r
163     #define portENABLE_INTERRUPTS()                   vPortEnableInterrupts()\r
164 \r
165     void vTaskEnterCritical(void);\r
166     void vTaskExitCritical(void);\r
167     #define portENTER_CRITICAL()                   vTaskEnterCritical()\r
168     #define portEXIT_CRITICAL()                    vTaskExitCritical()\r
169 \r
170     #define portRTOS_SPINLOCK_COUNT 2\r
171 \r
172     /* Note this is a single method with uxAcquire parameter since we have\r
173      * static vars, the method is always called with a compile time constant for\r
174      * uxAcquire, and the compiler should dothe right thing! */\r
175     static inline void vPortRecursiveLock(uint32_t ulLockNum, spin_lock_t *pxSpinLock, BaseType_t uxAcquire) {\r
176         static uint8_t ucOwnedByCore[ portMAX_CORE_COUNT ];\r
177         static uint8_t ucRecursionCountByLock[ portRTOS_SPINLOCK_COUNT ];\r
178         configASSERT(ulLockNum >= 0 && ulLockNum < portRTOS_SPINLOCK_COUNT );\r
179         uint32_t ulCoreNum = get_core_num();\r
180         uint32_t ulLockBit = 1u << ulLockNum;\r
181         configASSERT(ulLockBit < 256u );\r
182         if( uxAcquire )\r
183         {\r
184             if( __builtin_expect( !*pxSpinLock, 0 ) )\r
185             {\r
186                 if( ucOwnedByCore[ulCoreNum] & ulLockBit )\r
187                 {\r
188                     configASSERT(ucRecursionCountByLock[ulLockNum] != 255u );\r
189                     ucRecursionCountByLock[ulLockNum]++;\r
190                     return;\r
191                 }\r
192                 while ( __builtin_expect( !*pxSpinLock, 0 ) );\r
193             }\r
194             __mem_fence_acquire();\r
195             configASSERT(ucRecursionCountByLock[ulLockNum] == 0 );\r
196             ucRecursionCountByLock[ulLockNum] = 1;\r
197             ucOwnedByCore[ulCoreNum] |= ulLockBit;\r
198         } else {\r
199             configASSERT((ucOwnedByCore[ulCoreNum] & ulLockBit) != 0 );\r
200             configASSERT(ucRecursionCountByLock[ulLockNum] != 0 );\r
201             if( !--ucRecursionCountByLock[ulLockNum] )\r
202             {\r
203                 ucOwnedByCore[ulCoreNum] &= ~ulLockBit;\r
204                 __mem_fence_release();\r
205                 *pxSpinLock = 1;\r
206             }\r
207         }\r
208     }\r
209 \r
210     #define portGET_ISR_LOCK()      vPortRecursiveLock(0, spin_lock_instance(configSMP_SPINLOCK_0), pdTRUE)\r
211     #define portRELEASE_ISR_LOCK()  vPortRecursiveLock(0, spin_lock_instance(configSMP_SPINLOCK_0), pdFALSE)\r
212     #define portGET_TASK_LOCK()     vPortRecursiveLock(1, spin_lock_instance(configSMP_SPINLOCK_1), pdTRUE)\r
213     #define portRELEASE_TASK_LOCK() vPortRecursiveLock(1, spin_lock_instance(configSMP_SPINLOCK_1), pdFALSE)\r
214 \r
215 /*-----------------------------------------------------------*/\r
216 \r
217 /* Tickless idle/low power functionality. */\r
218     #ifndef portSUPPRESS_TICKS_AND_SLEEP\r
219         extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );\r
220         #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime )    vPortSuppressTicksAndSleep( xExpectedIdleTime )\r
221     #endif\r
222 /*-----------------------------------------------------------*/\r
223 \r
224 /* Task function macros as described on the FreeRTOS.org WEB site. */\r
225     #define portTASK_FUNCTION_PROTO( vFunction, pvParameters )    void vFunction( void * pvParameters )\r
226     #define portTASK_FUNCTION( vFunction, pvParameters )          void vFunction( void * pvParameters )\r
227 \r
228     #define portNOP()\r
229 \r
230     #define portMEMORY_BARRIER()    __asm volatile ( "" ::: "memory" )\r
231 \r
232     #ifdef __cplusplus\r
233         }\r
234     #endif\r
235 \r
236 #endif /* PORTMACRO_H */\r