Skip to content

Commit 3b54cd7

Browse files
author
Daniel Campora
committed
components: Add missing portmux_impl.inc.h.
1 parent 0c90893 commit 3b54cd7

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
Copyright (C) 2016-2017 Espressif Shanghai PTE LTD
3+
Copyright (C) 2015 Real Time Engineers Ltd.
4+
5+
All rights reserved
6+
7+
FreeRTOS is free software; you can redistribute it and/or modify it under
8+
the terms of the GNU General Public License (version 2) as published by the
9+
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
10+
11+
***************************************************************************
12+
>>! NOTE: The modification to the GPL is included to allow you to !<<
13+
>>! distribute a combined work that includes FreeRTOS without being !<<
14+
>>! obliged to provide the source code for proprietary components !<<
15+
>>! outside of the FreeRTOS kernel. !<<
16+
***************************************************************************
17+
18+
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
19+
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20+
FOR A PARTICULAR PURPOSE. Full license text is available on the following
21+
link: http://www.freertos.org/a00114.html
22+
*/
23+
24+
25+
/*
26+
Warning: funky preprocessor hackery ahead. Including these headers will generate two
27+
functions, which names are defined by the preprocessor macros
28+
PORTMUX_AQUIRE_MUX_FN_NAME and PORTMUX_RELEASE_MUX_FN_NAME. In order to do the compare
29+
and exchange function, they will use whatever PORTMUX_COMPARE_SET_FN_NAME resolves to.
30+
31+
In some scenarios, this header is included *twice* in portmux_impl.h: one time
32+
for the 'normal' mux code which uses a compare&exchange routine, another time
33+
to generate code for a second set of these routines that use a second mux
34+
(in internal ram) to fake a compare&exchange on a variable in external memory.
35+
*/
36+
37+
38+
39+
static inline bool __attribute__((always_inline))
40+
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
41+
PORTMUX_AQUIRE_MUX_FN_NAME(portMUX_TYPE *mux, int timeout_cycles, const char *fnName, int line) {
42+
#else
43+
PORTMUX_AQUIRE_MUX_FN_NAME(portMUX_TYPE *mux, int timeout_cycles) {
44+
#endif
45+
46+
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+
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+
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+
PORTMUX_COMPARE_SET_FN_NAME(&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+
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 */
108+
109+
/* now we own it, we can increment the refcount */
110+
mux->count++;
111+
112+
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+
}
125+
126+
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
127+
static inline void PORTMUX_RELEASE_MUX_FN_NAME(portMUX_TYPE *mux, const char *fnName, int line) {
128+
#else
129+
static inline void PORTMUX_RELEASE_MUX_FN_NAME(portMUX_TYPE *mux) {
130+
#endif
131+
132+
133+
#if !CONFIG_FREERTOS_UNICORE
134+
portBASE_TYPE coreID;
135+
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
136+
const char *lastLockedFn=mux->lastLockedFn;
137+
int lastLockedLine=mux->lastLockedLine;
138+
mux->lastLockedFn=fnName;
139+
mux->lastLockedLine=line;
140+
uint32_t owner = mux->owner;
141+
if (owner != portMUX_FREE_VAL && owner != CORE_ID_PRO && owner != CORE_ID_APP) {
142+
ets_printf("ERROR: vPortCPUReleaseMutex: mux %p is invalid (0x%x)!\n", mux, mux->owner);
143+
}
144+
#endif
145+
146+
#if CONFIG_FREERTOS_PORTMUX_DEBUG || !defined(NDEBUG)
147+
RSR(PRID, coreID);
148+
#endif
149+
150+
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
151+
if (coreID != mux->owner) {
152+
ets_printf("ERROR: vPortCPUReleaseMutex: mux %p was already unlocked!\n", mux);
153+
ets_printf("Last non-recursive unlock %s line %d, curr unlock %s line %d\n", lastLockedFn, lastLockedLine, fnName, line);
154+
}
155+
#endif
156+
157+
assert(coreID == mux->owner); // This is a mutex we didn't lock, or it's corrupt
158+
assert(mux->count > 0); // Indicates memory corruption
159+
assert(mux->count < 0x100); // Indicates memory corruption
160+
161+
mux->count--;
162+
if(mux->count == 0) {
163+
mux->owner = portMUX_FREE_VAL;
164+
}
165+
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG_RECURSIVE
166+
else {
167+
ets_printf("Recursive unlock: count=%d last locked %s line %d, curr %s line %d\n", mux->count, lastLockedFn, lastLockedLine, fnName, line);
168+
}
169+
#endif
170+
#endif //!CONFIG_FREERTOS_UNICORE
171+
}

0 commit comments

Comments
 (0)