13 |
14 | #include "FreeRTOS.h"
15 | #include "task.h"
16 | #include "queue.h"
17 | #include "semphr.h"
18 | #include "portmacro.h"
19 |
20 | #endif // __arm__
21 | #endif // FreeRTOS_TEENSY4_h
--------------------------------------------------------------------------------
/src/StackMacros.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeRTOS Kernel V10.0.1
3 | * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | *
22 | * http://www.FreeRTOS.org
23 | * http://aws.amazon.com/freertos
24 | *
25 | * 1 tab == 4 spaces!
26 | */
27 |
28 | #ifndef STACK_MACROS_H
29 | #define STACK_MACROS_H
30 |
31 | #ifndef _MSC_VER /* Visual Studio doesn't support #warning. */
32 | #warning The name of this file has changed to stack_macros.h. Please update your code accordingly. This source file (which has the original name) will be removed in future released.
33 | #endif
34 |
35 | /*
36 | * Call the stack overflow hook function if the stack of the task being swapped
37 | * out is currently overflowed, or looks like it might have overflowed in the
38 | * past.
39 | *
40 | * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
41 | * the current stack state only - comparing the current top of stack value to
42 | * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
43 | * will also cause the last few stack bytes to be checked to ensure the value
44 | * to which the bytes were set when the task was created have not been
45 | * overwritten. Note this second test does not guarantee that an overflowed
46 | * stack will always be recognised.
47 | */
48 |
49 | /*-----------------------------------------------------------*/
50 |
51 | #if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) )
52 |
53 | /* Only the current stack state is to be checked. */
54 | #define taskCHECK_FOR_STACK_OVERFLOW() \
55 | { \
56 | /* Is the currently saved stack pointer within the stack limit? */ \
57 | if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \
58 | { \
59 | vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
60 | } \
61 | }
62 |
63 | #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
64 | /*-----------------------------------------------------------*/
65 |
66 | #if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) )
67 |
68 | /* Only the current stack state is to be checked. */
69 | #define taskCHECK_FOR_STACK_OVERFLOW() \
70 | { \
71 | \
72 | /* Is the currently saved stack pointer within the stack limit? */ \
73 | if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \
74 | { \
75 | vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
76 | } \
77 | }
78 |
79 | #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
80 | /*-----------------------------------------------------------*/
81 |
82 | #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
83 |
84 | #define taskCHECK_FOR_STACK_OVERFLOW() \
85 | { \
86 | const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
87 | const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \
88 | \
89 | if( ( pulStack[ 0 ] != ulCheckValue ) || \
90 | ( pulStack[ 1 ] != ulCheckValue ) || \
91 | ( pulStack[ 2 ] != ulCheckValue ) || \
92 | ( pulStack[ 3 ] != ulCheckValue ) ) \
93 | { \
94 | vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
95 | } \
96 | }
97 |
98 | #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
99 | /*-----------------------------------------------------------*/
100 |
101 | #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
102 |
103 | #define taskCHECK_FOR_STACK_OVERFLOW() \
104 | { \
105 | int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
106 | static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
107 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
108 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
109 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
110 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
111 | \
112 | \
113 | pcEndOfStack -= sizeof( ucExpectedStackBytes ); \
114 | \
115 | /* Has the extremity of the task stack ever been written over? */ \
116 | if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
117 | { \
118 | vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
119 | } \
120 | }
121 |
122 | #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
123 | /*-----------------------------------------------------------*/
124 |
125 | /* Remove stack overflow macro if not being used. */
126 | #ifndef taskCHECK_FOR_STACK_OVERFLOW
127 | #define taskCHECK_FOR_STACK_OVERFLOW()
128 | #endif
129 |
130 |
131 |
132 | #endif /* STACK_MACROS_H */
133 |
134 |
--------------------------------------------------------------------------------
/src/croutine.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeRTOS Kernel V10.0.1
3 | * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | *
22 | * http://www.FreeRTOS.org
23 | * http://aws.amazon.com/freertos
24 | *
25 | * 1 tab == 4 spaces!
26 | */
27 |
28 | #include "FreeRTOS.h"
29 | #include "task.h"
30 | #include "croutine.h"
31 |
32 | /* Remove the whole file is co-routines are not being used. */
33 | #if( configUSE_CO_ROUTINES != 0 )
34 |
35 | /*
36 | * Some kernel aware debuggers require data to be viewed to be global, rather
37 | * than file scope.
38 | */
39 | #ifdef portREMOVE_STATIC_QUALIFIER
40 | #define static
41 | #endif
42 |
43 |
44 | /* Lists for ready and blocked co-routines. --------------------*/
45 | static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */
46 | static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */
47 | static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
48 | static List_t * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */
49 | static List_t * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
50 | static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
51 |
52 | /* Other file private variables. --------------------------------*/
53 | CRCB_t * pxCurrentCoRoutine = NULL;
54 | static UBaseType_t uxTopCoRoutineReadyPriority = 0;
55 | static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
56 |
57 | /* The initial state of the co-routine when it is created. */
58 | #define corINITIAL_STATE ( 0 )
59 |
60 | /*
61 | * Place the co-routine represented by pxCRCB into the appropriate ready queue
62 | * for the priority. It is inserted at the end of the list.
63 | *
64 | * This macro accesses the co-routine ready lists and therefore must not be
65 | * used from within an ISR.
66 | */
67 | #define prvAddCoRoutineToReadyQueue( pxCRCB ) \
68 | { \
69 | if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \
70 | { \
71 | uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \
72 | } \
73 | vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \
74 | }
75 |
76 | /*
77 | * Utility to ready all the lists used by the scheduler. This is called
78 | * automatically upon the creation of the first co-routine.
79 | */
80 | static void prvInitialiseCoRoutineLists( void );
81 |
82 | /*
83 | * Co-routines that are readied by an interrupt cannot be placed directly into
84 | * the ready lists (there is no mutual exclusion). Instead they are placed in
85 | * in the pending ready list in order that they can later be moved to the ready
86 | * list by the co-routine scheduler.
87 | */
88 | static void prvCheckPendingReadyList( void );
89 |
90 | /*
91 | * Macro that looks at the list of co-routines that are currently delayed to
92 | * see if any require waking.
93 | *
94 | * Co-routines are stored in the queue in the order of their wake time -
95 | * meaning once one co-routine has been found whose timer has not expired
96 | * we need not look any further down the list.
97 | */
98 | static void prvCheckDelayedList( void );
99 |
100 | /*-----------------------------------------------------------*/
101 |
102 | BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex )
103 | {
104 | BaseType_t xReturn;
105 | CRCB_t *pxCoRoutine;
106 |
107 | /* Allocate the memory that will store the co-routine control block. */
108 | pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
109 | if( pxCoRoutine )
110 | {
111 | /* If pxCurrentCoRoutine is NULL then this is the first co-routine to
112 | be created and the co-routine data structures need initialising. */
113 | if( pxCurrentCoRoutine == NULL )
114 | {
115 | pxCurrentCoRoutine = pxCoRoutine;
116 | prvInitialiseCoRoutineLists();
117 | }
118 |
119 | /* Check the priority is within limits. */
120 | if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES )
121 | {
122 | uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1;
123 | }
124 |
125 | /* Fill out the co-routine control block from the function parameters. */
126 | pxCoRoutine->uxState = corINITIAL_STATE;
127 | pxCoRoutine->uxPriority = uxPriority;
128 | pxCoRoutine->uxIndex = uxIndex;
129 | pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode;
130 |
131 | /* Initialise all the other co-routine control block parameters. */
132 | vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
133 | vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
134 |
135 | /* Set the co-routine control block as a link back from the ListItem_t.
136 | This is so we can get back to the containing CRCB from a generic item
137 | in a list. */
138 | listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
139 | listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
140 |
141 | /* Event lists are always in priority order. */
142 | listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) );
143 |
144 | /* Now the co-routine has been initialised it can be added to the ready
145 | list at the correct priority. */
146 | prvAddCoRoutineToReadyQueue( pxCoRoutine );
147 |
148 | xReturn = pdPASS;
149 | }
150 | else
151 | {
152 | xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
153 | }
154 |
155 | return xReturn;
156 | }
157 | /*-----------------------------------------------------------*/
158 |
159 | void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList )
160 | {
161 | TickType_t xTimeToWake;
162 |
163 | /* Calculate the time to wake - this may overflow but this is
164 | not a problem. */
165 | xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
166 |
167 | /* We must remove ourselves from the ready list before adding
168 | ourselves to the blocked list as the same list item is used for
169 | both lists. */
170 | ( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
171 |
172 | /* The list item will be inserted in wake time order. */
173 | listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
174 |
175 | if( xTimeToWake < xCoRoutineTickCount )
176 | {
177 | /* Wake time has overflowed. Place this item in the
178 | overflow list. */
179 | vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
180 | }
181 | else
182 | {
183 | /* The wake time has not overflowed, so we can use the
184 | current block list. */
185 | vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
186 | }
187 |
188 | if( pxEventList )
189 | {
190 | /* Also add the co-routine to an event list. If this is done then the
191 | function must be called with interrupts disabled. */
192 | vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
193 | }
194 | }
195 | /*-----------------------------------------------------------*/
196 |
197 | static void prvCheckPendingReadyList( void )
198 | {
199 | /* Are there any co-routines waiting to get moved to the ready list? These
200 | are co-routines that have been readied by an ISR. The ISR cannot access
201 | the ready lists itself. */
202 | while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
203 | {
204 | CRCB_t *pxUnblockedCRCB;
205 |
206 | /* The pending ready list can be accessed by an ISR. */
207 | portDISABLE_INTERRUPTS();
208 | {
209 | pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) );
210 | ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
211 | }
212 | portENABLE_INTERRUPTS();
213 |
214 | ( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
215 | prvAddCoRoutineToReadyQueue( pxUnblockedCRCB );
216 | }
217 | }
218 | /*-----------------------------------------------------------*/
219 |
220 | static void prvCheckDelayedList( void )
221 | {
222 | CRCB_t *pxCRCB;
223 |
224 | xPassedTicks = xTaskGetTickCount() - xLastTickCount;
225 | while( xPassedTicks )
226 | {
227 | xCoRoutineTickCount++;
228 | xPassedTicks--;
229 |
230 | /* If the tick count has overflowed we need to swap the ready lists. */
231 | if( xCoRoutineTickCount == 0 )
232 | {
233 | List_t * pxTemp;
234 |
235 | /* Tick count has overflowed so we need to swap the delay lists. If there are
236 | any items in pxDelayedCoRoutineList here then there is an error! */
237 | pxTemp = pxDelayedCoRoutineList;
238 | pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
239 | pxOverflowDelayedCoRoutineList = pxTemp;
240 | }
241 |
242 | /* See if this tick has made a timeout expire. */
243 | while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE )
244 | {
245 | pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList );
246 |
247 | if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
248 | {
249 | /* Timeout not yet expired. */
250 | break;
251 | }
252 |
253 | portDISABLE_INTERRUPTS();
254 | {
255 | /* The event could have occurred just before this critical
256 | section. If this is the case then the generic list item will
257 | have been moved to the pending ready list and the following
258 | line is still valid. Also the pvContainer parameter will have
259 | been set to NULL so the following lines are also valid. */
260 | ( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
261 |
262 | /* Is the co-routine waiting on an event also? */
263 | if( pxCRCB->xEventListItem.pxContainer )
264 | {
265 | ( void ) uxListRemove( &( pxCRCB->xEventListItem ) );
266 | }
267 | }
268 | portENABLE_INTERRUPTS();
269 |
270 | prvAddCoRoutineToReadyQueue( pxCRCB );
271 | }
272 | }
273 |
274 | xLastTickCount = xCoRoutineTickCount;
275 | }
276 | /*-----------------------------------------------------------*/
277 |
278 | void vCoRoutineSchedule( void )
279 | {
280 | /* See if any co-routines readied by events need moving to the ready lists. */
281 | prvCheckPendingReadyList();
282 |
283 | /* See if any delayed co-routines have timed out. */
284 | prvCheckDelayedList();
285 |
286 | /* Find the highest priority queue that contains ready co-routines. */
287 | while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) )
288 | {
289 | if( uxTopCoRoutineReadyPriority == 0 )
290 | {
291 | /* No more co-routines to check. */
292 | return;
293 | }
294 | --uxTopCoRoutineReadyPriority;
295 | }
296 |
297 | /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines
298 | of the same priority get an equal share of the processor time. */
299 | listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
300 |
301 | /* Call the co-routine. */
302 | ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
303 |
304 | return;
305 | }
306 | /*-----------------------------------------------------------*/
307 |
308 | static void prvInitialiseCoRoutineLists( void )
309 | {
310 | UBaseType_t uxPriority;
311 |
312 | for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
313 | {
314 | vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) );
315 | }
316 |
317 | vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 );
318 | vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 );
319 | vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList );
320 |
321 | /* Start with pxDelayedCoRoutineList using list1 and the
322 | pxOverflowDelayedCoRoutineList using list2. */
323 | pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
324 | pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
325 | }
326 | /*-----------------------------------------------------------*/
327 |
328 | BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList )
329 | {
330 | CRCB_t *pxUnblockedCRCB;
331 | BaseType_t xReturn;
332 |
333 | /* This function is called from within an interrupt. It can only access
334 | event lists and the pending ready list. This function assumes that a
335 | check has already been made to ensure pxEventList is not empty. */
336 | pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
337 | ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
338 | vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
339 |
340 | if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority )
341 | {
342 | xReturn = pdTRUE;
343 | }
344 | else
345 | {
346 | xReturn = pdFALSE;
347 | }
348 |
349 | return xReturn;
350 | }
351 |
352 | #endif /* configUSE_CO_ROUTINES == 0 */
353 |
354 |
--------------------------------------------------------------------------------
/src/croutine.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeRTOS Kernel V10.0.1
3 | * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | *
22 | * http://www.FreeRTOS.org
23 | * http://aws.amazon.com/freertos
24 | *
25 | * 1 tab == 4 spaces!
26 | */
27 |
28 | #ifndef CO_ROUTINE_H
29 | #define CO_ROUTINE_H
30 |
31 | #ifndef INC_FREERTOS_H
32 | #error "include FreeRTOS.h must appear in source files before include croutine.h"
33 | #endif
34 |
35 | #include "list.h"
36 |
37 | #ifdef __cplusplus
38 | extern "C" {
39 | #endif
40 |
41 | /* Used to hide the implementation of the co-routine control block. The
42 | control block structure however has to be included in the header due to
43 | the macro implementation of the co-routine functionality. */
44 | typedef void * CoRoutineHandle_t;
45 |
46 | /* Defines the prototype to which co-routine functions must conform. */
47 | typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t );
48 |
49 | typedef struct corCoRoutineControlBlock
50 | {
51 | crCOROUTINE_CODE pxCoRoutineFunction;
52 | ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */
53 | ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */
54 | UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */
55 | UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */
56 | uint16_t uxState; /*< Used internally by the co-routine implementation. */
57 | } CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */
58 |
59 | /**
60 | * croutine. h
61 | *
62 | BaseType_t xCoRoutineCreate(
63 | crCOROUTINE_CODE pxCoRoutineCode,
64 | UBaseType_t uxPriority,
65 | UBaseType_t uxIndex
66 | );
67 | *
68 | * Create a new co-routine and add it to the list of co-routines that are
69 | * ready to run.
70 | *
71 | * @param pxCoRoutineCode Pointer to the co-routine function. Co-routine
72 | * functions require special syntax - see the co-routine section of the WEB
73 | * documentation for more information.
74 | *
75 | * @param uxPriority The priority with respect to other co-routines at which
76 | * the co-routine will run.
77 | *
78 | * @param uxIndex Used to distinguish between different co-routines that
79 | * execute the same function. See the example below and the co-routine section
80 | * of the WEB documentation for further information.
81 | *
82 | * @return pdPASS if the co-routine was successfully created and added to a ready
83 | * list, otherwise an error code defined with ProjDefs.h.
84 | *
85 | * Example usage:
86 |
87 | // Co-routine to be created.
88 | void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
89 | {
90 | // Variables in co-routines must be declared static if they must maintain value across a blocking call.
91 | // This may not be necessary for const variables.
92 | static const char cLedToFlash[ 2 ] = { 5, 6 };
93 | static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
94 |
95 | // Must start every co-routine with a call to crSTART();
96 | crSTART( xHandle );
97 |
98 | for( ;; )
99 | {
100 | // This co-routine just delays for a fixed period, then toggles
101 | // an LED. Two co-routines are created using this function, so
102 | // the uxIndex parameter is used to tell the co-routine which
103 | // LED to flash and how int32_t to delay. This assumes xQueue has
104 | // already been created.
105 | vParTestToggleLED( cLedToFlash[ uxIndex ] );
106 | crDELAY( xHandle, uxFlashRates[ uxIndex ] );
107 | }
108 |
109 | // Must end every co-routine with a call to crEND();
110 | crEND();
111 | }
112 |
113 | // Function that creates two co-routines.
114 | void vOtherFunction( void )
115 | {
116 | uint8_t ucParameterToPass;
117 | TaskHandle_t xHandle;
118 |
119 | // Create two co-routines at priority 0. The first is given index 0
120 | // so (from the code above) toggles LED 5 every 200 ticks. The second
121 | // is given index 1 so toggles LED 6 every 400 ticks.
122 | for( uxIndex = 0; uxIndex < 2; uxIndex++ )
123 | {
124 | xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
125 | }
126 | }
127 |
128 | * \defgroup xCoRoutineCreate xCoRoutineCreate
129 | * \ingroup Tasks
130 | */
131 | BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex );
132 |
133 |
134 | /**
135 | * croutine. h
136 | *
137 | void vCoRoutineSchedule( void );
138 | *
139 | * Run a co-routine.
140 | *
141 | * vCoRoutineSchedule() executes the highest priority co-routine that is able
142 | * to run. The co-routine will execute until it either blocks, yields or is
143 | * preempted by a task. Co-routines execute cooperatively so one
144 | * co-routine cannot be preempted by another, but can be preempted by a task.
145 | *
146 | * If an application comprises of both tasks and co-routines then
147 | * vCoRoutineSchedule should be called from the idle task (in an idle task
148 | * hook).
149 | *
150 | * Example usage:
151 |
152 | // This idle task hook will schedule a co-routine each time it is called.
153 | // The rest of the idle task will execute between co-routine calls.
154 | void vApplicationIdleHook( void )
155 | {
156 | vCoRoutineSchedule();
157 | }
158 |
159 | // Alternatively, if you do not require any other part of the idle task to
160 | // execute, the idle task hook can call vCoRoutineScheduler() within an
161 | // infinite loop.
162 | void vApplicationIdleHook( void )
163 | {
164 | for( ;; )
165 | {
166 | vCoRoutineSchedule();
167 | }
168 | }
169 |
170 | * \defgroup vCoRoutineSchedule vCoRoutineSchedule
171 | * \ingroup Tasks
172 | */
173 | void vCoRoutineSchedule( void );
174 |
175 | /**
176 | * croutine. h
177 | *
178 | crSTART( CoRoutineHandle_t xHandle );
179 | *
180 | * This macro MUST always be called at the start of a co-routine function.
181 | *
182 | * Example usage:
183 |
184 | // Co-routine to be created.
185 | void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
186 | {
187 | // Variables in co-routines must be declared static if they must maintain value across a blocking call.
188 | static int32_t ulAVariable;
189 |
190 | // Must start every co-routine with a call to crSTART();
191 | crSTART( xHandle );
192 |
193 | for( ;; )
194 | {
195 | // Co-routine functionality goes here.
196 | }
197 |
198 | // Must end every co-routine with a call to crEND();
199 | crEND();
200 | }
201 | * \defgroup crSTART crSTART
202 | * \ingroup Tasks
203 | */
204 | #define crSTART( pxCRCB ) switch( ( ( CRCB_t * )( pxCRCB ) )->uxState ) { case 0:
205 |
206 | /**
207 | * croutine. h
208 | *
209 | crEND();
210 | *
211 | * This macro MUST always be called at the end of a co-routine function.
212 | *
213 | * Example usage:
214 |
215 | // Co-routine to be created.
216 | void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
217 | {
218 | // Variables in co-routines must be declared static if they must maintain value across a blocking call.
219 | static int32_t ulAVariable;
220 |
221 | // Must start every co-routine with a call to crSTART();
222 | crSTART( xHandle );
223 |
224 | for( ;; )
225 | {
226 | // Co-routine functionality goes here.
227 | }
228 |
229 | // Must end every co-routine with a call to crEND();
230 | crEND();
231 | }
232 | * \defgroup crSTART crSTART
233 | * \ingroup Tasks
234 | */
235 | #define crEND() }
236 |
237 | /*
238 | * These macros are intended for internal use by the co-routine implementation
239 | * only. The macros should not be used directly by application writers.
240 | */
241 | #define crSET_STATE0( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2):
242 | #define crSET_STATE1( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1):
243 |
244 | /**
245 | * croutine. h
246 | *
247 | crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );
248 | *
249 | * Delay a co-routine for a fixed period of time.
250 | *
251 | * crDELAY can only be called from the co-routine function itself - not
252 | * from within a function called by the co-routine function. This is because
253 | * co-routines do not maintain their own stack.
254 | *
255 | * @param xHandle The handle of the co-routine to delay. This is the xHandle
256 | * parameter of the co-routine function.
257 | *
258 | * @param xTickToDelay The number of ticks that the co-routine should delay
259 | * for. The actual amount of time this equates to is defined by
260 | * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS
261 | * can be used to convert ticks to milliseconds.
262 | *
263 | * Example usage:
264 |
265 | // Co-routine to be created.
266 | void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
267 | {
268 | // Variables in co-routines must be declared static if they must maintain value across a blocking call.
269 | // This may not be necessary for const variables.
270 | // We are to delay for 200ms.
271 | static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
272 |
273 | // Must start every co-routine with a call to crSTART();
274 | crSTART( xHandle );
275 |
276 | for( ;; )
277 | {
278 | // Delay for 200ms.
279 | crDELAY( xHandle, xDelayTime );
280 |
281 | // Do something here.
282 | }
283 |
284 | // Must end every co-routine with a call to crEND();
285 | crEND();
286 | }
287 | * \defgroup crDELAY crDELAY
288 | * \ingroup Tasks
289 | */
290 | #define crDELAY( xHandle, xTicksToDelay ) \
291 | if( ( xTicksToDelay ) > 0 ) \
292 | { \
293 | vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \
294 | } \
295 | crSET_STATE0( ( xHandle ) );
296 |
297 | /**
298 | *
299 | crQUEUE_SEND(
300 | CoRoutineHandle_t xHandle,
301 | QueueHandle_t pxQueue,
302 | void *pvItemToQueue,
303 | TickType_t xTicksToWait,
304 | BaseType_t *pxResult
305 | )
306 | *
307 | * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
308 | * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
309 | *
310 | * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
311 | * xQueueSend() and xQueueReceive() can only be used from tasks.
312 | *
313 | * crQUEUE_SEND can only be called from the co-routine function itself - not
314 | * from within a function called by the co-routine function. This is because
315 | * co-routines do not maintain their own stack.
316 | *
317 | * See the co-routine section of the WEB documentation for information on
318 | * passing data between tasks and co-routines and between ISR's and
319 | * co-routines.
320 | *
321 | * @param xHandle The handle of the calling co-routine. This is the xHandle
322 | * parameter of the co-routine function.
323 | *
324 | * @param pxQueue The handle of the queue on which the data will be posted.
325 | * The handle is obtained as the return value when the queue is created using
326 | * the xQueueCreate() API function.
327 | *
328 | * @param pvItemToQueue A pointer to the data being posted onto the queue.
329 | * The number of bytes of each queued item is specified when the queue is
330 | * created. This number of bytes is copied from pvItemToQueue into the queue
331 | * itself.
332 | *
333 | * @param xTickToDelay The number of ticks that the co-routine should block
334 | * to wait for space to become available on the queue, should space not be
335 | * available immediately. The actual amount of time this equates to is defined
336 | * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
337 | * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example
338 | * below).
339 | *
340 | * @param pxResult The variable pointed to by pxResult will be set to pdPASS if
341 | * data was successfully posted onto the queue, otherwise it will be set to an
342 | * error defined within ProjDefs.h.
343 | *
344 | * Example usage:
345 |
346 | // Co-routine function that blocks for a fixed period then posts a number onto
347 | // a queue.
348 | static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
349 | {
350 | // Variables in co-routines must be declared static if they must maintain value across a blocking call.
351 | static BaseType_t xNumberToPost = 0;
352 | static BaseType_t xResult;
353 |
354 | // Co-routines must begin with a call to crSTART().
355 | crSTART( xHandle );
356 |
357 | for( ;; )
358 | {
359 | // This assumes the queue has already been created.
360 | crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
361 |
362 | if( xResult != pdPASS )
363 | {
364 | // The message was not posted!
365 | }
366 |
367 | // Increment the number to be posted onto the queue.
368 | xNumberToPost++;
369 |
370 | // Delay for 100 ticks.
371 | crDELAY( xHandle, 100 );
372 | }
373 |
374 | // Co-routines must end with a call to crEND().
375 | crEND();
376 | }
377 | * \defgroup crQUEUE_SEND crQUEUE_SEND
378 | * \ingroup Tasks
379 | */
380 | #define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \
381 | { \
382 | *( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) ); \
383 | if( *( pxResult ) == errQUEUE_BLOCKED ) \
384 | { \
385 | crSET_STATE0( ( xHandle ) ); \
386 | *pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \
387 | } \
388 | if( *pxResult == errQUEUE_YIELD ) \
389 | { \
390 | crSET_STATE1( ( xHandle ) ); \
391 | *pxResult = pdPASS; \
392 | } \
393 | }
394 |
395 | /**
396 | * croutine. h
397 | *
398 | crQUEUE_RECEIVE(
399 | CoRoutineHandle_t xHandle,
400 | QueueHandle_t pxQueue,
401 | void *pvBuffer,
402 | TickType_t xTicksToWait,
403 | BaseType_t *pxResult
404 | )
405 | *
406 | * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
407 | * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
408 | *
409 | * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
410 | * xQueueSend() and xQueueReceive() can only be used from tasks.
411 | *
412 | * crQUEUE_RECEIVE can only be called from the co-routine function itself - not
413 | * from within a function called by the co-routine function. This is because
414 | * co-routines do not maintain their own stack.
415 | *
416 | * See the co-routine section of the WEB documentation for information on
417 | * passing data between tasks and co-routines and between ISR's and
418 | * co-routines.
419 | *
420 | * @param xHandle The handle of the calling co-routine. This is the xHandle
421 | * parameter of the co-routine function.
422 | *
423 | * @param pxQueue The handle of the queue from which the data will be received.
424 | * The handle is obtained as the return value when the queue is created using
425 | * the xQueueCreate() API function.
426 | *
427 | * @param pvBuffer The buffer into which the received item is to be copied.
428 | * The number of bytes of each queued item is specified when the queue is
429 | * created. This number of bytes is copied into pvBuffer.
430 | *
431 | * @param xTickToDelay The number of ticks that the co-routine should block
432 | * to wait for data to become available from the queue, should data not be
433 | * available immediately. The actual amount of time this equates to is defined
434 | * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
435 | * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the
436 | * crQUEUE_SEND example).
437 | *
438 | * @param pxResult The variable pointed to by pxResult will be set to pdPASS if
439 | * data was successfully retrieved from the queue, otherwise it will be set to
440 | * an error code as defined within ProjDefs.h.
441 | *
442 | * Example usage:
443 |
444 | // A co-routine receives the number of an LED to flash from a queue. It
445 | // blocks on the queue until the number is received.
446 | static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
447 | {
448 | // Variables in co-routines must be declared static if they must maintain value across a blocking call.
449 | static BaseType_t xResult;
450 | static UBaseType_t uxLEDToFlash;
451 |
452 | // All co-routines must start with a call to crSTART().
453 | crSTART( xHandle );
454 |
455 | for( ;; )
456 | {
457 | // Wait for data to become available on the queue.
458 | crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
459 |
460 | if( xResult == pdPASS )
461 | {
462 | // We received the LED to flash - flash it!
463 | vParTestToggleLED( uxLEDToFlash );
464 | }
465 | }
466 |
467 | crEND();
468 | }
469 | * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE
470 | * \ingroup Tasks
471 | */
472 | #define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \
473 | { \
474 | *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) ); \
475 | if( *( pxResult ) == errQUEUE_BLOCKED ) \
476 | { \
477 | crSET_STATE0( ( xHandle ) ); \
478 | *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 ); \
479 | } \
480 | if( *( pxResult ) == errQUEUE_YIELD ) \
481 | { \
482 | crSET_STATE1( ( xHandle ) ); \
483 | *( pxResult ) = pdPASS; \
484 | } \
485 | }
486 |
487 | /**
488 | * croutine. h
489 | *
490 | crQUEUE_SEND_FROM_ISR(
491 | QueueHandle_t pxQueue,
492 | void *pvItemToQueue,
493 | BaseType_t xCoRoutinePreviouslyWoken
494 | )
495 | *
496 | * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
497 | * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
498 | * functions used by tasks.
499 | *
500 | * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
501 | * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
502 | * xQueueReceiveFromISR() can only be used to pass data between a task and and
503 | * ISR.
504 | *
505 | * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue
506 | * that is being used from within a co-routine.
507 | *
508 | * See the co-routine section of the WEB documentation for information on
509 | * passing data between tasks and co-routines and between ISR's and
510 | * co-routines.
511 | *
512 | * @param xQueue The handle to the queue on which the item is to be posted.
513 | *
514 | * @param pvItemToQueue A pointer to the item that is to be placed on the
515 | * queue. The size of the items the queue will hold was defined when the
516 | * queue was created, so this many bytes will be copied from pvItemToQueue
517 | * into the queue storage area.
518 | *
519 | * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto
520 | * the same queue multiple times from a single interrupt. The first call
521 | * should always pass in pdFALSE. Subsequent calls should pass in
522 | * the value returned from the previous call.
523 | *
524 | * @return pdTRUE if a co-routine was woken by posting onto the queue. This is
525 | * used by the ISR to determine if a context switch may be required following
526 | * the ISR.
527 | *
528 | * Example usage:
529 |
530 | // A co-routine that blocks on a queue waiting for characters to be received.
531 | static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
532 | {
533 | char cRxedChar;
534 | BaseType_t xResult;
535 |
536 | // All co-routines must start with a call to crSTART().
537 | crSTART( xHandle );
538 |
539 | for( ;; )
540 | {
541 | // Wait for data to become available on the queue. This assumes the
542 | // queue xCommsRxQueue has already been created!
543 | crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
544 |
545 | // Was a character received?
546 | if( xResult == pdPASS )
547 | {
548 | // Process the character here.
549 | }
550 | }
551 |
552 | // All co-routines must end with a call to crEND().
553 | crEND();
554 | }
555 |
556 | // An ISR that uses a queue to send characters received on a serial port to
557 | // a co-routine.
558 | void vUART_ISR( void )
559 | {
560 | char cRxedChar;
561 | BaseType_t xCRWokenByPost = pdFALSE;
562 |
563 | // We loop around reading characters until there are none left in the UART.
564 | while( UART_RX_REG_NOT_EMPTY() )
565 | {
566 | // Obtain the character from the UART.
567 | cRxedChar = UART_RX_REG;
568 |
569 | // Post the character onto a queue. xCRWokenByPost will be pdFALSE
570 | // the first time around the loop. If the post causes a co-routine
571 | // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
572 | // In this manner we can ensure that if more than one co-routine is
573 | // blocked on the queue only one is woken by this ISR no matter how
574 | // many characters are posted to the queue.
575 | xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
576 | }
577 | }
578 | * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR
579 | * \ingroup Tasks
580 | */
581 | #define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) )
582 |
583 |
584 | /**
585 | * croutine. h
586 | *
587 | crQUEUE_SEND_FROM_ISR(
588 | QueueHandle_t pxQueue,
589 | void *pvBuffer,
590 | BaseType_t * pxCoRoutineWoken
591 | )
592 | *
593 | * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
594 | * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
595 | * functions used by tasks.
596 | *
597 | * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
598 | * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
599 | * xQueueReceiveFromISR() can only be used to pass data between a task and and
600 | * ISR.
601 | *
602 | * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data
603 | * from a queue that is being used from within a co-routine (a co-routine
604 | * posted to the queue).
605 | *
606 | * See the co-routine section of the WEB documentation for information on
607 | * passing data between tasks and co-routines and between ISR's and
608 | * co-routines.
609 | *
610 | * @param xQueue The handle to the queue on which the item is to be posted.
611 | *
612 | * @param pvBuffer A pointer to a buffer into which the received item will be
613 | * placed. The size of the items the queue will hold was defined when the
614 | * queue was created, so this many bytes will be copied from the queue into
615 | * pvBuffer.
616 | *
617 | * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become
618 | * available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a
619 | * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise
620 | * *pxCoRoutineWoken will remain unchanged.
621 | *
622 | * @return pdTRUE an item was successfully received from the queue, otherwise
623 | * pdFALSE.
624 | *
625 | * Example usage:
626 |
627 | // A co-routine that posts a character to a queue then blocks for a fixed
628 | // period. The character is incremented each time.
629 | static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
630 | {
631 | // cChar holds its value while this co-routine is blocked and must therefore
632 | // be declared static.
633 | static char cCharToTx = 'a';
634 | BaseType_t xResult;
635 |
636 | // All co-routines must start with a call to crSTART().
637 | crSTART( xHandle );
638 |
639 | for( ;; )
640 | {
641 | // Send the next character to the queue.
642 | crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
643 |
644 | if( xResult == pdPASS )
645 | {
646 | // The character was successfully posted to the queue.
647 | }
648 | else
649 | {
650 | // Could not post the character to the queue.
651 | }
652 |
653 | // Enable the UART Tx interrupt to cause an interrupt in this
654 | // hypothetical UART. The interrupt will obtain the character
655 | // from the queue and send it.
656 | ENABLE_RX_INTERRUPT();
657 |
658 | // Increment to the next character then block for a fixed period.
659 | // cCharToTx will maintain its value across the delay as it is
660 | // declared static.
661 | cCharToTx++;
662 | if( cCharToTx > 'x' )
663 | {
664 | cCharToTx = 'a';
665 | }
666 | crDELAY( 100 );
667 | }
668 |
669 | // All co-routines must end with a call to crEND().
670 | crEND();
671 | }
672 |
673 | // An ISR that uses a queue to receive characters to send on a UART.
674 | void vUART_ISR( void )
675 | {
676 | char cCharToTx;
677 | BaseType_t xCRWokenByPost = pdFALSE;
678 |
679 | while( UART_TX_REG_EMPTY() )
680 | {
681 | // Are there any characters in the queue waiting to be sent?
682 | // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
683 | // is woken by the post - ensuring that only a single co-routine is
684 | // woken no matter how many times we go around this loop.
685 | if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
686 | {
687 | SEND_CHARACTER( cCharToTx );
688 | }
689 | }
690 | }
691 | * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR
692 | * \ingroup Tasks
693 | */
694 | #define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) )
695 |
696 | /*
697 | * This function is intended for internal use by the co-routine macros only.
698 | * The macro nature of the co-routine implementation requires that the
699 | * prototype appears here. The function should not be used by application
700 | * writers.
701 | *
702 | * Removes the current co-routine from its ready list and places it in the
703 | * appropriate delayed list.
704 | */
705 | void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList );
706 |
707 | /*
708 | * This function is intended for internal use by the queue implementation only.
709 | * The function should not be used by application writers.
710 | *
711 | * Removes the highest priority co-routine from the event list and places it in
712 | * the pending ready list.
713 | */
714 | BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList );
715 |
716 | #ifdef __cplusplus
717 | }
718 | #endif
719 |
720 | #endif /* CO_ROUTINE_H */
721 |
--------------------------------------------------------------------------------
/src/deprecated_definitions.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeRTOS Kernel V10.2.0
3 | * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | *
22 | * http://www.FreeRTOS.org
23 | * http://aws.amazon.com/freertos
24 | *
25 | * 1 tab == 4 spaces!
26 | */
27 |
28 | #ifndef DEPRECATED_DEFINITIONS_H
29 | #define DEPRECATED_DEFINITIONS_H
30 |
31 |
32 | /* Each FreeRTOS port has a unique portmacro.h header file. Originally a
33 | pre-processor definition was used to ensure the pre-processor found the correct
34 | portmacro.h file for the port being used. That scheme was deprecated in favour
35 | of setting the compiler's include path such that it found the correct
36 | portmacro.h file - removing the need for the constant and allowing the
37 | portmacro.h file to be located anywhere in relation to the port being used. The
38 | definitions below remain in the code for backward compatibility only. New
39 | projects should not use them. */
40 |
41 | #ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
42 | #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
43 | typedef void ( __interrupt __far *pxISR )();
44 | #endif
45 |
46 | #ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
47 | #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h"
48 | typedef void ( __interrupt __far *pxISR )();
49 | #endif
50 |
51 | #ifdef GCC_MEGA_AVR
52 | #include "../portable/GCC/ATMega323/portmacro.h"
53 | #endif
54 |
55 | #ifdef IAR_MEGA_AVR
56 | #include "../portable/IAR/ATMega323/portmacro.h"
57 | #endif
58 |
59 | #ifdef MPLAB_PIC24_PORT
60 | #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
61 | #endif
62 |
63 | #ifdef MPLAB_DSPIC_PORT
64 | #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
65 | #endif
66 |
67 | #ifdef MPLAB_PIC18F_PORT
68 | #include "../../Source/portable/MPLAB/PIC18F/portmacro.h"
69 | #endif
70 |
71 | #ifdef MPLAB_PIC32MX_PORT
72 | #include "../../Source/portable/MPLAB/PIC32MX/portmacro.h"
73 | #endif
74 |
75 | #ifdef _FEDPICC
76 | #include "libFreeRTOS/Include/portmacro.h"
77 | #endif
78 |
79 | #ifdef SDCC_CYGNAL
80 | #include "../../Source/portable/SDCC/Cygnal/portmacro.h"
81 | #endif
82 |
83 | #ifdef GCC_ARM7
84 | #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
85 | #endif
86 |
87 | #ifdef GCC_ARM7_ECLIPSE
88 | #include "portmacro.h"
89 | #endif
90 |
91 | #ifdef ROWLEY_LPC23xx
92 | #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
93 | #endif
94 |
95 | #ifdef IAR_MSP430
96 | #include "..\..\Source\portable\IAR\MSP430\portmacro.h"
97 | #endif
98 |
99 | #ifdef GCC_MSP430
100 | #include "../../Source/portable/GCC/MSP430F449/portmacro.h"
101 | #endif
102 |
103 | #ifdef ROWLEY_MSP430
104 | #include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
105 | #endif
106 |
107 | #ifdef ARM7_LPC21xx_KEIL_RVDS
108 | #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h"
109 | #endif
110 |
111 | #ifdef SAM7_GCC
112 | #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
113 | #endif
114 |
115 | #ifdef SAM7_IAR
116 | #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
117 | #endif
118 |
119 | #ifdef SAM9XE_IAR
120 | #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h"
121 | #endif
122 |
123 | #ifdef LPC2000_IAR
124 | #include "..\..\Source\portable\IAR\LPC2000\portmacro.h"
125 | #endif
126 |
127 | #ifdef STR71X_IAR
128 | #include "..\..\Source\portable\IAR\STR71x\portmacro.h"
129 | #endif
130 |
131 | #ifdef STR75X_IAR
132 | #include "..\..\Source\portable\IAR\STR75x\portmacro.h"
133 | #endif
134 |
135 | #ifdef STR75X_GCC
136 | #include "..\..\Source\portable\GCC\STR75x\portmacro.h"
137 | #endif
138 |
139 | #ifdef STR91X_IAR
140 | #include "..\..\Source\portable\IAR\STR91x\portmacro.h"
141 | #endif
142 |
143 | #ifdef GCC_H8S
144 | #include "../../Source/portable/GCC/H8S2329/portmacro.h"
145 | #endif
146 |
147 | #ifdef GCC_AT91FR40008
148 | #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h"
149 | #endif
150 |
151 | #ifdef RVDS_ARMCM3_LM3S102
152 | #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h"
153 | #endif
154 |
155 | #ifdef GCC_ARMCM3_LM3S102
156 | #include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
157 | #endif
158 |
159 | #ifdef GCC_ARMCM3
160 | #include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
161 | #endif
162 |
163 | #ifdef IAR_ARM_CM3
164 | #include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
165 | #endif
166 |
167 | #ifdef IAR_ARMCM3_LM
168 | #include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
169 | #endif
170 |
171 | #ifdef HCS12_CODE_WARRIOR
172 | #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h"
173 | #endif
174 |
175 | #ifdef MICROBLAZE_GCC
176 | #include "../../Source/portable/GCC/MicroBlaze/portmacro.h"
177 | #endif
178 |
179 | #ifdef TERN_EE
180 | #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h"
181 | #endif
182 |
183 | #ifdef GCC_HCS12
184 | #include "../../Source/portable/GCC/HCS12/portmacro.h"
185 | #endif
186 |
187 | #ifdef GCC_MCF5235
188 | #include "../../Source/portable/GCC/MCF5235/portmacro.h"
189 | #endif
190 |
191 | #ifdef COLDFIRE_V2_GCC
192 | #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h"
193 | #endif
194 |
195 | #ifdef COLDFIRE_V2_CODEWARRIOR
196 | #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h"
197 | #endif
198 |
199 | #ifdef GCC_PPC405
200 | #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h"
201 | #endif
202 |
203 | #ifdef GCC_PPC440
204 | #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h"
205 | #endif
206 |
207 | #ifdef _16FX_SOFTUNE
208 | #include "..\..\Source\portable\Softune\MB96340\portmacro.h"
209 | #endif
210 |
211 | #ifdef BCC_INDUSTRIAL_PC_PORT
212 | /* A short file name has to be used in place of the normal
213 | FreeRTOSConfig.h when using the Borland compiler. */
214 | #include "frconfig.h"
215 | #include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
216 | typedef void ( __interrupt __far *pxISR )();
217 | #endif
218 |
219 | #ifdef BCC_FLASH_LITE_186_PORT
220 | /* A short file name has to be used in place of the normal
221 | FreeRTOSConfig.h when using the Borland compiler. */
222 | #include "frconfig.h"
223 | #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
224 | typedef void ( __interrupt __far *pxISR )();
225 | #endif
226 |
227 | #ifdef __GNUC__
228 | #ifdef __AVR32_AVR32A__
229 | #include "portmacro.h"
230 | #endif
231 | #endif
232 |
233 | #ifdef __ICCAVR32__
234 | #ifdef __CORE__
235 | #if __CORE__ == __AVR32A__
236 | #include "portmacro.h"
237 | #endif
238 | #endif
239 | #endif
240 |
241 | #ifdef __91467D
242 | #include "portmacro.h"
243 | #endif
244 |
245 | #ifdef __96340
246 | #include "portmacro.h"
247 | #endif
248 |
249 |
250 | #ifdef __IAR_V850ES_Fx3__
251 | #include "../../Source/portable/IAR/V850ES/portmacro.h"
252 | #endif
253 |
254 | #ifdef __IAR_V850ES_Jx3__
255 | #include "../../Source/portable/IAR/V850ES/portmacro.h"
256 | #endif
257 |
258 | #ifdef __IAR_V850ES_Jx3_L__
259 | #include "../../Source/portable/IAR/V850ES/portmacro.h"
260 | #endif
261 |
262 | #ifdef __IAR_V850ES_Jx2__
263 | #include "../../Source/portable/IAR/V850ES/portmacro.h"
264 | #endif
265 |
266 | #ifdef __IAR_V850ES_Hx2__
267 | #include "../../Source/portable/IAR/V850ES/portmacro.h"
268 | #endif
269 |
270 | #ifdef __IAR_78K0R_Kx3__
271 | #include "../../Source/portable/IAR/78K0R/portmacro.h"
272 | #endif
273 |
274 | #ifdef __IAR_78K0R_Kx3L__
275 | #include "../../Source/portable/IAR/78K0R/portmacro.h"
276 | #endif
277 |
278 | #endif /* DEPRECATED_DEFINITIONS_H */
279 |
280 |
--------------------------------------------------------------------------------
/src/event_groups.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeRTOS Kernel V10.2.0
3 | * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | *
22 | * http://www.FreeRTOS.org
23 | * http://aws.amazon.com/freertos
24 | *
25 | * 1 tab == 4 spaces!
26 | */
27 |
28 | /* Standard includes. */
29 | #include
30 |
31 | /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
32 | all the API functions to use the MPU wrappers. That should only be done when
33 | task.h is included from an application file. */
34 | #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
35 |
36 | /* FreeRTOS includes. */
37 | #include "FreeRTOS.h"
38 | #include "task.h"
39 | #include "timers.h"
40 | #include "event_groups.h"
41 |
42 | /* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified
43 | because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
44 | for the header files above, but not in this file, in order to generate the
45 | correct privileged Vs unprivileged linkage and placement. */
46 | #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */
47 |
48 | /* The following bit fields convey control information in a task's event list
49 | item value. It is important they don't clash with the
50 | taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
51 | #if configUSE_16_BIT_TICKS == 1
52 | #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
53 | #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
54 | #define eventWAIT_FOR_ALL_BITS 0x0400U
55 | #define eventEVENT_BITS_CONTROL_BYTES 0xff00U
56 | #else
57 | #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
58 | #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
59 | #define eventWAIT_FOR_ALL_BITS 0x04000000UL
60 | #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
61 | #endif
62 |
63 | typedef struct EventGroupDef_t
64 | {
65 | EventBits_t uxEventBits;
66 | List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
67 |
68 | #if( configUSE_TRACE_FACILITY == 1 )
69 | UBaseType_t uxEventGroupNumber;
70 | #endif
71 |
72 | #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
73 | uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
74 | #endif
75 | } EventGroup_t;
76 |
77 | /*-----------------------------------------------------------*/
78 |
79 | /*
80 | * Test the bits set in uxCurrentEventBits to see if the wait condition is met.
81 | * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
82 | * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
83 | * are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
84 | * wait condition is met if any of the bits set in uxBitsToWait for are also set
85 | * in uxCurrentEventBits.
86 | */
87 | static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
88 |
89 | /*-----------------------------------------------------------*/
90 |
91 | #if( configSUPPORT_STATIC_ALLOCATION == 1 )
92 |
93 | EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer )
94 | {
95 | EventGroup_t *pxEventBits;
96 |
97 | /* A StaticEventGroup_t object must be provided. */
98 | configASSERT( pxEventGroupBuffer );
99 |
100 | #if( configASSERT_DEFINED == 1 )
101 | {
102 | /* Sanity check that the size of the structure used to declare a
103 | variable of type StaticEventGroup_t equals the size of the real
104 | event group structure. */
105 | volatile size_t xSize = sizeof( StaticEventGroup_t );
106 | configASSERT( xSize == sizeof( EventGroup_t ) );
107 | } /*lint !e529 xSize is referenced if configASSERT() is defined. */
108 | #endif /* configASSERT_DEFINED */
109 |
110 | /* The user has provided a statically allocated event group - use it. */
111 | pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 !e9087 EventGroup_t and StaticEventGroup_t are deliberately aliased for data hiding purposes and guaranteed to have the same size and alignment requirement - checked by configASSERT(). */
112 |
113 | if( pxEventBits != NULL )
114 | {
115 | pxEventBits->uxEventBits = 0;
116 | vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
117 |
118 | #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
119 | {
120 | /* Both static and dynamic allocation can be used, so note that
121 | this event group was created statically in case the event group
122 | is later deleted. */
123 | pxEventBits->ucStaticallyAllocated = pdTRUE;
124 | }
125 | #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
126 |
127 | traceEVENT_GROUP_CREATE( pxEventBits );
128 | }
129 | else
130 | {
131 | /* xEventGroupCreateStatic should only ever be called with
132 | pxEventGroupBuffer pointing to a pre-allocated (compile time
133 | allocated) StaticEventGroup_t variable. */
134 | traceEVENT_GROUP_CREATE_FAILED();
135 | }
136 |
137 | return pxEventBits;
138 | }
139 |
140 | #endif /* configSUPPORT_STATIC_ALLOCATION */
141 | /*-----------------------------------------------------------*/
142 |
143 | #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
144 |
145 | EventGroupHandle_t xEventGroupCreate( void )
146 | {
147 | EventGroup_t *pxEventBits;
148 |
149 | /* Allocate the event group. Justification for MISRA deviation as
150 | follows: pvPortMalloc() always ensures returned memory blocks are
151 | aligned per the requirements of the MCU stack. In this case
152 | pvPortMalloc() must return a pointer that is guaranteed to meet the
153 | alignment requirements of the EventGroup_t structure - which (if you
154 | follow it through) is the alignment requirements of the TickType_t type
155 | (EventBits_t being of TickType_t itself). Therefore, whenever the
156 | stack alignment requirements are greater than or equal to the
157 | TickType_t alignment requirements the cast is safe. In other cases,
158 | where the natural word size of the architecture is less than
159 | sizeof( TickType_t ), the TickType_t variables will be accessed in two
160 | or more reads operations, and the alignment requirements is only that
161 | of each individual read. */
162 | pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
163 |
164 | if( pxEventBits != NULL )
165 | {
166 | pxEventBits->uxEventBits = 0;
167 | vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
168 |
169 | #if( configSUPPORT_STATIC_ALLOCATION == 1 )
170 | {
171 | /* Both static and dynamic allocation can be used, so note this
172 | event group was allocated statically in case the event group is
173 | later deleted. */
174 | pxEventBits->ucStaticallyAllocated = pdFALSE;
175 | }
176 | #endif /* configSUPPORT_STATIC_ALLOCATION */
177 |
178 | traceEVENT_GROUP_CREATE( pxEventBits );
179 | }
180 | else
181 | {
182 | traceEVENT_GROUP_CREATE_FAILED(); /*lint !e9063 Else branch only exists to allow tracing and does not generate code if trace macros are not defined. */
183 | }
184 |
185 | return pxEventBits;
186 | }
187 |
188 | #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
189 | /*-----------------------------------------------------------*/
190 |
191 | EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
192 | {
193 | EventBits_t uxOriginalBitValue, uxReturn;
194 | EventGroup_t *pxEventBits = xEventGroup;
195 | BaseType_t xAlreadyYielded;
196 | BaseType_t xTimeoutOccurred = pdFALSE;
197 |
198 | configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
199 | configASSERT( uxBitsToWaitFor != 0 );
200 | #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
201 | {
202 | configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
203 | }
204 | #endif
205 |
206 | vTaskSuspendAll();
207 | {
208 | uxOriginalBitValue = pxEventBits->uxEventBits;
209 |
210 | ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
211 |
212 | if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
213 | {
214 | /* All the rendezvous bits are now set - no need to block. */
215 | uxReturn = ( uxOriginalBitValue | uxBitsToSet );
216 |
217 | /* Rendezvous always clear the bits. They will have been cleared
218 | already unless this is the only task in the rendezvous. */
219 | pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
220 |
221 | xTicksToWait = 0;
222 | }
223 | else
224 | {
225 | if( xTicksToWait != ( TickType_t ) 0 )
226 | {
227 | traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
228 |
229 | /* Store the bits that the calling task is waiting for in the
230 | task's event list item so the kernel knows when a match is
231 | found. Then enter the blocked state. */
232 | vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
233 |
234 | /* This assignment is obsolete as uxReturn will get set after
235 | the task unblocks, but some compilers mistakenly generate a
236 | warning about uxReturn being returned without being set if the
237 | assignment is omitted. */
238 | uxReturn = 0;
239 | }
240 | else
241 | {
242 | /* The rendezvous bits were not set, but no block time was
243 | specified - just return the current event bit value. */
244 | uxReturn = pxEventBits->uxEventBits;
245 | xTimeoutOccurred = pdTRUE;
246 | }
247 | }
248 | }
249 | xAlreadyYielded = xTaskResumeAll();
250 |
251 | if( xTicksToWait != ( TickType_t ) 0 )
252 | {
253 | if( xAlreadyYielded == pdFALSE )
254 | {
255 | portYIELD_WITHIN_API();
256 | }
257 | else
258 | {
259 | mtCOVERAGE_TEST_MARKER();
260 | }
261 |
262 | /* The task blocked to wait for its required bits to be set - at this
263 | point either the required bits were set or the block time expired. If
264 | the required bits were set they will have been stored in the task's
265 | event list item, and they should now be retrieved then cleared. */
266 | uxReturn = uxTaskResetEventItemValue();
267 |
268 | if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
269 | {
270 | /* The task timed out, just return the current event bit value. */
271 | taskENTER_CRITICAL();
272 | {
273 | uxReturn = pxEventBits->uxEventBits;
274 |
275 | /* Although the task got here because it timed out before the
276 | bits it was waiting for were set, it is possible that since it
277 | unblocked another task has set the bits. If this is the case
278 | then it needs to clear the bits before exiting. */
279 | if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
280 | {
281 | pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
282 | }
283 | else
284 | {
285 | mtCOVERAGE_TEST_MARKER();
286 | }
287 | }
288 | taskEXIT_CRITICAL();
289 |
290 | xTimeoutOccurred = pdTRUE;
291 | }
292 | else
293 | {
294 | /* The task unblocked because the bits were set. */
295 | }
296 |
297 | /* Control bits might be set as the task had blocked should not be
298 | returned. */
299 | uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
300 | }
301 |
302 | traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
303 |
304 | /* Prevent compiler warnings when trace macros are not used. */
305 | ( void ) xTimeoutOccurred;
306 |
307 | return uxReturn;
308 | }
309 | /*-----------------------------------------------------------*/
310 |
311 | EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
312 | {
313 | EventGroup_t *pxEventBits = xEventGroup;
314 | EventBits_t uxReturn, uxControlBits = 0;
315 | BaseType_t xWaitConditionMet, xAlreadyYielded;
316 | BaseType_t xTimeoutOccurred = pdFALSE;
317 |
318 | /* Check the user is not attempting to wait on the bits used by the kernel
319 | itself, and that at least one bit is being requested. */
320 | configASSERT( xEventGroup );
321 | configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
322 | configASSERT( uxBitsToWaitFor != 0 );
323 | #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
324 | {
325 | configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
326 | }
327 | #endif
328 |
329 | vTaskSuspendAll();
330 | {
331 | const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
332 |
333 | /* Check to see if the wait condition is already met or not. */
334 | xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
335 |
336 | if( xWaitConditionMet != pdFALSE )
337 | {
338 | /* The wait condition has already been met so there is no need to
339 | block. */
340 | uxReturn = uxCurrentEventBits;
341 | xTicksToWait = ( TickType_t ) 0;
342 |
343 | /* Clear the wait bits if requested to do so. */
344 | if( xClearOnExit != pdFALSE )
345 | {
346 | pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
347 | }
348 | else
349 | {
350 | mtCOVERAGE_TEST_MARKER();
351 | }
352 | }
353 | else if( xTicksToWait == ( TickType_t ) 0 )
354 | {
355 | /* The wait condition has not been met, but no block time was
356 | specified, so just return the current value. */
357 | uxReturn = uxCurrentEventBits;
358 | xTimeoutOccurred = pdTRUE;
359 | }
360 | else
361 | {
362 | /* The task is going to block to wait for its required bits to be
363 | set. uxControlBits are used to remember the specified behaviour of
364 | this call to xEventGroupWaitBits() - for use when the event bits
365 | unblock the task. */
366 | if( xClearOnExit != pdFALSE )
367 | {
368 | uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
369 | }
370 | else
371 | {
372 | mtCOVERAGE_TEST_MARKER();
373 | }
374 |
375 | if( xWaitForAllBits != pdFALSE )
376 | {
377 | uxControlBits |= eventWAIT_FOR_ALL_BITS;
378 | }
379 | else
380 | {
381 | mtCOVERAGE_TEST_MARKER();
382 | }
383 |
384 | /* Store the bits that the calling task is waiting for in the
385 | task's event list item so the kernel knows when a match is
386 | found. Then enter the blocked state. */
387 | vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
388 |
389 | /* This is obsolete as it will get set after the task unblocks, but
390 | some compilers mistakenly generate a warning about the variable
391 | being returned without being set if it is not done. */
392 | uxReturn = 0;
393 |
394 | traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
395 | }
396 | }
397 | xAlreadyYielded = xTaskResumeAll();
398 |
399 | if( xTicksToWait != ( TickType_t ) 0 )
400 | {
401 | if( xAlreadyYielded == pdFALSE )
402 | {
403 | portYIELD_WITHIN_API();
404 | }
405 | else
406 | {
407 | mtCOVERAGE_TEST_MARKER();
408 | }
409 |
410 | /* The task blocked to wait for its required bits to be set - at this
411 | point either the required bits were set or the block time expired. If
412 | the required bits were set they will have been stored in the task's
413 | event list item, and they should now be retrieved then cleared. */
414 | uxReturn = uxTaskResetEventItemValue();
415 |
416 | if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
417 | {
418 | taskENTER_CRITICAL();
419 | {
420 | /* The task timed out, just return the current event bit value. */
421 | uxReturn = pxEventBits->uxEventBits;
422 |
423 | /* It is possible that the event bits were updated between this
424 | task leaving the Blocked state and running again. */
425 | if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
426 | {
427 | if( xClearOnExit != pdFALSE )
428 | {
429 | pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
430 | }
431 | else
432 | {
433 | mtCOVERAGE_TEST_MARKER();
434 | }
435 | }
436 | else
437 | {
438 | mtCOVERAGE_TEST_MARKER();
439 | }
440 | xTimeoutOccurred = pdTRUE;
441 | }
442 | taskEXIT_CRITICAL();
443 | }
444 | else
445 | {
446 | /* The task unblocked because the bits were set. */
447 | }
448 |
449 | /* The task blocked so control bits may have been set. */
450 | uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
451 | }
452 | traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
453 |
454 | /* Prevent compiler warnings when trace macros are not used. */
455 | ( void ) xTimeoutOccurred;
456 |
457 | return uxReturn;
458 | }
459 | /*-----------------------------------------------------------*/
460 |
461 | EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
462 | {
463 | EventGroup_t *pxEventBits = xEventGroup;
464 | EventBits_t uxReturn;
465 |
466 | /* Check the user is not attempting to clear the bits used by the kernel
467 | itself. */
468 | configASSERT( xEventGroup );
469 | configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
470 |
471 | taskENTER_CRITICAL();
472 | {
473 | traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
474 |
475 | /* The value returned is the event group value prior to the bits being
476 | cleared. */
477 | uxReturn = pxEventBits->uxEventBits;
478 |
479 | /* Clear the bits. */
480 | pxEventBits->uxEventBits &= ~uxBitsToClear;
481 | }
482 | taskEXIT_CRITICAL();
483 |
484 | return uxReturn;
485 | }
486 | /*-----------------------------------------------------------*/
487 |
488 | #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
489 |
490 | BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
491 | {
492 | BaseType_t xReturn;
493 |
494 | traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
495 | xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */
496 |
497 | return xReturn;
498 | }
499 |
500 | #endif
501 | /*-----------------------------------------------------------*/
502 |
503 | EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
504 | {
505 | UBaseType_t uxSavedInterruptStatus;
506 | EventGroup_t const * const pxEventBits = xEventGroup;
507 | EventBits_t uxReturn;
508 |
509 | uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
510 | {
511 | uxReturn = pxEventBits->uxEventBits;
512 | }
513 | portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
514 |
515 | return uxReturn;
516 | } /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
517 | /*-----------------------------------------------------------*/
518 |
519 | EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
520 | {
521 | ListItem_t *pxListItem, *pxNext;
522 | ListItem_t const *pxListEnd;
523 | List_t const * pxList;
524 | EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
525 | EventGroup_t *pxEventBits = xEventGroup;
526 | BaseType_t xMatchFound = pdFALSE;
527 |
528 | /* Check the user is not attempting to set the bits used by the kernel
529 | itself. */
530 | configASSERT( xEventGroup );
531 | configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
532 |
533 | pxList = &( pxEventBits->xTasksWaitingForBits );
534 | pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
535 | vTaskSuspendAll();
536 | {
537 | traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
538 |
539 | pxListItem = listGET_HEAD_ENTRY( pxList );
540 |
541 | /* Set the bits. */
542 | pxEventBits->uxEventBits |= uxBitsToSet;
543 |
544 | /* See if the new bit value should unblock any tasks. */
545 | while( pxListItem != pxListEnd )
546 | {
547 | pxNext = listGET_NEXT( pxListItem );
548 | uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
549 | xMatchFound = pdFALSE;
550 |
551 | /* Split the bits waited for from the control bits. */
552 | uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
553 | uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
554 |
555 | if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
556 | {
557 | /* Just looking for single bit being set. */
558 | if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
559 | {
560 | xMatchFound = pdTRUE;
561 | }
562 | else
563 | {
564 | mtCOVERAGE_TEST_MARKER();
565 | }
566 | }
567 | else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
568 | {
569 | /* All bits are set. */
570 | xMatchFound = pdTRUE;
571 | }
572 | else
573 | {
574 | /* Need all bits to be set, but not all the bits were set. */
575 | }
576 |
577 | if( xMatchFound != pdFALSE )
578 | {
579 | /* The bits match. Should the bits be cleared on exit? */
580 | if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
581 | {
582 | uxBitsToClear |= uxBitsWaitedFor;
583 | }
584 | else
585 | {
586 | mtCOVERAGE_TEST_MARKER();
587 | }
588 |
589 | /* Store the actual event flag value in the task's event list
590 | item before removing the task from the event list. The
591 | eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
592 | that is was unblocked due to its required bits matching, rather
593 | than because it timed out. */
594 | vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
595 | }
596 |
597 | /* Move onto the next list item. Note pxListItem->pxNext is not
598 | used here as the list item may have been removed from the event list
599 | and inserted into the ready/pending reading list. */
600 | pxListItem = pxNext;
601 | }
602 |
603 | /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
604 | bit was set in the control word. */
605 | pxEventBits->uxEventBits &= ~uxBitsToClear;
606 | }
607 | ( void ) xTaskResumeAll();
608 |
609 | return pxEventBits->uxEventBits;
610 | }
611 | /*-----------------------------------------------------------*/
612 |
613 | void vEventGroupDelete( EventGroupHandle_t xEventGroup )
614 | {
615 | EventGroup_t *pxEventBits = xEventGroup;
616 | const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
617 |
618 | vTaskSuspendAll();
619 | {
620 | traceEVENT_GROUP_DELETE( xEventGroup );
621 |
622 | while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
623 | {
624 | /* Unblock the task, returning 0 as the event list is being deleted
625 | and cannot therefore have any bits set. */
626 | configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
627 | vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
628 | }
629 |
630 | #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
631 | {
632 | /* The event group can only have been allocated dynamically - free
633 | it again. */
634 | vPortFree( pxEventBits );
635 | }
636 | #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
637 | {
638 | /* The event group could have been allocated statically or
639 | dynamically, so check before attempting to free the memory. */
640 | if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
641 | {
642 | vPortFree( pxEventBits );
643 | }
644 | else
645 | {
646 | mtCOVERAGE_TEST_MARKER();
647 | }
648 | }
649 | #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
650 | }
651 | ( void ) xTaskResumeAll();
652 | }
653 | /*-----------------------------------------------------------*/
654 |
655 | /* For internal use only - execute a 'set bits' command that was pended from
656 | an interrupt. */
657 | void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet )
658 | {
659 | ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
660 | }
661 | /*-----------------------------------------------------------*/
662 |
663 | /* For internal use only - execute a 'clear bits' command that was pended from
664 | an interrupt. */
665 | void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear )
666 | {
667 | ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
668 | }
669 | /*-----------------------------------------------------------*/
670 |
671 | static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits )
672 | {
673 | BaseType_t xWaitConditionMet = pdFALSE;
674 |
675 | if( xWaitForAllBits == pdFALSE )
676 | {
677 | /* Task only has to wait for one bit within uxBitsToWaitFor to be
678 | set. Is one already set? */
679 | if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
680 | {
681 | xWaitConditionMet = pdTRUE;
682 | }
683 | else
684 | {
685 | mtCOVERAGE_TEST_MARKER();
686 | }
687 | }
688 | else
689 | {
690 | /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
691 | Are they set already? */
692 | if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
693 | {
694 | xWaitConditionMet = pdTRUE;
695 | }
696 | else
697 | {
698 | mtCOVERAGE_TEST_MARKER();
699 | }
700 | }
701 |
702 | return xWaitConditionMet;
703 | }
704 | /*-----------------------------------------------------------*/
705 |
706 | #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
707 |
708 | BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )
709 | {
710 | BaseType_t xReturn;
711 |
712 | traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
713 | xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */
714 |
715 | return xReturn;
716 | }
717 |
718 | #endif
719 | /*-----------------------------------------------------------*/
720 |
721 | #if (configUSE_TRACE_FACILITY == 1)
722 |
723 | UBaseType_t uxEventGroupGetNumber( void* xEventGroup )
724 | {
725 | UBaseType_t xReturn;
726 | EventGroup_t const *pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
727 |
728 | if( xEventGroup == NULL )
729 | {
730 | xReturn = 0;
731 | }
732 | else
733 | {
734 | xReturn = pxEventBits->uxEventGroupNumber;
735 | }
736 |
737 | return xReturn;
738 | }
739 |
740 | #endif /* configUSE_TRACE_FACILITY */
741 | /*-----------------------------------------------------------*/
742 |
743 | #if ( configUSE_TRACE_FACILITY == 1 )
744 |
745 | void vEventGroupSetNumber( void * xEventGroup, UBaseType_t uxEventGroupNumber )
746 | {
747 | ( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
748 | }
749 |
750 | #endif /* configUSE_TRACE_FACILITY */
751 | /*-----------------------------------------------------------*/
752 |
753 |
754 |
--------------------------------------------------------------------------------
/src/heap_3.c:
--------------------------------------------------------------------------------
1 | /*
2 | FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
3 | All rights reserved
4 |
5 | VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
6 |
7 | This file is part of the FreeRTOS distribution.
8 |
9 | FreeRTOS is free software; you can redistribute it and/or modify it under
10 | the terms of the GNU General Public License (version 2) as published by the
11 | Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
12 |
13 | ***************************************************************************
14 | >>! NOTE: The modification to the GPL is included to allow you to !<<
15 | >>! distribute a combined work that includes FreeRTOS without being !<<
16 | >>! obliged to provide the source code for proprietary components !<<
17 | >>! outside of the FreeRTOS kernel. !<<
18 | ***************************************************************************
19 |
20 | FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
21 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22 | FOR A PARTICULAR PURPOSE. Full license text is available on the following
23 | link: http://www.freertos.org/a00114.html
24 |
25 | ***************************************************************************
26 | * *
27 | * FreeRTOS provides completely free yet professionally developed, *
28 | * robust, strictly quality controlled, supported, and cross *
29 | * platform software that is more than just the market leader, it *
30 | * is the industry's de facto standard. *
31 | * *
32 | * Help yourself get started quickly while simultaneously helping *
33 | * to support the FreeRTOS project by purchasing a FreeRTOS *
34 | * tutorial book, reference manual, or both: *
35 | * http://www.FreeRTOS.org/Documentation *
36 | * *
37 | ***************************************************************************
38 |
39 | http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
40 | the FAQ page "My application does not run, what could be wrong?". Have you
41 | defined configASSERT()?
42 |
43 | http://www.FreeRTOS.org/support - In return for receiving this top quality
44 | embedded software for free we request you assist our global community by
45 | participating in the support forum.
46 |
47 | http://www.FreeRTOS.org/training - Investing in training allows your team to
48 | be as productive as possible as early as possible. Now you can receive
49 | FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
50 | Ltd, and the world's leading authority on the world's leading RTOS.
51 |
52 | http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
53 | including FreeRTOS+Trace - an indispensable productivity tool, a DOS
54 | compatible FAT file system, and our tiny thread aware UDP/IP stack.
55 |
56 | http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
57 | Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
58 |
59 | http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
60 | Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
61 | licenses offer ticketed support, indemnification and commercial middleware.
62 |
63 | http://www.SafeRTOS.com - High Integrity Systems also provide a safety
64 | engineered and independently SIL3 certified version for use in safety and
65 | mission critical applications that require provable dependability.
66 |
67 | 1 tab == 4 spaces!
68 | */
69 |
70 |
71 | /*
72 | * Implementation of pvPortMalloc() and vPortFree() that relies on the
73 | * compilers own malloc() and free() implementations.
74 | *
75 | * This file can only be used if the linker is configured to to generate
76 | * a heap memory area.
77 | *
78 | * See heap_1.c, heap_2.c and heap_4.c for alternative implementations, and the
79 | * memory management pages of http://www.FreeRTOS.org for more information.
80 | */
81 |
82 | #include
83 |
84 | /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
85 | all the API functions to use the MPU wrappers. That should only be done when
86 | task.h is included from an application file. */
87 | #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
88 |
89 | #include "FreeRTOS.h"
90 | #include "task.h"
91 |
92 | #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
93 |
94 | #if( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
95 | #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
96 | #endif
97 |
98 | /*-----------------------------------------------------------*/
99 |
100 | void *pvPortMalloc( size_t xWantedSize )
101 | {
102 | void *pvReturn;
103 |
104 | vTaskSuspendAll();
105 | {
106 | pvReturn = malloc( xWantedSize );
107 | traceMALLOC( pvReturn, xWantedSize );
108 | }
109 | ( void ) xTaskResumeAll();
110 |
111 | #if( configUSE_MALLOC_FAILED_HOOK == 1 )
112 | {
113 | if( pvReturn == NULL )
114 | {
115 | extern void vApplicationMallocFailedHook( void );
116 | vApplicationMallocFailedHook();
117 | }
118 | }
119 | #endif
120 |
121 | return pvReturn;
122 | }
123 | /*-----------------------------------------------------------*/
124 |
125 | void vPortFree( void *pv )
126 | {
127 | if( pv )
128 | {
129 | vTaskSuspendAll();
130 | {
131 | free( pv );
132 | traceFREE( pv, 0 );
133 | }
134 | ( void ) xTaskResumeAll();
135 | }
136 | }
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/src/list.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeRTOS Kernel V10.2.0
3 | * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | *
22 | * http://www.FreeRTOS.org
23 | * http://aws.amazon.com/freertos
24 | *
25 | * 1 tab == 4 spaces!
26 | */
27 |
28 |
29 | #include
30 | #include "FreeRTOS.h"
31 | #include "list.h"
32 |
33 | /*-----------------------------------------------------------
34 | * PUBLIC LIST API documented in list.h
35 | *----------------------------------------------------------*/
36 |
37 | void vListInitialise( List_t * const pxList )
38 | {
39 | /* The list structure contains a list item which is used to mark the
40 | end of the list. To initialise the list the list end is inserted
41 | as the only list entry. */
42 | pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
43 |
44 | /* The list end value is the highest possible value in the list to
45 | ensure it remains at the end of the list. */
46 | pxList->xListEnd.xItemValue = portMAX_DELAY;
47 |
48 | /* The list end next and previous pointers point to itself so we know
49 | when the list is empty. */
50 | pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
51 | pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
52 |
53 | pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
54 |
55 | /* Write known values into the list if
56 | configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
57 | listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
58 | listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
59 | }
60 | /*-----------------------------------------------------------*/
61 |
62 | void vListInitialiseItem( ListItem_t * const pxItem )
63 | {
64 | /* Make sure the list item is not recorded as being on a list. */
65 | pxItem->pxContainer = NULL;
66 |
67 | /* Write known values into the list item if
68 | configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
69 | listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
70 | listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
71 | }
72 | /*-----------------------------------------------------------*/
73 |
74 | void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
75 | {
76 | ListItem_t * const pxIndex = pxList->pxIndex;
77 |
78 | /* Only effective when configASSERT() is also defined, these tests may catch
79 | the list data structures being overwritten in memory. They will not catch
80 | data errors caused by incorrect configuration or use of FreeRTOS. */
81 | listTEST_LIST_INTEGRITY( pxList );
82 | listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
83 |
84 | /* Insert a new list item into pxList, but rather than sort the list,
85 | makes the new list item the last item to be removed by a call to
86 | listGET_OWNER_OF_NEXT_ENTRY(). */
87 | pxNewListItem->pxNext = pxIndex;
88 | pxNewListItem->pxPrevious = pxIndex->pxPrevious;
89 |
90 | /* Only used during decision coverage testing. */
91 | mtCOVERAGE_TEST_DELAY();
92 |
93 | pxIndex->pxPrevious->pxNext = pxNewListItem;
94 | pxIndex->pxPrevious = pxNewListItem;
95 |
96 | /* Remember which list the item is in. */
97 | pxNewListItem->pxContainer = pxList;
98 |
99 | ( pxList->uxNumberOfItems )++;
100 | }
101 | /*-----------------------------------------------------------*/
102 |
103 | void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
104 | {
105 | ListItem_t *pxIterator;
106 | const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
107 |
108 | /* Only effective when configASSERT() is also defined, these tests may catch
109 | the list data structures being overwritten in memory. They will not catch
110 | data errors caused by incorrect configuration or use of FreeRTOS. */
111 | listTEST_LIST_INTEGRITY( pxList );
112 | listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
113 |
114 | /* Insert the new list item into the list, sorted in xItemValue order.
115 |
116 | If the list already contains a list item with the same item value then the
117 | new list item should be placed after it. This ensures that TCBs which are
118 | stored in ready lists (all of which have the same xItemValue value) get a
119 | share of the CPU. However, if the xItemValue is the same as the back marker
120 | the iteration loop below will not end. Therefore the value is checked
121 | first, and the algorithm slightly modified if necessary. */
122 | if( xValueOfInsertion == portMAX_DELAY )
123 | {
124 | pxIterator = pxList->xListEnd.pxPrevious;
125 | }
126 | else
127 | {
128 | /* *** NOTE ***********************************************************
129 | If you find your application is crashing here then likely causes are
130 | listed below. In addition see https://www.freertos.org/FAQHelp.html for
131 | more tips, and ensure configASSERT() is defined!
132 | https://www.freertos.org/a00110.html#configASSERT
133 |
134 | 1) Stack overflow -
135 | see https://www.freertos.org/Stacks-and-stack-overflow-checking.html
136 | 2) Incorrect interrupt priority assignment, especially on Cortex-M
137 | parts where numerically high priority values denote low actual
138 | interrupt priorities, which can seem counter intuitive. See
139 | https://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition
140 | of configMAX_SYSCALL_INTERRUPT_PRIORITY on
141 | https://www.freertos.org/a00110.html
142 | 3) Calling an API function from within a critical section or when
143 | the scheduler is suspended, or calling an API function that does
144 | not end in "FromISR" from an interrupt.
145 | 4) Using a queue or semaphore before it has been initialised or
146 | before the scheduler has been started (are interrupts firing
147 | before vTaskStartScheduler() has been called?).
148 | **********************************************************************/
149 |
150 | for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */
151 | {
152 | /* There is nothing to do here, just iterating to the wanted
153 | insertion position. */
154 | }
155 | }
156 |
157 | pxNewListItem->pxNext = pxIterator->pxNext;
158 | pxNewListItem->pxNext->pxPrevious = pxNewListItem;
159 | pxNewListItem->pxPrevious = pxIterator;
160 | pxIterator->pxNext = pxNewListItem;
161 |
162 | /* Remember which list the item is in. This allows fast removal of the
163 | item later. */
164 | pxNewListItem->pxContainer = pxList;
165 |
166 | ( pxList->uxNumberOfItems )++;
167 | }
168 | /*-----------------------------------------------------------*/
169 |
170 | UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
171 | {
172 | /* The list item knows which list it is in. Obtain the list from the list
173 | item. */
174 | List_t * const pxList = pxItemToRemove->pxContainer;
175 |
176 | pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
177 | pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
178 |
179 | /* Only used during decision coverage testing. */
180 | mtCOVERAGE_TEST_DELAY();
181 |
182 | /* Make sure the index is left pointing to a valid item. */
183 | if( pxList->pxIndex == pxItemToRemove )
184 | {
185 | pxList->pxIndex = pxItemToRemove->pxPrevious;
186 | }
187 | else
188 | {
189 | mtCOVERAGE_TEST_MARKER();
190 | }
191 |
192 | pxItemToRemove->pxContainer = NULL;
193 | ( pxList->uxNumberOfItems )--;
194 |
195 | return pxList->uxNumberOfItems;
196 | }
197 | /*-----------------------------------------------------------*/
198 |
199 |
--------------------------------------------------------------------------------
/src/list.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeRTOS Kernel V10.2.0
3 | * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | *
22 | * http://www.FreeRTOS.org
23 | * http://aws.amazon.com/freertos
24 | *
25 | * 1 tab == 4 spaces!
26 | */
27 |
28 | /*
29 | * This is the list implementation used by the scheduler. While it is tailored
30 | * heavily for the schedulers needs, it is also available for use by
31 | * application code.
32 | *
33 | * list_ts can only store pointers to list_item_ts. Each ListItem_t contains a
34 | * numeric value (xItemValue). Most of the time the lists are sorted in
35 | * descending item value order.
36 | *
37 | * Lists are created already containing one list item. The value of this
38 | * item is the maximum possible that can be stored, it is therefore always at
39 | * the end of the list and acts as a marker. The list member pxHead always
40 | * points to this marker - even though it is at the tail of the list. This
41 | * is because the tail contains a wrap back pointer to the true head of
42 | * the list.
43 | *
44 | * In addition to it's value, each list item contains a pointer to the next
45 | * item in the list (pxNext), a pointer to the list it is in (pxContainer)
46 | * and a pointer to back to the object that contains it. These later two
47 | * pointers are included for efficiency of list manipulation. There is
48 | * effectively a two way link between the object containing the list item and
49 | * the list item itself.
50 | *
51 | *
52 | * \page ListIntroduction List Implementation
53 | * \ingroup FreeRTOSIntro
54 | */
55 |
56 | #ifndef INC_FREERTOS_H
57 | #error FreeRTOS.h must be included before list.h
58 | #endif
59 |
60 | #ifndef LIST_H
61 | #define LIST_H
62 |
63 | /*
64 | * The list structure members are modified from within interrupts, and therefore
65 | * by rights should be declared volatile. However, they are only modified in a
66 | * functionally atomic way (within critical sections of with the scheduler
67 | * suspended) and are either passed by reference into a function or indexed via
68 | * a volatile variable. Therefore, in all use cases tested so far, the volatile
69 | * qualifier can be omitted in order to provide a moderate performance
70 | * improvement without adversely affecting functional behaviour. The assembly
71 | * instructions generated by the IAR, ARM and GCC compilers when the respective
72 | * compiler's options were set for maximum optimisation has been inspected and
73 | * deemed to be as intended. That said, as compiler technology advances, and
74 | * especially if aggressive cross module optimisation is used (a use case that
75 | * has not been exercised to any great extend) then it is feasible that the
76 | * volatile qualifier will be needed for correct optimisation. It is expected
77 | * that a compiler removing essential code because, without the volatile
78 | * qualifier on the list structure members and with aggressive cross module
79 | * optimisation, the compiler deemed the code unnecessary will result in
80 | * complete and obvious failure of the scheduler. If this is ever experienced
81 | * then the volatile qualifier can be inserted in the relevant places within the
82 | * list structures by simply defining configLIST_VOLATILE to volatile in
83 | * FreeRTOSConfig.h (as per the example at the bottom of this comment block).
84 | * If configLIST_VOLATILE is not defined then the preprocessor directives below
85 | * will simply #define configLIST_VOLATILE away completely.
86 | *
87 | * To use volatile list structure members then add the following line to
88 | * FreeRTOSConfig.h (without the quotes):
89 | * "#define configLIST_VOLATILE volatile"
90 | */
91 | #ifndef configLIST_VOLATILE
92 | #define configLIST_VOLATILE
93 | #endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */
94 |
95 | #ifdef __cplusplus
96 | extern "C" {
97 | #endif
98 |
99 | /* Macros that can be used to place known values within the list structures,
100 | then check that the known values do not get corrupted during the execution of
101 | the application. These may catch the list data structures being overwritten in
102 | memory. They will not catch data errors caused by incorrect configuration or
103 | use of FreeRTOS.*/
104 | #if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )
105 | /* Define the macros to do nothing. */
106 | #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
107 | #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
108 | #define listFIRST_LIST_INTEGRITY_CHECK_VALUE
109 | #define listSECOND_LIST_INTEGRITY_CHECK_VALUE
110 | #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
111 | #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
112 | #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )
113 | #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )
114 | #define listTEST_LIST_ITEM_INTEGRITY( pxItem )
115 | #define listTEST_LIST_INTEGRITY( pxList )
116 | #else
117 | /* Define macros that add new members into the list structures. */
118 | #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1;
119 | #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2;
120 | #define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1;
121 | #define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2;
122 |
123 | /* Define macros that set the new structure members to known values. */
124 | #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
125 | #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
126 | #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
127 | #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
128 |
129 | /* Define macros that will assert if one of the structure members does not
130 | contain its expected value. */
131 | #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
132 | #define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
133 | #endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */
134 |
135 |
136 | /*
137 | * Definition of the only type of object that a list can contain.
138 | */
139 | struct xLIST;
140 | struct xLIST_ITEM
141 | {
142 | listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
143 | configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */
144 | struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */
145 | struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */
146 | void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */
147 | struct xLIST * configLIST_VOLATILE pxContainer; /*< Pointer to the list in which this list item is placed (if any). */
148 | listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
149 | };
150 | typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */
151 |
152 | struct xMINI_LIST_ITEM
153 | {
154 | listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
155 | configLIST_VOLATILE TickType_t xItemValue;
156 | struct xLIST_ITEM * configLIST_VOLATILE pxNext;
157 | struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
158 | };
159 | typedef struct xMINI_LIST_ITEM MiniListItem_t;
160 |
161 | /*
162 | * Definition of the type of queue used by the scheduler.
163 | */
164 | typedef struct xLIST
165 | {
166 | listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
167 | volatile UBaseType_t uxNumberOfItems;
168 | ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */
169 | MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
170 | listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
171 | } List_t;
172 |
173 | /*
174 | * Access macro to set the owner of a list item. The owner of a list item
175 | * is the object (usually a TCB) that contains the list item.
176 | *
177 | * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
178 | * \ingroup LinkedList
179 | */
180 | #define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
181 |
182 | /*
183 | * Access macro to get the owner of a list item. The owner of a list item
184 | * is the object (usually a TCB) that contains the list item.
185 | *
186 | * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
187 | * \ingroup LinkedList
188 | */
189 | #define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner )
190 |
191 | /*
192 | * Access macro to set the value of the list item. In most cases the value is
193 | * used to sort the list in descending order.
194 | *
195 | * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE
196 | * \ingroup LinkedList
197 | */
198 | #define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) )
199 |
200 | /*
201 | * Access macro to retrieve the value of the list item. The value can
202 | * represent anything - for example the priority of a task, or the time at
203 | * which a task should be unblocked.
204 | *
205 | * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
206 | * \ingroup LinkedList
207 | */
208 | #define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue )
209 |
210 | /*
211 | * Access macro to retrieve the value of the list item at the head of a given
212 | * list.
213 | *
214 | * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
215 | * \ingroup LinkedList
216 | */
217 | #define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue )
218 |
219 | /*
220 | * Return the list item at the head of the list.
221 | *
222 | * \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY
223 | * \ingroup LinkedList
224 | */
225 | #define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext )
226 |
227 | /*
228 | * Return the list item at the head of the list.
229 | *
230 | * \page listGET_NEXT listGET_NEXT
231 | * \ingroup LinkedList
232 | */
233 | #define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext )
234 |
235 | /*
236 | * Return the list item that marks the end of the list
237 | *
238 | * \page listGET_END_MARKER listGET_END_MARKER
239 | * \ingroup LinkedList
240 | */
241 | #define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
242 |
243 | /*
244 | * Access macro to determine if a list contains any items. The macro will
245 | * only have the value true if the list is empty.
246 | *
247 | * \page listLIST_IS_EMPTY listLIST_IS_EMPTY
248 | * \ingroup LinkedList
249 | */
250 | #define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )
251 |
252 | /*
253 | * Access macro to return the number of items in the list.
254 | */
255 | #define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems )
256 |
257 | /*
258 | * Access function to obtain the owner of the next entry in a list.
259 | *
260 | * The list member pxIndex is used to walk through a list. Calling
261 | * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list
262 | * and returns that entry's pxOwner parameter. Using multiple calls to this
263 | * function it is therefore possible to move through every item contained in
264 | * a list.
265 | *
266 | * The pxOwner parameter of a list item is a pointer to the object that owns
267 | * the list item. In the scheduler this is normally a task control block.
268 | * The pxOwner parameter effectively creates a two way link between the list
269 | * item and its owner.
270 | *
271 | * @param pxTCB pxTCB is set to the address of the owner of the next list item.
272 | * @param pxList The list from which the next item owner is to be returned.
273 | *
274 | * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY
275 | * \ingroup LinkedList
276 | */
277 | #define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
278 | { \
279 | List_t * const pxConstList = ( pxList ); \
280 | /* Increment the index to the next item and return the item, ensuring */ \
281 | /* we don't return the marker used at the end of the list. */ \
282 | ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
283 | if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \
284 | { \
285 | ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
286 | } \
287 | ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
288 | }
289 |
290 |
291 | /*
292 | * Access function to obtain the owner of the first entry in a list. Lists
293 | * are normally sorted in ascending item value order.
294 | *
295 | * This function returns the pxOwner member of the first item in the list.
296 | * The pxOwner parameter of a list item is a pointer to the object that owns
297 | * the list item. In the scheduler this is normally a task control block.
298 | * The pxOwner parameter effectively creates a two way link between the list
299 | * item and its owner.
300 | *
301 | * @param pxList The list from which the owner of the head item is to be
302 | * returned.
303 | *
304 | * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY
305 | * \ingroup LinkedList
306 | */
307 | #define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner )
308 |
309 | /*
310 | * Check to see if a list item is within a list. The list item maintains a
311 | * "container" pointer that points to the list it is in. All this macro does
312 | * is check to see if the container and the list match.
313 | *
314 | * @param pxList The list we want to know if the list item is within.
315 | * @param pxListItem The list item we want to know if is in the list.
316 | * @return pdTRUE if the list item is in the list, otherwise pdFALSE.
317 | */
318 | #define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) )
319 |
320 | /*
321 | * Return the list a list item is contained within (referenced from).
322 | *
323 | * @param pxListItem The list item being queried.
324 | * @return A pointer to the List_t object that references the pxListItem
325 | */
326 | #define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pxContainer )
327 |
328 | /*
329 | * This provides a crude means of knowing if a list has been initialised, as
330 | * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise()
331 | * function.
332 | */
333 | #define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )
334 |
335 | /*
336 | * Must be called before a list is used! This initialises all the members
337 | * of the list structure and inserts the xListEnd item into the list as a
338 | * marker to the back of the list.
339 | *
340 | * @param pxList Pointer to the list being initialised.
341 | *
342 | * \page vListInitialise vListInitialise
343 | * \ingroup LinkedList
344 | */
345 | void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
346 |
347 | /*
348 | * Must be called before a list item is used. This sets the list container to
349 | * null so the item does not think that it is already contained in a list.
350 | *
351 | * @param pxItem Pointer to the list item being initialised.
352 | *
353 | * \page vListInitialiseItem vListInitialiseItem
354 | * \ingroup LinkedList
355 | */
356 | void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
357 |
358 | /*
359 | * Insert a list item into a list. The item will be inserted into the list in
360 | * a position determined by its item value (descending item value order).
361 | *
362 | * @param pxList The list into which the item is to be inserted.
363 | *
364 | * @param pxNewListItem The item that is to be placed in the list.
365 | *
366 | * \page vListInsert vListInsert
367 | * \ingroup LinkedList
368 | */
369 | void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
370 |
371 | /*
372 | * Insert a list item into a list. The item will be inserted in a position
373 | * such that it will be the last item within the list returned by multiple
374 | * calls to listGET_OWNER_OF_NEXT_ENTRY.
375 | *
376 | * The list member pxIndex is used to walk through a list. Calling
377 | * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.
378 | * Placing an item in a list using vListInsertEnd effectively places the item
379 | * in the list position pointed to by pxIndex. This means that every other
380 | * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
381 | * the pxIndex parameter again points to the item being inserted.
382 | *
383 | * @param pxList The list into which the item is to be inserted.
384 | *
385 | * @param pxNewListItem The list item to be inserted into the list.
386 | *
387 | * \page vListInsertEnd vListInsertEnd
388 | * \ingroup LinkedList
389 | */
390 | void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
391 |
392 | /*
393 | * Remove an item from a list. The list item has a pointer to the list that
394 | * it is in, so only the list item need be passed into the function.
395 | *
396 | * @param uxListRemove The item to be removed. The item will remove itself from
397 | * the list pointed to by it's pxContainer parameter.
398 | *
399 | * @return The number of items that remain in the list after the list item has
400 | * been removed.
401 | *
402 | * \page uxListRemove uxListRemove
403 | * \ingroup LinkedList
404 | */
405 | UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;
406 |
407 | #ifdef __cplusplus
408 | }
409 | #endif
410 |
411 | #endif
412 |
413 |
--------------------------------------------------------------------------------
/src/memcpy-armv7m.S:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 ARM Ltd
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | * 3. The name of the company may not be used to endorse or promote
14 | * products derived from this software without specific prior written
15 | * permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #if defined (__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__)
30 | /*
31 | * Let __ARM_FEATURE_UNALIGNED be set by the achitechture and the compiler flags:
32 | * -munaligned-access
33 | * -mno-unaligned-access
34 | * instead of always setting it here.
35 | *
36 | * #define __ARM_FEATURE_UNALIGNED 1
37 | */
38 |
39 | /* This memcpy routine is optimised for Cortex-M3/M4 cores with/without
40 | unaligned access.
41 |
42 | If compiled with GCC, this file should be enclosed within following
43 | pre-processing check:
44 | if defined (__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__)
45 |
46 | Prototype: void *memcpy (void *dst, const void *src, size_t count);
47 |
48 | The job will be done in 5 steps.
49 | Step 1: Align src/dest pointers, copy mis-aligned if fail to align both
50 | Step 2: Repeatedly copy big block size of __OPT_BIG_BLOCK_SIZE
51 | Step 3: Repeatedly copy big block size of __OPT_MID_BLOCK_SIZE
52 | Step 4: Copy word by word
53 | Step 5: Copy byte-to-byte
54 |
55 | Tunable options:
56 | __OPT_BIG_BLOCK_SIZE: Size of big block in words. Default to 64.
57 | __OPT_MID_BLOCK_SIZE: Size of big block in words. Default to 16.
58 | */
59 | #ifndef __OPT_BIG_BLOCK_SIZE
60 | #define __OPT_BIG_BLOCK_SIZE (4 * 16)
61 | #endif
62 |
63 | #ifndef __OPT_MID_BLOCK_SIZE
64 | #define __OPT_MID_BLOCK_SIZE (4 * 4)
65 | #endif
66 |
67 | #if __OPT_BIG_BLOCK_SIZE == 16
68 | #define BEGIN_UNROLL_BIG_BLOCK \
69 | .irp offset, 0,4,8,12
70 | #elif __OPT_BIG_BLOCK_SIZE == 32
71 | #define BEGIN_UNROLL_BIG_BLOCK \
72 | .irp offset, 0,4,8,12,16,20,24,28
73 | #elif __OPT_BIG_BLOCK_SIZE == 64
74 | #define BEGIN_UNROLL_BIG_BLOCK \
75 | .irp offset, 0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60
76 | #else
77 | #error "Illegal __OPT_BIG_BLOCK_SIZE"
78 | #endif
79 |
80 | #if __OPT_MID_BLOCK_SIZE == 8
81 | #define BEGIN_UNROLL_MID_BLOCK \
82 | .irp offset, 0,4
83 | #elif __OPT_MID_BLOCK_SIZE == 16
84 | #define BEGIN_UNROLL_MID_BLOCK \
85 | .irp offset, 0,4,8,12
86 | #else
87 | #error "Illegal __OPT_MID_BLOCK_SIZE"
88 | #endif
89 |
90 | #define END_UNROLL .endr
91 |
92 | .syntax unified
93 | .text
94 | .align 2
95 | .global memcpy
96 | .thumb
97 | .thumb_func
98 | .type memcpy, %function
99 | memcpy:
100 | @ r0: dst
101 | @ r1: src
102 | @ r2: len
103 | #ifdef __ARM_FEATURE_UNALIGNED
104 | /* In case of UNALIGNED access supported, ip is not used in
105 | function body. */
106 | mov ip, r0
107 | #else
108 | push {r0}
109 | #endif
110 | orr r3, r1, r0
111 | ands r3, r3, #3
112 | bne .Lmisaligned_copy
113 |
114 | .Lbig_block:
115 | subs r2, __OPT_BIG_BLOCK_SIZE
116 | blo .Lmid_block
117 |
118 | /* Kernel loop for big block copy */
119 | .align 2
120 | .Lbig_block_loop:
121 | BEGIN_UNROLL_BIG_BLOCK
122 | #ifdef __ARM_ARCH_7EM__
123 | ldr r3, [r1], #4
124 | str r3, [r0], #4
125 | END_UNROLL
126 | #else /* __ARM_ARCH_7M__ */
127 | ldr r3, [r1, \offset]
128 | str r3, [r0, \offset]
129 | END_UNROLL
130 | adds r0, __OPT_BIG_BLOCK_SIZE
131 | adds r1, __OPT_BIG_BLOCK_SIZE
132 | #endif
133 | subs r2, __OPT_BIG_BLOCK_SIZE
134 | bhs .Lbig_block_loop
135 |
136 | .Lmid_block:
137 | adds r2, __OPT_BIG_BLOCK_SIZE - __OPT_MID_BLOCK_SIZE
138 | blo .Lcopy_word_by_word
139 |
140 | /* Kernel loop for mid-block copy */
141 | .align 2
142 | .Lmid_block_loop:
143 | BEGIN_UNROLL_MID_BLOCK
144 | #ifdef __ARM_ARCH_7EM__
145 | ldr r3, [r1], #4
146 | str r3, [r0], #4
147 | END_UNROLL
148 | #else /* __ARM_ARCH_7M__ */
149 | ldr r3, [r1, \offset]
150 | str r3, [r0, \offset]
151 | END_UNROLL
152 | adds r0, __OPT_MID_BLOCK_SIZE
153 | adds r1, __OPT_MID_BLOCK_SIZE
154 | #endif
155 | subs r2, __OPT_MID_BLOCK_SIZE
156 | bhs .Lmid_block_loop
157 |
158 | .Lcopy_word_by_word:
159 | adds r2, __OPT_MID_BLOCK_SIZE - 4
160 | blo .Lcopy_less_than_4
161 |
162 | /* Kernel loop for small block copy */
163 | .align 2
164 | .Lcopy_word_by_word_loop:
165 | ldr r3, [r1], #4
166 | str r3, [r0], #4
167 | subs r2, #4
168 | bhs .Lcopy_word_by_word_loop
169 |
170 | .Lcopy_less_than_4:
171 | adds r2, #4
172 | beq .Ldone
173 |
174 | lsls r2, r2, #31
175 | itt ne
176 | ldrbne r3, [r1], #1
177 | strbne r3, [r0], #1
178 |
179 | bcc .Ldone
180 | #ifdef __ARM_FEATURE_UNALIGNED
181 | ldrh r3, [r1]
182 | strh r3, [r0]
183 | #else
184 | ldrb r3, [r1]
185 | strb r3, [r0]
186 | ldrb r3, [r1, #1]
187 | strb r3, [r0, #1]
188 | #endif /* __ARM_FEATURE_UNALIGNED */
189 |
190 | .Ldone:
191 | #ifdef __ARM_FEATURE_UNALIGNED
192 | mov r0, ip
193 | #else
194 | pop {r0}
195 | #endif
196 | bx lr
197 |
198 | .align 2
199 | .Lmisaligned_copy:
200 | #ifdef __ARM_FEATURE_UNALIGNED
201 | /* Define label DST_ALIGNED to BIG_BLOCK. It will go to aligned copy
202 | once destination is adjusted to aligned. */
203 | #define Ldst_aligned Lbig_block
204 |
205 | /* Copy word by word using LDR when alignment can be done in hardware,
206 | i.e., SCTLR.A is set, supporting unaligned access in LDR and STR. */
207 |
208 | cmp r2, #8
209 | blo .Lbyte_copy
210 |
211 | /* if src is aligned, just go to the big block loop. */
212 | lsls r3, r1, #30
213 | beq .Ldst_aligned
214 | #else
215 | /* if len < 12, misalignment adjustment has more overhead than
216 | just byte-to-byte copy. Also, len must >=8 to guarantee code
217 | afterward work correctly. */
218 | cmp r2, #12
219 | blo .Lbyte_copy
220 | #endif /* __ARM_FEATURE_UNALIGNED */
221 |
222 | /* Align dst only, not trying to align src. That is the because
223 | handling of aligned src and misaligned dst need more overhead than
224 | otherwise. By doing this the worst case is when initial src is aligned,
225 | additional up to 4 byte additional copy will executed, which is
226 | acceptable. */
227 |
228 | ands r3, r0, #3
229 | beq .Ldst_aligned
230 |
231 | rsb r3, #4
232 | subs r2, r3
233 |
234 | lsls r3, r3, #31
235 | itt ne
236 | ldrbne r3, [r1], #1
237 | strbne r3, [r0], #1
238 |
239 | bcc .Ldst_aligned
240 |
241 | #ifdef __ARM_FEATURE_UNALIGNED
242 | ldrh r3, [r1], #2
243 | strh r3, [r0], #2
244 | b .Ldst_aligned
245 | #else
246 | ldrb r3, [r1], #1
247 | strb r3, [r0], #1
248 | ldrb r3, [r1], #1
249 | strb r3, [r0], #1
250 | /* Now that dst is aligned */
251 | .Ldst_aligned:
252 | /* if r1 is aligned now, it means r0/r1 has the same misalignment,
253 | and they are both aligned now. Go aligned copy. */
254 | ands r3, r1, #3
255 | beq .Lbig_block
256 |
257 | /* dst is aligned, but src isn't. Misaligned copy. */
258 |
259 | push {r4, r5}
260 | subs r2, #4
261 |
262 | /* Backward r1 by misaligned bytes, to make r1 aligned.
263 | Since we need to restore r1 to unaligned address after the loop,
264 | we need keep the offset bytes to ip and sub it from r1 afterward. */
265 | subs r1, r3
266 | rsb ip, r3, #4
267 |
268 | /* Pre-load on word */
269 | ldr r4, [r1], #4
270 |
271 | cmp r3, #2
272 | beq .Lmisaligned_copy_2_2
273 | cmp r3, #3
274 | beq .Lmisaligned_copy_3_1
275 |
276 | .macro mis_src_copy shift
277 | 1:
278 | lsrs r4, r4, \shift
279 | ldr r3, [r1], #4
280 | lsls r5, r3, 32-\shift
281 | orr r4, r4, r5
282 | str r4, [r0], #4
283 | mov r4, r3
284 | subs r2, #4
285 | bhs 1b
286 | .endm
287 |
288 | .Lmisaligned_copy_1_3:
289 | mis_src_copy shift=8
290 | b .Lsrc_misaligned_tail
291 |
292 | .Lmisaligned_copy_3_1:
293 | mis_src_copy shift=24
294 | b .Lsrc_misaligned_tail
295 |
296 | .Lmisaligned_copy_2_2:
297 | /* For 2_2 misalignment, ldr is still faster than 2 x ldrh. */
298 | mis_src_copy shift=16
299 |
300 | .Lsrc_misaligned_tail:
301 | adds r2, #4
302 | subs r1, ip
303 | pop {r4, r5}
304 |
305 | #endif /* __ARM_FEATURE_UNALIGNED */
306 |
307 | .Lbyte_copy:
308 | subs r2, #4
309 | blo .Lcopy_less_than_4
310 |
311 | .Lbyte_copy_loop:
312 | subs r2, #1
313 | ldrb r3, [r1], #1
314 | strb r3, [r0], #1
315 | bhs .Lbyte_copy_loop
316 |
317 | ldrb r3, [r1]
318 | strb r3, [r0]
319 | ldrb r3, [r1, #1]
320 | strb r3, [r0, #1]
321 | ldrb r3, [r1, #2]
322 | strb r3, [r0, #2]
323 |
324 | #ifdef __ARM_FEATURE_UNALIGNED
325 | mov r0, ip
326 | #else
327 | pop {r0}
328 | #endif
329 | bx lr
330 |
331 | .size memcpy, .-memcpy
332 | #endif
333 |
--------------------------------------------------------------------------------
/src/memset.S:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014 Travis Geiselbrecht
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining
5 | * a copy of this software and associated documentation files
6 | * (the "Software"), to deal in the Software without restriction,
7 | * including without limitation the rights to use, copy, modify, merge,
8 | * publish, distribute, sublicense, and/or sell copies of the Software,
9 | * and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be
13 | * included in all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 | */
23 | //#include
24 | //#include
25 | #if defined (__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__)
26 | .global memset
27 | .text
28 | .syntax unified
29 | .thumb
30 | .align 2
31 |
32 | /* void *memset(void *s, int c, size_t n); */
33 | .type memset, %function
34 | .thumb_func
35 | memset:
36 | //FUNCTION(memset)
37 | // save the original pointer
38 | push { r0, lr }
39 |
40 | // check for zero length
41 | cbz r2, .L_done
42 |
43 | // short memsets aren't worth optimizing and make sure we have
44 | // enough headroom to try to do dwordwise move optimization
45 | cmp r2, #16
46 | blt .L_bytewise
47 |
48 | // see how many bytes we need to move to align to dword boundaries
49 | and r3, r0, #7
50 | cbz r3, .L_prepare_dwordwise
51 | rsb r3, #8
52 | subs r2, r3
53 |
54 | .L_bytewise_align:
55 | // bytewise to align memset
56 | subs r3, r3, #1
57 | strb r1, [r0], #1
58 | bgt .L_bytewise_align
59 |
60 | .L_prepare_dwordwise:
61 | // fill a pair of 32 bit registers with the 8 bit value
62 | uxtb r1, r1
63 | orr r1, r1, r1, lsl #8
64 | orr r1, r1, r1, lsl #16
65 | mov r12, r1
66 |
67 | // load the number of dwords left
68 | lsrs r3, r2, #3
69 |
70 | .L_dwordwise:
71 | // dwordwise memset
72 |
73 | subs r3, r3, #1
74 | strd r1, r12, [r0], #8
75 | bgt .L_dwordwise
76 |
77 | // remaining bytes
78 | ands r2, #7
79 | beq .L_done
80 |
81 | .L_bytewise:
82 | // bytewise memset
83 | subs r2, r2, #1
84 | strb r1, [r0], #1
85 | bgt .L_bytewise
86 |
87 | .L_done:
88 | // restore the base pointer as return value
89 | pop { r0, pc }
90 |
91 | #endif
92 |
--------------------------------------------------------------------------------
/src/mpu_prototypes.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeRTOS Kernel V10.2.0
3 | * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | *
22 | * http://www.FreeRTOS.org
23 | * http://aws.amazon.com/freertos
24 | *
25 | * 1 tab == 4 spaces!
26 | */
27 |
28 | /*
29 | * When the MPU is used the standard (non MPU) API functions are mapped to
30 | * equivalents that start "MPU_", the prototypes for which are defined in this
31 | * header files. This will cause the application code to call the MPU_ version
32 | * which wraps the non-MPU version with privilege promoting then demoting code,
33 | * so the kernel code always runs will full privileges.
34 | */
35 |
36 |
37 | #ifndef MPU_PROTOTYPES_H
38 | #define MPU_PROTOTYPES_H
39 |
40 | /* MPU versions of tasks.h API functions. */
41 | BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ) FREERTOS_SYSTEM_CALL;
42 | TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer ) FREERTOS_SYSTEM_CALL;
43 | BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) FREERTOS_SYSTEM_CALL;
44 | BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) FREERTOS_SYSTEM_CALL;
45 | void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ) FREERTOS_SYSTEM_CALL;
46 | void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ) FREERTOS_SYSTEM_CALL;
47 | void MPU_vTaskDelay( const TickType_t xTicksToDelay ) FREERTOS_SYSTEM_CALL;
48 | void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) FREERTOS_SYSTEM_CALL;
49 | BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
50 | UBaseType_t MPU_uxTaskPriorityGet( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
51 | eTaskState MPU_eTaskGetState( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
52 | void MPU_vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ) FREERTOS_SYSTEM_CALL;
53 | void MPU_vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) FREERTOS_SYSTEM_CALL;
54 | void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ) FREERTOS_SYSTEM_CALL;
55 | void MPU_vTaskResume( TaskHandle_t xTaskToResume ) FREERTOS_SYSTEM_CALL;
56 | void MPU_vTaskStartScheduler( void ) FREERTOS_SYSTEM_CALL;
57 | void MPU_vTaskSuspendAll( void ) FREERTOS_SYSTEM_CALL;
58 | BaseType_t MPU_xTaskResumeAll( void ) FREERTOS_SYSTEM_CALL;
59 | TickType_t MPU_xTaskGetTickCount( void ) FREERTOS_SYSTEM_CALL;
60 | UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) FREERTOS_SYSTEM_CALL;
61 | char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) FREERTOS_SYSTEM_CALL;
62 | TaskHandle_t MPU_xTaskGetHandle( const char *pcNameToQuery ) FREERTOS_SYSTEM_CALL;
63 | UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
64 | configSTACK_DEPTH_TYPE MPU_uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
65 | void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) FREERTOS_SYSTEM_CALL;
66 | TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
67 | void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) FREERTOS_SYSTEM_CALL;
68 | void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) FREERTOS_SYSTEM_CALL;
69 | BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) FREERTOS_SYSTEM_CALL;
70 | TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) FREERTOS_SYSTEM_CALL;
71 | UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL;
72 | TickType_t MPU_xTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL;
73 | void MPU_vTaskList( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL;
74 | void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer ) FREERTOS_SYSTEM_CALL;
75 | BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) FREERTOS_SYSTEM_CALL;
76 | BaseType_t MPU_xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
77 | uint32_t MPU_ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
78 | BaseType_t MPU_xTaskNotifyStateClear( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
79 | BaseType_t MPU_xTaskIncrementTick( void ) FREERTOS_SYSTEM_CALL;
80 | TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL;
81 | void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) FREERTOS_SYSTEM_CALL;
82 | BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) FREERTOS_SYSTEM_CALL;
83 | void MPU_vTaskMissedYield( void ) FREERTOS_SYSTEM_CALL;
84 | BaseType_t MPU_xTaskGetSchedulerState( void ) FREERTOS_SYSTEM_CALL;
85 |
86 | /* MPU versions of queue.h API functions. */
87 | BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) FREERTOS_SYSTEM_CALL;
88 | BaseType_t MPU_xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
89 | BaseType_t MPU_xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
90 | BaseType_t MPU_xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
91 | UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
92 | UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
93 | void MPU_vQueueDelete( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
94 | QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
95 | QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) FREERTOS_SYSTEM_CALL;
96 | QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) FREERTOS_SYSTEM_CALL;
97 | QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) FREERTOS_SYSTEM_CALL;
98 | TaskHandle_t MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) FREERTOS_SYSTEM_CALL;
99 | BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
100 | BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) FREERTOS_SYSTEM_CALL;
101 | void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcName ) FREERTOS_SYSTEM_CALL;
102 | void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
103 | const char * MPU_pcQueueGetName( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
104 | QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
105 | QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
106 | QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ) FREERTOS_SYSTEM_CALL;
107 | BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL;
108 | BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL;
109 | QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
110 | BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) FREERTOS_SYSTEM_CALL;
111 | void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) FREERTOS_SYSTEM_CALL;
112 | UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
113 | uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
114 |
115 | /* MPU versions of timers.h API functions. */
116 | TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) FREERTOS_SYSTEM_CALL;
117 | TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t *pxTimerBuffer ) FREERTOS_SYSTEM_CALL;
118 | void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
119 | void MPU_vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) FREERTOS_SYSTEM_CALL;
120 | BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
121 | TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) FREERTOS_SYSTEM_CALL;
122 | BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
123 | const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
124 | void MPU_vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ) FREERTOS_SYSTEM_CALL;
125 | TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
126 | TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
127 | BaseType_t MPU_xTimerCreateTimerTask( void ) FREERTOS_SYSTEM_CALL;
128 | BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
129 |
130 | /* MPU versions of event_group.h API functions. */
131 | EventGroupHandle_t MPU_xEventGroupCreate( void ) FREERTOS_SYSTEM_CALL;
132 | EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) FREERTOS_SYSTEM_CALL;
133 | EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
134 | EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) FREERTOS_SYSTEM_CALL;
135 | EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) FREERTOS_SYSTEM_CALL;
136 | EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
137 | void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ) FREERTOS_SYSTEM_CALL;
138 | UBaseType_t MPU_uxEventGroupGetNumber( void* xEventGroup ) FREERTOS_SYSTEM_CALL;
139 |
140 | /* MPU versions of message/stream_buffer.h API functions. */
141 | size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, const void *pvTxData, size_t xDataLengthBytes, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
142 | size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t xBufferLengthBytes, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
143 | size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
144 | void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
145 | BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
146 | BaseType_t MPU_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
147 | BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
148 | size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
149 | size_t MPU_xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
150 | BaseType_t MPU_xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel ) FREERTOS_SYSTEM_CALL;
151 | StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, BaseType_t xIsMessageBuffer ) FREERTOS_SYSTEM_CALL;
152 | StreamBufferHandle_t MPU_xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, BaseType_t xIsMessageBuffer, uint8_t * const pucStreamBufferStorageArea, StaticStreamBuffer_t * const pxStaticStreamBuffer ) FREERTOS_SYSTEM_CALL;
153 |
154 |
155 |
156 | #endif /* MPU_PROTOTYPES_H */
157 |
158 |
--------------------------------------------------------------------------------
/src/mpu_wrappers.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeRTOS Kernel V10.2.0
3 | * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | *
22 | * http://www.FreeRTOS.org
23 | * http://aws.amazon.com/freertos
24 | *
25 | * 1 tab == 4 spaces!
26 | */
27 |
28 | #ifndef MPU_WRAPPERS_H
29 | #define MPU_WRAPPERS_H
30 |
31 | /* This file redefines API functions to be called through a wrapper macro, but
32 | only for ports that are using the MPU. */
33 | #ifdef portUSING_MPU_WRAPPERS
34 |
35 | /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is
36 | included from queue.c or task.c to prevent it from having an effect within
37 | those files. */
38 | #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
39 |
40 | /*
41 | * Map standard (non MPU) API functions to equivalents that start
42 | * "MPU_". This will cause the application code to call the MPU_
43 | * version, which wraps the non-MPU version with privilege promoting
44 | * then demoting code, so the kernel code always runs will full
45 | * privileges.
46 | */
47 |
48 | /* Map standard tasks.h API functions to the MPU equivalents. */
49 | #define xTaskCreate MPU_xTaskCreate
50 | #define xTaskCreateStatic MPU_xTaskCreateStatic
51 | #define xTaskCreateRestricted MPU_xTaskCreateRestricted
52 | #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions
53 | #define vTaskDelete MPU_vTaskDelete
54 | #define vTaskDelay MPU_vTaskDelay
55 | #define vTaskDelayUntil MPU_vTaskDelayUntil
56 | #define xTaskAbortDelay MPU_xTaskAbortDelay
57 | #define uxTaskPriorityGet MPU_uxTaskPriorityGet
58 | #define eTaskGetState MPU_eTaskGetState
59 | #define vTaskGetInfo MPU_vTaskGetInfo
60 | #define vTaskPrioritySet MPU_vTaskPrioritySet
61 | #define vTaskSuspend MPU_vTaskSuspend
62 | #define vTaskResume MPU_vTaskResume
63 | #define vTaskSuspendAll MPU_vTaskSuspendAll
64 | #define xTaskResumeAll MPU_xTaskResumeAll
65 | #define xTaskGetTickCount MPU_xTaskGetTickCount
66 | #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks
67 | #define pcTaskGetName MPU_pcTaskGetName
68 | #define xTaskGetHandle MPU_xTaskGetHandle
69 | #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark
70 | #define uxTaskGetStackHighWaterMark2 MPU_uxTaskGetStackHighWaterMark2
71 | #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag
72 | #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag
73 | #define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer
74 | #define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer
75 | #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook
76 | #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle
77 | #define uxTaskGetSystemState MPU_uxTaskGetSystemState
78 | #define vTaskList MPU_vTaskList
79 | #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats
80 | #define xTaskGetIdleRunTimeCounter MPU_xTaskGetIdleRunTimeCounter
81 | #define xTaskGenericNotify MPU_xTaskGenericNotify
82 | #define xTaskNotifyWait MPU_xTaskNotifyWait
83 | #define ulTaskNotifyTake MPU_ulTaskNotifyTake
84 | #define xTaskNotifyStateClear MPU_xTaskNotifyStateClear
85 |
86 | #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
87 | #define vTaskSetTimeOutState MPU_vTaskSetTimeOutState
88 | #define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut
89 | #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState
90 |
91 | /* Map standard queue.h API functions to the MPU equivalents. */
92 | #define xQueueGenericSend MPU_xQueueGenericSend
93 | #define xQueueReceive MPU_xQueueReceive
94 | #define xQueuePeek MPU_xQueuePeek
95 | #define xQueueSemaphoreTake MPU_xQueueSemaphoreTake
96 | #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting
97 | #define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable
98 | #define vQueueDelete MPU_vQueueDelete
99 | #define xQueueCreateMutex MPU_xQueueCreateMutex
100 | #define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic
101 | #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore
102 | #define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic
103 | #define xQueueGetMutexHolder MPU_xQueueGetMutexHolder
104 | #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive
105 | #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive
106 | #define xQueueGenericCreate MPU_xQueueGenericCreate
107 | #define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic
108 | #define xQueueCreateSet MPU_xQueueCreateSet
109 | #define xQueueAddToSet MPU_xQueueAddToSet
110 | #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet
111 | #define xQueueSelectFromSet MPU_xQueueSelectFromSet
112 | #define xQueueGenericReset MPU_xQueueGenericReset
113 |
114 | #if( configQUEUE_REGISTRY_SIZE > 0 )
115 | #define vQueueAddToRegistry MPU_vQueueAddToRegistry
116 | #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue
117 | #define pcQueueGetName MPU_pcQueueGetName
118 | #endif
119 |
120 | /* Map standard timer.h API functions to the MPU equivalents. */
121 | #define xTimerCreate MPU_xTimerCreate
122 | #define xTimerCreateStatic MPU_xTimerCreateStatic
123 | #define pvTimerGetTimerID MPU_pvTimerGetTimerID
124 | #define vTimerSetTimerID MPU_vTimerSetTimerID
125 | #define xTimerIsTimerActive MPU_xTimerIsTimerActive
126 | #define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle
127 | #define xTimerPendFunctionCall MPU_xTimerPendFunctionCall
128 | #define pcTimerGetName MPU_pcTimerGetName
129 | #define vTimerSetReloadMode MPU_vTimerSetReloadMode
130 | #define xTimerGetPeriod MPU_xTimerGetPeriod
131 | #define xTimerGetExpiryTime MPU_xTimerGetExpiryTime
132 | #define xTimerGenericCommand MPU_xTimerGenericCommand
133 |
134 | /* Map standard event_group.h API functions to the MPU equivalents. */
135 | #define xEventGroupCreate MPU_xEventGroupCreate
136 | #define xEventGroupCreateStatic MPU_xEventGroupCreateStatic
137 | #define xEventGroupWaitBits MPU_xEventGroupWaitBits
138 | #define xEventGroupClearBits MPU_xEventGroupClearBits
139 | #define xEventGroupSetBits MPU_xEventGroupSetBits
140 | #define xEventGroupSync MPU_xEventGroupSync
141 | #define vEventGroupDelete MPU_vEventGroupDelete
142 |
143 | /* Map standard message/stream_buffer.h API functions to the MPU
144 | equivalents. */
145 | #define xStreamBufferSend MPU_xStreamBufferSend
146 | #define xStreamBufferReceive MPU_xStreamBufferReceive
147 | #define xStreamBufferNextMessageLengthBytes MPU_xStreamBufferNextMessageLengthBytes
148 | #define vStreamBufferDelete MPU_vStreamBufferDelete
149 | #define xStreamBufferIsFull MPU_xStreamBufferIsFull
150 | #define xStreamBufferIsEmpty MPU_xStreamBufferIsEmpty
151 | #define xStreamBufferReset MPU_xStreamBufferReset
152 | #define xStreamBufferSpacesAvailable MPU_xStreamBufferSpacesAvailable
153 | #define xStreamBufferBytesAvailable MPU_xStreamBufferBytesAvailable
154 | #define xStreamBufferSetTriggerLevel MPU_xStreamBufferSetTriggerLevel
155 | #define xStreamBufferGenericCreate MPU_xStreamBufferGenericCreate
156 | #define xStreamBufferGenericCreateStatic MPU_xStreamBufferGenericCreateStatic
157 |
158 |
159 | /* Remove the privileged function macro, but keep the PRIVILEGED_DATA
160 | macro so applications can place data in privileged access sections
161 | (useful when using statically allocated objects). */
162 | #define PRIVILEGED_FUNCTION
163 | #define PRIVILEGED_DATA __attribute__((section("privileged_data")))
164 | #define FREERTOS_SYSTEM_CALL
165 |
166 | #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
167 |
168 | /* Ensure API functions go in the privileged execution section. */
169 | #define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions")))
170 | #define PRIVILEGED_DATA __attribute__((section("privileged_data")))
171 | #define FREERTOS_SYSTEM_CALL __attribute__((section( "freertos_system_calls")))
172 |
173 | #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
174 |
175 | #else /* portUSING_MPU_WRAPPERS */
176 |
177 | #define PRIVILEGED_FUNCTION
178 | #define PRIVILEGED_DATA
179 | #define FREERTOS_SYSTEM_CALL
180 | #define portUSING_MPU_WRAPPERS 0
181 |
182 | #endif /* portUSING_MPU_WRAPPERS */
183 |
184 |
185 | #endif /* MPU_WRAPPERS_H */
186 |
187 |
--------------------------------------------------------------------------------
/src/portable.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeRTOS Kernel V10.2.0
3 | * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | *
22 | * http://www.FreeRTOS.org
23 | * http://aws.amazon.com/freertos
24 | *
25 | * 1 tab == 4 spaces!
26 | */
27 |
28 | /*-----------------------------------------------------------
29 | * Portable layer API. Each function must be defined for each port.
30 | *----------------------------------------------------------*/
31 |
32 | #ifndef PORTABLE_H
33 | #define PORTABLE_H
34 |
35 | /* Each FreeRTOS port has a unique portmacro.h header file. Originally a
36 | pre-processor definition was used to ensure the pre-processor found the correct
37 | portmacro.h file for the port being used. That scheme was deprecated in favour
38 | of setting the compiler's include path such that it found the correct
39 | portmacro.h file - removing the need for the constant and allowing the
40 | portmacro.h file to be located anywhere in relation to the port being used.
41 | Purely for reasons of backward compatibility the old method is still valid, but
42 | to make it clear that new projects should not use it, support for the port
43 | specific constants has been moved into the deprecated_definitions.h header
44 | file. */
45 | #include "deprecated_definitions.h"
46 |
47 | /* If portENTER_CRITICAL is not defined then including deprecated_definitions.h
48 | did not result in a portmacro.h header file being included - and it should be
49 | included here. In this case the path to the correct portmacro.h header file
50 | must be set in the compiler's include path. */
51 | #ifndef portENTER_CRITICAL
52 | #include "portmacro.h"
53 | #endif
54 |
55 | #if portBYTE_ALIGNMENT == 32
56 | #define portBYTE_ALIGNMENT_MASK ( 0x001f )
57 | #endif
58 |
59 | #if portBYTE_ALIGNMENT == 16
60 | #define portBYTE_ALIGNMENT_MASK ( 0x000f )
61 | #endif
62 |
63 | #if portBYTE_ALIGNMENT == 8
64 | #define portBYTE_ALIGNMENT_MASK ( 0x0007 )
65 | #endif
66 |
67 | #if portBYTE_ALIGNMENT == 4
68 | #define portBYTE_ALIGNMENT_MASK ( 0x0003 )
69 | #endif
70 |
71 | #if portBYTE_ALIGNMENT == 2
72 | #define portBYTE_ALIGNMENT_MASK ( 0x0001 )
73 | #endif
74 |
75 | #if portBYTE_ALIGNMENT == 1
76 | #define portBYTE_ALIGNMENT_MASK ( 0x0000 )
77 | #endif
78 |
79 | #ifndef portBYTE_ALIGNMENT_MASK
80 | #error "Invalid portBYTE_ALIGNMENT definition"
81 | #endif
82 |
83 | #ifndef portNUM_CONFIGURABLE_REGIONS
84 | #define portNUM_CONFIGURABLE_REGIONS 1
85 | #endif
86 |
87 | #ifndef portHAS_STACK_OVERFLOW_CHECKING
88 | #define portHAS_STACK_OVERFLOW_CHECKING 0
89 | #endif
90 |
91 | #ifndef portARCH_NAME
92 | #define portARCH_NAME NULL
93 | #endif
94 |
95 | #ifdef __cplusplus
96 | extern "C" {
97 | #endif
98 |
99 | #include "mpu_wrappers.h"
100 |
101 | /*
102 | * Setup the stack of a new task so it is ready to be placed under the
103 | * scheduler control. The registers have to be placed on the stack in
104 | * the order that the port expects to find them.
105 | *
106 | */
107 | #if( portUSING_MPU_WRAPPERS == 1 )
108 | #if( portHAS_STACK_OVERFLOW_CHECKING == 1 )
109 | StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
110 | #else
111 | StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
112 | #endif
113 | #else
114 | #if( portHAS_STACK_OVERFLOW_CHECKING == 1 )
115 | StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION;
116 | #else
117 | StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION;
118 | #endif
119 | #endif
120 |
121 | /* Used by heap_5.c. */
122 | typedef struct HeapRegion
123 | {
124 | uint8_t *pucStartAddress;
125 | size_t xSizeInBytes;
126 | } HeapRegion_t;
127 |
128 | /*
129 | * Used to define multiple heap regions for use by heap_5.c. This function
130 | * must be called before any calls to pvPortMalloc() - not creating a task,
131 | * queue, semaphore, mutex, software timer, event group, etc. will result in
132 | * pvPortMalloc being called.
133 | *
134 | * pxHeapRegions passes in an array of HeapRegion_t structures - each of which
135 | * defines a region of memory that can be used as the heap. The array is
136 | * terminated by a HeapRegions_t structure that has a size of 0. The region
137 | * with the lowest start address must appear first in the array.
138 | */
139 | void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION;
140 |
141 |
142 | /*
143 | * Map to the memory management routines required for the port.
144 | */
145 | void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION;
146 | void vPortFree( void *pv ) PRIVILEGED_FUNCTION;
147 | void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
148 | size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
149 | size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
150 |
151 | /*
152 | * Setup the hardware ready for the scheduler to take control. This generally
153 | * sets up a tick interrupt and sets timers for the correct tick frequency.
154 | */
155 | BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION;
156 |
157 | /*
158 | * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so
159 | * the hardware is left in its original condition after the scheduler stops
160 | * executing.
161 | */
162 | void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
163 |
164 | /*
165 | * The structures and methods of manipulating the MPU are contained within the
166 | * port layer.
167 | *
168 | * Fills the xMPUSettings structure with the memory region information
169 | * contained in xRegions.
170 | */
171 | #if( portUSING_MPU_WRAPPERS == 1 )
172 | struct xMEMORY_REGION;
173 | void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) PRIVILEGED_FUNCTION;
174 | #endif
175 |
176 | #ifdef __cplusplus
177 | }
178 | #endif
179 |
180 | #endif /* PORTABLE_H */
181 |
182 |
--------------------------------------------------------------------------------
/src/portmacro.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeRTOS Kernel V10.2.0
3 | * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | *
22 | * http://www.FreeRTOS.org
23 | * http://aws.amazon.com/freertos
24 | *
25 | * 1 tab == 4 spaces!
26 | */
27 |
28 |
29 | #ifndef PORTMACRO_H
30 | #define PORTMACRO_H
31 |
32 | #ifdef __cplusplus
33 | extern "C" {
34 | #endif
35 |
36 | /*-----------------------------------------------------------
37 | * Port specific definitions.
38 | *
39 | * The settings in this file configure FreeRTOS correctly for the
40 | * given hardware and compiler.
41 | *
42 | * These settings should not be altered.
43 | *-----------------------------------------------------------
44 | */
45 |
46 | /* Type definitions. */
47 | #define portCHAR char
48 | #define portFLOAT float
49 | #define portDOUBLE double
50 | #define portLONG long
51 | #define portSHORT short
52 | #define portSTACK_TYPE uint32_t
53 | #define portBASE_TYPE long
54 |
55 | typedef portSTACK_TYPE StackType_t;
56 | typedef long BaseType_t;
57 | typedef unsigned long UBaseType_t;
58 |
59 | #if( configUSE_16_BIT_TICKS == 1 )
60 | typedef uint16_t TickType_t;
61 | #define portMAX_DELAY ( TickType_t ) 0xffff
62 | #else
63 | typedef uint32_t TickType_t;
64 | #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
65 |
66 | /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
67 | not need to be guarded with a critical section. */
68 | #define portTICK_TYPE_IS_ATOMIC 1
69 | #endif
70 | /*-----------------------------------------------------------*/
71 |
72 | /* Architecture specifics. */
73 | #define portSTACK_GROWTH ( -1 )
74 | #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
75 | #define portBYTE_ALIGNMENT 4
76 | /*-----------------------------------------------------------*/
77 |
78 | /* Scheduler utilities. */
79 | #define portYIELD() \
80 | { \
81 | /* Set a PendSV to request a context switch. */ \
82 | portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
83 | \
84 | /* Barriers are normally not required but do ensure the code is completely \
85 | within the specified behaviour for the architecture. */ \
86 | __asm volatile( "dsb" ::: "memory" ); \
87 | __asm volatile( "isb" ); \
88 | }
89 |
90 | #define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
91 | #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
92 | #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
93 | #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
94 | /*-----------------------------------------------------------*/
95 |
96 | /* Critical section management. */
97 | extern void vPortEnterCritical( void );
98 | extern void vPortExitCritical( void );
99 | #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
100 | #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
101 | #define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
102 | #define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
103 | #define portENTER_CRITICAL() vPortEnterCritical()
104 | #define portEXIT_CRITICAL() vPortExitCritical()
105 |
106 |
107 | /*-----------------------------------------------------------*/
108 |
109 | /* Task function macros as described on the FreeRTOS.org WEB site. These are
110 | not necessary for to use this port. They are defined so the common demo files
111 | (which build with all the ports) will build. */
112 | #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
113 | #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
114 | /*-----------------------------------------------------------*/
115 |
116 | /* Tickless idle/low power functionality. */
117 | #ifndef portSUPPRESS_TICKS_AND_SLEEP
118 | extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
119 | #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
120 | #endif
121 | /*-----------------------------------------------------------*/
122 |
123 | /* Architecture specific optimisations. */
124 | #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
125 | #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
126 | #endif
127 |
128 | #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
129 |
130 | /* Generic helper function. */
131 | __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
132 | {
133 | uint8_t ucReturn;
134 |
135 | __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
136 | return ucReturn;
137 | }
138 |
139 | /* Check the configuration. */
140 | #if( configMAX_PRIORITIES > 32 )
141 | #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
142 | #endif
143 |
144 | /* Store/clear the ready priorities in a bit map. */
145 | #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
146 | #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
147 |
148 | /*-----------------------------------------------------------*/
149 |
150 | #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
151 |
152 | #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
153 |
154 | /*-----------------------------------------------------------*/
155 |
156 | #ifdef configASSERT
157 | void vPortValidateInterruptPriority( void );
158 | #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
159 | #endif
160 |
161 | /* portNOP() is not required by this port. */
162 | #define portNOP()
163 |
164 | #define portINLINE __inline
165 |
166 | #ifndef portFORCE_INLINE
167 | #define portFORCE_INLINE inline __attribute__(( always_inline))
168 | #endif
169 |
170 | portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
171 | {
172 | uint32_t ulCurrentInterrupt;
173 | BaseType_t xReturn;
174 |
175 | /* Obtain the number of the currently executing interrupt. */
176 | __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
177 |
178 | if( ulCurrentInterrupt == 0 )
179 | {
180 | xReturn = pdFALSE;
181 | }
182 | else
183 | {
184 | xReturn = pdTRUE;
185 | }
186 |
187 | return xReturn;
188 | }
189 |
190 | /*-----------------------------------------------------------*/
191 |
192 | portFORCE_INLINE static void vPortRaiseBASEPRI( void )
193 | {
194 | uint32_t ulNewBASEPRI;
195 |
196 | __asm volatile
197 | (
198 | " mov %0, %1 \n" \
199 | " msr basepri, %0 \n" \
200 | " isb \n" \
201 | " dsb \n" \
202 | :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
203 | );
204 | }
205 |
206 | /*-----------------------------------------------------------*/
207 |
208 | portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
209 | {
210 | uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
211 |
212 | __asm volatile
213 | (
214 | " mrs %0, basepri \n" \
215 | " mov %1, %2 \n" \
216 | " msr basepri, %1 \n" \
217 | " isb \n" \
218 | " dsb \n" \
219 | :"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
220 | );
221 |
222 | /* This return will not be reached but is necessary to prevent compiler
223 | warnings. */
224 | return ulOriginalBASEPRI;
225 | }
226 | /*-----------------------------------------------------------*/
227 |
228 | portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
229 | {
230 | __asm volatile
231 | (
232 | " msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory"
233 | );
234 | }
235 | /*-----------------------------------------------------------*/
236 |
237 |
238 | #ifdef __cplusplus
239 | }
240 | #endif
241 |
242 | #endif /* PORTMACRO_H */
243 |
244 |
--------------------------------------------------------------------------------
/src/projdefs.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeRTOS Kernel V10.2.0
3 | * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | *
22 | * http://www.FreeRTOS.org
23 | * http://aws.amazon.com/freertos
24 | *
25 | * 1 tab == 4 spaces!
26 | */
27 |
28 | #ifndef PROJDEFS_H
29 | #define PROJDEFS_H
30 |
31 | /*
32 | * Defines the prototype to which task functions must conform. Defined in this
33 | * file to ensure the type is known before portable.h is included.
34 | */
35 | typedef void (*TaskFunction_t)( void * );
36 |
37 | /* Converts a time in milliseconds to a time in ticks. This macro can be
38 | overridden by a macro of the same name defined in FreeRTOSConfig.h in case the
39 | definition here is not suitable for your application. */
40 | #ifndef pdMS_TO_TICKS
41 | #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) )
42 | #endif
43 |
44 | #define pdFALSE ( ( BaseType_t ) 0 )
45 | #define pdTRUE ( ( BaseType_t ) 1 )
46 |
47 | #define pdPASS ( pdTRUE )
48 | #define pdFAIL ( pdFALSE )
49 | #define errQUEUE_EMPTY ( ( BaseType_t ) 0 )
50 | #define errQUEUE_FULL ( ( BaseType_t ) 0 )
51 |
52 | /* FreeRTOS error definitions. */
53 | #define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 )
54 | #define errQUEUE_BLOCKED ( -4 )
55 | #define errQUEUE_YIELD ( -5 )
56 |
57 | /* Macros used for basic data corruption checks. */
58 | #ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES
59 | #define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0
60 | #endif
61 |
62 | #if( configUSE_16_BIT_TICKS == 1 )
63 | #define pdINTEGRITY_CHECK_VALUE 0x5a5a
64 | #else
65 | #define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL
66 | #endif
67 |
68 | /* The following errno values are used by FreeRTOS+ components, not FreeRTOS
69 | itself. */
70 | #define pdFREERTOS_ERRNO_NONE 0 /* No errors */
71 | #define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */
72 | #define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */
73 | #define pdFREERTOS_ERRNO_EIO 5 /* I/O error */
74 | #define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */
75 | #define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */
76 | #define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */
77 | #define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */
78 | #define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */
79 | #define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */
80 | #define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */
81 | #define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */
82 | #define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */
83 | #define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */
84 | #define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */
85 | #define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */
86 | #define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */
87 | #define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */
88 | #define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */
89 | #define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */
90 | #define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */
91 | #define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */
92 | #define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */
93 | #define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */
94 | #define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */
95 | #define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */
96 | #define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */
97 | #define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
98 | #define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */
99 | #define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */
100 | #define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */
101 | #define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */
102 | #define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */
103 | #define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */
104 | #define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */
105 | #define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */
106 | #define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */
107 | #define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */
108 | #define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */
109 | #define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */
110 |
111 | /* The following endian values are used by FreeRTOS+ components, not FreeRTOS
112 | itself. */
113 | #define pdFREERTOS_LITTLE_ENDIAN 0
114 | #define pdFREERTOS_BIG_ENDIAN 1
115 |
116 | /* Re-defining endian values for generic naming. */
117 | #define pdLITTLE_ENDIAN pdFREERTOS_LITTLE_ENDIAN
118 | #define pdBIG_ENDIAN pdFREERTOS_BIG_ENDIAN
119 |
120 |
121 | #endif /* PROJDEFS_H */
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/src/stack_macros.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeRTOS Kernel V10.2.0
3 | * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | *
22 | * http://www.FreeRTOS.org
23 | * http://aws.amazon.com/freertos
24 | *
25 | * 1 tab == 4 spaces!
26 | */
27 |
28 | #ifndef STACK_MACROS_H
29 | #define STACK_MACROS_H
30 |
31 | /*
32 | * Call the stack overflow hook function if the stack of the task being swapped
33 | * out is currently overflowed, or looks like it might have overflowed in the
34 | * past.
35 | *
36 | * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
37 | * the current stack state only - comparing the current top of stack value to
38 | * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
39 | * will also cause the last few stack bytes to be checked to ensure the value
40 | * to which the bytes were set when the task was created have not been
41 | * overwritten. Note this second test does not guarantee that an overflowed
42 | * stack will always be recognised.
43 | */
44 |
45 | /*-----------------------------------------------------------*/
46 |
47 | #if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) )
48 |
49 | /* Only the current stack state is to be checked. */
50 | #define taskCHECK_FOR_STACK_OVERFLOW() \
51 | { \
52 | /* Is the currently saved stack pointer within the stack limit? */ \
53 | if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \
54 | { \
55 | vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
56 | } \
57 | }
58 |
59 | #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
60 | /*-----------------------------------------------------------*/
61 |
62 | #if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) )
63 |
64 | /* Only the current stack state is to be checked. */
65 | #define taskCHECK_FOR_STACK_OVERFLOW() \
66 | { \
67 | \
68 | /* Is the currently saved stack pointer within the stack limit? */ \
69 | if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \
70 | { \
71 | vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
72 | } \
73 | }
74 |
75 | #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
76 | /*-----------------------------------------------------------*/
77 |
78 | #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
79 |
80 | #define taskCHECK_FOR_STACK_OVERFLOW() \
81 | { \
82 | const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
83 | const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \
84 | \
85 | if( ( pulStack[ 0 ] != ulCheckValue ) || \
86 | ( pulStack[ 1 ] != ulCheckValue ) || \
87 | ( pulStack[ 2 ] != ulCheckValue ) || \
88 | ( pulStack[ 3 ] != ulCheckValue ) ) \
89 | { \
90 | vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
91 | } \
92 | }
93 |
94 | #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
95 | /*-----------------------------------------------------------*/
96 |
97 | #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
98 |
99 | #define taskCHECK_FOR_STACK_OVERFLOW() \
100 | { \
101 | int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
102 | static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
103 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
104 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
105 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
106 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
107 | \
108 | \
109 | pcEndOfStack -= sizeof( ucExpectedStackBytes ); \
110 | \
111 | /* Has the extremity of the task stack ever been written over? */ \
112 | if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
113 | { \
114 | vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
115 | } \
116 | }
117 |
118 | #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
119 | /*-----------------------------------------------------------*/
120 |
121 | /* Remove stack overflow macro if not being used. */
122 | #ifndef taskCHECK_FOR_STACK_OVERFLOW
123 | #define taskCHECK_FOR_STACK_OVERFLOW()
124 | #endif
125 |
126 |
127 |
128 | #endif /* STACK_MACROS_H */
129 |
130 |
--------------------------------------------------------------------------------
/src/threading_alt.h:
--------------------------------------------------------------------------------
1 | #ifndef __THREADING_ALT_H__
2 | #define __THREADING_ALT_H__
3 |
4 |
5 | #include "FreeRTOS.h"
6 | #include "semphr.h"
7 |
8 | typedef struct
9 | {
10 | SemaphoreHandle_t mutex;
11 | char is_valid;
12 | } mbedtls_threading_mutex_t;
13 |
14 | extern void mbedtls_threading_set_alt( void ( * mutex_init )( mbedtls_threading_mutex_t * ),
15 | void ( * mutex_free )( mbedtls_threading_mutex_t * ),
16 | int ( * mutex_lock )( mbedtls_threading_mutex_t * ),
17 | int ( * mutex_unlock )( mbedtls_threading_mutex_t * ) );
18 |
19 |
20 | #endif /* ifndef __THREADING_ALT_H__ */
21 |
--------------------------------------------------------------------------------