|
38 | 38 | #endif
|
39 | 39 |
|
40 | 40 | #include "pico.h"
|
| 41 | + #include "hardware/sync.h" |
| 42 | + |
41 | 43 | /*-----------------------------------------------------------
|
42 | 44 | * Port specific definitions.
|
43 | 45 | *
|
|
83 | 85 | * as our FreeRTOSConfig.h header cannot be included by ASM code - which is what this affects in the SDK */
|
84 | 86 | #define portUSE_DIVIDER_SAVE_RESTORE !PICO_DIVIDER_DISABLE_INTERRUPTS
|
85 | 87 | #if portUSE_DIVIDER_SAVE_RESTORE
|
86 |
| - #define portSTACK_LIMIT_PADDING 4 |
| 88 | + #define portSTACK_LIMIT_PADDING 4 |
87 | 89 | #endif
|
88 | 90 |
|
89 | 91 | /*-----------------------------------------------------------*/
|
|
107 | 109 | #define xPortSysTickHandler isr_systick
|
108 | 110 | #endif
|
109 | 111 |
|
| 112 | +/*-----------------------------------------------------------*/ |
| 113 | + |
| 114 | +/* Multi-core */ |
| 115 | + #define portSUPPORT_SMP 1 /* this is an SMP build which means configNUM_CORES is relevant */ |
| 116 | + #define portMAX_CORE_COUNT 2 |
| 117 | + #ifndef configNUM_CORES |
| 118 | + #define configNUM_CORES 2 |
| 119 | + #endif |
| 120 | + |
| 121 | + /* Requires for SMP */ |
| 122 | + #define portCRITICAL_NESTING_IN_TCB 1 |
| 123 | + |
| 124 | + /*-----------------------------------------------------------*/ |
| 125 | + |
| 126 | + |
| 127 | + /* Check validity of number of cores specified in config */ |
| 128 | + #if ( configNUM_CORES < 1 || portMAX_CORE_COUNT < configNUM_CORES ) |
| 129 | + #error "Invalid number of cores specified in config!" |
| 130 | + #endif |
| 131 | + |
| 132 | + #if ( configTICK_CORE < 0 || configTICK_CORE > configNUM_CORES ) |
| 133 | + #error "Invalid tick core specified in config!" |
| 134 | + #endif |
| 135 | + |
| 136 | + /* FreeRTOS core id is always zero based, so always 0 if we're running on only one core */ |
| 137 | + #if configNUM_CORES == portMAX_CORE_COUNT |
| 138 | + #define portGET_CORE_ID() get_core_num() |
| 139 | + #else |
| 140 | + #define portGET_CORE_ID() 0 |
| 141 | + #endif |
| 142 | + |
110 | 143 | #define portCHECK_IF_IN_ISR() ({ \
|
111 | 144 | uint32_t ulIPSR; \
|
112 | 145 | __asm volatile ("mrs %0, IPSR" : "=r" (ulIPSR)::); \
|
113 | 146 | ((uint8_t)ulIPSR)>0;})
|
114 | 147 |
|
| 148 | + void vYieldCore(int xCoreID); |
| 149 | + #define portYIELD_CORE(a) vYieldCore(a) |
| 150 | + #define portRESTORE_INTERRUPTS(ulState) __asm volatile ("msr PRIMASK,%0"::"r" (ulState) : ) |
| 151 | + |
115 | 152 | /*-----------------------------------------------------------*/
|
116 | 153 |
|
117 | 154 | /* Critical section management. */
|
118 |
| - extern uint32_t ulSetInterruptMaskFromISR( void ) __attribute__( ( naked ) ); |
119 |
| - extern void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__( ( naked ) ); |
120 |
| - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR() |
121 |
| - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMaskFromISR( x ) |
122 | 155 |
|
123 |
| - #define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) |
| 156 | + #define portSET_INTERRUPT_MASK_FROM_ISR() ({ uint32_t ulStateISR = portDISABLE_INTERRUPTS(); vTaskEnterCritical(); ulStateISR; }) |
| 157 | + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) do { vTaskExitCritical(); portRESTORE_INTERRUPTS( x ); } while (0) |
| 158 | + |
| 159 | + #define portDISABLE_INTERRUPTS() ({ \ |
| 160 | + uint32_t ulState; \ |
| 161 | + __asm volatile ("mrs %0, PRIMASK" : "=r" (ulState)::); \ |
| 162 | + __asm volatile ( " cpsid i " ::: "memory" ); \ |
| 163 | + ulState;}) |
124 | 164 |
|
125 | 165 | extern void vPortEnableInterrupts();
|
126 | 166 | #define portENABLE_INTERRUPTS() vPortEnableInterrupts()
|
127 | 167 |
|
128 |
| - extern void vPortEnterCritical( void ); |
129 |
| - extern void vPortExitCritical( void ); |
130 |
| - #define portENTER_CRITICAL() vPortEnterCritical() |
131 |
| - #define portEXIT_CRITICAL() vPortExitCritical() |
| 168 | + void vTaskEnterCritical(void); |
| 169 | + void vTaskExitCritical(void); |
| 170 | + #define portENTER_CRITICAL() vTaskEnterCritical() |
| 171 | + #define portEXIT_CRITICAL() vTaskExitCritical() |
| 172 | + |
| 173 | + #define portSIO_SPINLOCK_ISR portSIO_SPINLOCK0 |
| 174 | + #define portSIO_SPINLOCK_TASK portSIO_SPINLOCK1 |
| 175 | + #define portRTOS_SPINLOCK_COUNT 2 |
| 176 | + |
| 177 | + /* Note this is a single method with uxAcquire parameter since we have |
| 178 | + * static vars, the method is always called with a compile time constant for |
| 179 | + * uxAcquire, and the compiler should dothe right thing! */ |
| 180 | + static inline void vPortRecursiveLock(uint32_t ulLockNum, spin_lock_t *pxSpinLock, BaseType_t uxAcquire) { |
| 181 | + static uint8_t ucOwnedByCore[ portMAX_CORE_COUNT ]; |
| 182 | + static uint8_t ucRecursionCountByLock[ portRTOS_SPINLOCK_COUNT ]; |
| 183 | + configASSERT(ulLockNum >= 0 && ulLockNum < portRTOS_SPINLOCK_COUNT ); |
| 184 | + uint32_t ulCoreNum = get_core_num(); |
| 185 | + uint32_t ulLockBit = 1u << ulLockNum; |
| 186 | + configASSERT(ulLockBit < 256u ); |
| 187 | + if( uxAcquire ) |
| 188 | + { |
| 189 | + if( __builtin_expect( !*pxSpinLock, 0 ) ) |
| 190 | + { |
| 191 | + if( ucOwnedByCore[ulCoreNum] & ulLockBit ) |
| 192 | + { |
| 193 | + configASSERT(ucRecursionCountByLock[ulLockNum] != 255u ); |
| 194 | + ucRecursionCountByLock[ulLockNum]++; |
| 195 | + return; |
| 196 | + } |
| 197 | + while ( __builtin_expect( !*pxSpinLock, 0 ) ); |
| 198 | + } |
| 199 | + __mem_fence_acquire(); |
| 200 | + configASSERT(ucRecursionCountByLock[ulLockNum] == 0 ); |
| 201 | + ucRecursionCountByLock[ulLockNum] = 1; |
| 202 | + ucOwnedByCore[ulCoreNum] |= ulLockBit; |
| 203 | + } else { |
| 204 | + configASSERT((ucOwnedByCore[ulCoreNum] & ulLockBit) != 0 ); |
| 205 | + configASSERT(ucRecursionCountByLock[ulLockNum] != 0 ); |
| 206 | + if( !--ucRecursionCountByLock[ulLockNum] ) |
| 207 | + { |
| 208 | + ucOwnedByCore[ulCoreNum] &= ~ulLockBit; |
| 209 | + __mem_fence_release(); |
| 210 | + *pxSpinLock = 1; |
| 211 | + } |
| 212 | + } |
| 213 | + } |
| 214 | + |
| 215 | + #define portGET_ISR_LOCK() vPortRecursiveLock(0, spin_lock_instance(configSMP_SPINLOCK_0), pdTRUE) |
| 216 | + #define portRELEASE_ISR_LOCK() vPortRecursiveLock(0, spin_lock_instance(configSMP_SPINLOCK_0), pdFALSE) |
| 217 | + #define portGET_TASK_LOCK() vPortRecursiveLock(1, spin_lock_instance(configSMP_SPINLOCK_1), pdTRUE) |
| 218 | + #define portRELEASE_TASK_LOCK() vPortRecursiveLock(1, spin_lock_instance(configSMP_SPINLOCK_1), pdFALSE) |
132 | 219 |
|
133 | 220 | /*-----------------------------------------------------------*/
|
134 | 221 |
|
|
0 commit comments