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