|
32 | 32 | deal by FreeRTOS internals. |
33 | 33 |
|
34 | 34 | It should be #included by freertos port.c or tasks.c, in esp-idf. |
| 35 | +
|
| 36 | + The way it works is that it essentially uses portmux_impl.inc.h as a |
| 37 | + generator template of sorts. When no external memory is used, this |
| 38 | + template is only used to generate the vPortCPUAcquireMutexIntsDisabledInternal |
| 39 | + and vPortCPUReleaseMutexIntsDisabledInternal functions, which use S32C1 to |
| 40 | + do an atomic compare & swap. When external memory is used the functions |
| 41 | + vPortCPUAcquireMutexIntsDisabledExtram and vPortCPUReleaseMutexIntsDisabledExtram |
| 42 | + are also generated, which use uxPortCompareSetExtram to fake the S32C1 instruction. |
| 43 | + The wrapper functions vPortCPUAcquireMutexIntsDisabled and |
| 44 | + vPortCPUReleaseMutexIntsDisabled will then use the appropriate function to do the |
| 45 | + actual lock/unlock. |
35 | 46 | */ |
36 | 47 | #include "soc/cpu.h" |
| 48 | +#include "portable.h" |
37 | 49 |
|
38 | 50 | /* XOR one core ID with this value to get the other core ID */ |
39 | 51 | #define CORE_ID_XOR_SWAP (CORE_ID_PRO ^ CORE_ID_APP) |
40 | 52 |
|
41 | | -static inline bool __attribute__((always_inline)) |
42 | | -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG |
43 | | -vPortCPUAcquireMutexIntsDisabled(portMUX_TYPE *mux, int timeout_cycles, const char *fnName, int line) { |
44 | | -#else |
45 | | -vPortCPUAcquireMutexIntsDisabled(portMUX_TYPE *mux, int timeout_cycles) { |
46 | | -#endif |
47 | | -#if !CONFIG_FREERTOS_UNICORE |
48 | | - uint32_t res; |
49 | | - portBASE_TYPE coreID, otherCoreID; |
50 | | - uint32_t ccount_start; |
51 | | - bool set_timeout = timeout_cycles > portMUX_NO_TIMEOUT; |
52 | | -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG |
53 | | - if (!set_timeout) { |
54 | | - timeout_cycles = 10000; // Always set a timeout in debug mode |
55 | | - set_timeout = true; |
56 | | - } |
57 | | -#endif |
58 | | - if (set_timeout) { // Timeout |
59 | | - RSR(CCOUNT, ccount_start); |
60 | | - } |
61 | 53 |
|
62 | | -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG |
63 | | - uint32_t owner = mux->owner; |
64 | | - if (owner != portMUX_FREE_VAL && owner != CORE_ID_PRO && owner != CORE_ID_APP) { |
65 | | - ets_printf("ERROR: vPortCPUAcquireMutex: mux %p is uninitialized (0x%X)! Called from %s line %d.\n", mux, owner, fnName, line); |
66 | | - mux->owner=portMUX_FREE_VAL; |
67 | | - } |
68 | | -#endif |
69 | 54 |
|
70 | | - /* Spin until we own the core */ |
71 | | - |
72 | | - RSR(PRID, coreID); |
73 | | - /* Note: coreID is the full 32 bit core ID (CORE_ID_PRO/CORE_ID_APP), |
74 | | - not the 0/1 value returned by xPortGetCoreID() |
75 | | - */ |
76 | | - otherCoreID = CORE_ID_XOR_SWAP ^ coreID; |
77 | | - do { |
78 | | - /* mux->owner should be one of portMUX_FREE_VAL, CORE_ID_PRO, |
79 | | - CORE_ID_APP: |
80 | | -
|
81 | | - - If portMUX_FREE_VAL, we want to atomically set to 'coreID'. |
82 | | - - If "our" coreID, we can drop through immediately. |
83 | | - - If "otherCoreID", we spin here. |
84 | | - */ |
85 | | - res = coreID; |
86 | | - uxPortCompareSet(&mux->owner, portMUX_FREE_VAL, &res); |
87 | | - |
88 | | - if (res != otherCoreID) { |
89 | | - break; // mux->owner is "our" coreID |
90 | | - } |
91 | | - |
92 | | - if (set_timeout) { |
93 | | - uint32_t ccount_now; |
94 | | - RSR(CCOUNT, ccount_now); |
95 | | - if (ccount_now - ccount_start > (unsigned)timeout_cycles) { |
96 | | -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG |
97 | | - ets_printf("Timeout on mux! last non-recursive lock %s line %d, curr %s line %d\n", mux->lastLockedFn, mux->lastLockedLine, fnName, line); |
98 | | - ets_printf("Owner 0x%x count %d\n", mux->owner, mux->count); |
99 | | -#endif |
100 | | - return false; |
101 | | - } |
102 | | - } |
103 | | - } while (1); |
104 | 55 |
|
105 | | - assert(res == coreID || res == portMUX_FREE_VAL); /* any other value implies memory corruption or uninitialized mux */ |
106 | | - assert((res == portMUX_FREE_VAL) == (mux->count == 0)); /* we're first to lock iff count is zero */ |
107 | | - assert(mux->count < 0xFF); /* Bad count value implies memory corruption */ |
| 56 | +//Define the mux routines for use with muxes in internal RAM |
| 57 | +#define PORTMUX_AQUIRE_MUX_FN_NAME vPortCPUAcquireMutexIntsDisabledInternal |
| 58 | +#define PORTMUX_RELEASE_MUX_FN_NAME vPortCPUReleaseMutexIntsDisabledInternal |
| 59 | +#define PORTMUX_COMPARE_SET_FN_NAME uxPortCompareSet |
| 60 | +#include "portmux_impl.inc.h" |
| 61 | +#undef PORTMUX_AQUIRE_MUX_FN_NAME |
| 62 | +#undef PORTMUX_RELEASE_MUX_FN_NAME |
| 63 | +#undef PORTMUX_COMPARE_SET_FN_NAME |
108 | 64 |
|
109 | | - /* now we own it, we can increment the refcount */ |
110 | | - mux->count++; |
111 | 65 |
|
| 66 | +#if defined(CONFIG_SPIRAM_SUPPORT) |
112 | 67 |
|
113 | | -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG |
114 | | - if (res==portMUX_FREE_VAL) { //initial lock |
115 | | - mux->lastLockedFn=fnName; |
116 | | - mux->lastLockedLine=line; |
117 | | - } else { |
118 | | - ets_printf("Recursive lock: count=%d last non-recursive lock %s line %d, curr %s line %d\n", mux->count-1, |
119 | | - mux->lastLockedFn, mux->lastLockedLine, fnName, line); |
120 | | - } |
121 | | -#endif /* CONFIG_FREERTOS_PORTMUX_DEBUG */ |
122 | | -#endif /* CONFIG_FREERTOS_UNICORE */ |
123 | | - return true; |
124 | | -} |
| 68 | +#define PORTMUX_AQUIRE_MUX_FN_NAME vPortCPUAcquireMutexIntsDisabledExtram |
| 69 | +#define PORTMUX_RELEASE_MUX_FN_NAME vPortCPUReleaseMutexIntsDisabledExtram |
| 70 | +#define PORTMUX_COMPARE_SET_FN_NAME uxPortCompareSetExtram |
| 71 | +#include "portmux_impl.inc.h" |
| 72 | +#undef PORTMUX_AQUIRE_MUX_FN_NAME |
| 73 | +#undef PORTMUX_RELEASE_MUX_FN_NAME |
| 74 | +#undef PORTMUX_COMPARE_SET_FN_NAME |
125 | 75 |
|
126 | | -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG |
127 | | - static inline void vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux, const char *fnName, int line) { |
128 | | -#else |
129 | | -static inline void vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux) { |
130 | 76 | #endif |
131 | | -#if !CONFIG_FREERTOS_UNICORE |
132 | | - portBASE_TYPE coreID; |
| 77 | + |
| 78 | + |
133 | 79 | #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG |
134 | | - const char *lastLockedFn=mux->lastLockedFn; |
135 | | - int lastLockedLine=mux->lastLockedLine; |
136 | | - mux->lastLockedFn=fnName; |
137 | | - mux->lastLockedLine=line; |
138 | | - uint32_t owner = mux->owner; |
139 | | - if (owner != portMUX_FREE_VAL && owner != CORE_ID_PRO && owner != CORE_ID_APP) { |
140 | | - ets_printf("ERROR: vPortCPUReleaseMutex: mux %p is invalid (0x%x)!\n", mux, mux->owner); |
141 | | - } |
| 80 | +#define PORTMUX_AQUIRE_MUX_FN_ARGS portMUX_TYPE *mux, int timeout_cycles, const char *fnName, int line |
| 81 | +#define PORTMUX_RELEASE_MUX_FN_ARGS portMUX_TYPE *mux, const char *fnName, int line |
| 82 | +#define PORTMUX_AQUIRE_MUX_FN_CALL_ARGS(x) x, timeout_cycles, fnName, line |
| 83 | +#define PORTMUX_RELEASE_MUX_FN_CALL_ARGS(x) x, fnName, line |
| 84 | +#else |
| 85 | +#define PORTMUX_AQUIRE_MUX_FN_ARGS portMUX_TYPE *mux, int timeout_cycles |
| 86 | +#define PORTMUX_RELEASE_MUX_FN_ARGS portMUX_TYPE *mux |
| 87 | +#define PORTMUX_AQUIRE_MUX_FN_CALL_ARGS(x) x, timeout_cycles |
| 88 | +#define PORTMUX_RELEASE_MUX_FN_CALL_ARGS(x) x |
142 | 89 | #endif |
143 | 90 |
|
144 | | -#if CONFIG_FREERTOS_PORTMUX_DEBUG || !defined(NDEBUG) |
145 | | - RSR(PRID, coreID); |
146 | | -#endif |
147 | 91 |
|
148 | | -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG |
149 | | - if (coreID != mux->owner) { |
150 | | - ets_printf("ERROR: vPortCPUReleaseMutex: mux %p was already unlocked!\n", mux); |
151 | | - ets_printf("Last non-recursive unlock %s line %d, curr unlock %s line %d\n", lastLockedFn, lastLockedLine, fnName, line); |
| 92 | +static inline bool __attribute__((always_inline)) vPortCPUAcquireMutexIntsDisabled(PORTMUX_AQUIRE_MUX_FN_ARGS) { |
| 93 | +#if defined(CONFIG_SPIRAM_SUPPORT) |
| 94 | + if (esp_ptr_external_ram(mux)) { |
| 95 | + return vPortCPUAcquireMutexIntsDisabledExtram(PORTMUX_AQUIRE_MUX_FN_CALL_ARGS(mux)); |
152 | 96 | } |
153 | 97 | #endif |
| 98 | + return vPortCPUAcquireMutexIntsDisabledInternal(PORTMUX_AQUIRE_MUX_FN_CALL_ARGS(mux)); |
| 99 | +} |
154 | 100 |
|
155 | | - assert(coreID == mux->owner); // This is a mutex we didn't lock, or it's corrupt |
156 | | - assert(mux->count > 0); // Indicates memory corruption |
157 | | - assert(mux->count < 0x100); // Indicates memory corruption |
158 | 101 |
|
159 | | - mux->count--; |
160 | | - if(mux->count == 0) { |
161 | | - mux->owner = portMUX_FREE_VAL; |
162 | | - } |
163 | | -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG_RECURSIVE |
164 | | - else { |
165 | | - ets_printf("Recursive unlock: count=%d last locked %s line %d, curr %s line %d\n", mux->count, lastLockedFn, lastLockedLine, fnName, line); |
| 102 | +static inline void vPortCPUReleaseMutexIntsDisabled(PORTMUX_RELEASE_MUX_FN_ARGS) { |
| 103 | +#if defined(CONFIG_SPIRAM_SUPPORT) |
| 104 | + if (esp_ptr_external_ram(mux)) { |
| 105 | + vPortCPUReleaseMutexIntsDisabledExtram(PORTMUX_RELEASE_MUX_FN_CALL_ARGS(mux)); |
| 106 | + return; |
166 | 107 | } |
167 | 108 | #endif |
168 | | -#endif //!CONFIG_FREERTOS_UNICORE |
| 109 | + vPortCPUReleaseMutexIntsDisabledInternal(PORTMUX_RELEASE_MUX_FN_CALL_ARGS(mux)); |
169 | 110 | } |
| 111 | + |
0 commit comments