1 /*
2  * FreeRTOS Kernel V11.1.0
3  * Copyright (C) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28 
29 #ifndef PORTMACRO_H
30 #define PORTMACRO_H
31 
32 /**
33  * @brief Functions, Defines, and Structs for use in the ARM_CRx_MPU FreeRTOS-Port
34  * @file portmacro.h
35  * @note The settings in this file configure FreeRTOS correctly for the given
36  *  hardware and compiler. These settings should not be altered.
37  */
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 /* Include stdint for integer types of specific bit widths. */
44 #include <stdint.h>
45 
46 /* ------------------------------ FreeRTOS Config Check ------------------------------ */
47 
48 #ifndef configSYSTEM_CALL_STACK_SIZE
49     #error "Define configSYSTEM_CALL_STACK_SIZE to a length, in bytes, " \
50             "to use when an unprivileged task makes a FreeRTOS Kernel call. "
51 #endif /* configSYSTEM_CALL_STACK_SIZE */
52 
53 #if( configUSE_MPU_WRAPPERS_V1 == 1 )
54     #error This port is usable with MPU wrappers V2 only.
55 #endif /* configUSE_MPU_WRAPPERS_V1 */
56 
57 #ifndef configSETUP_TICK_INTERRUPT
58     #error "configSETUP_TICK_INTERRUPT() must be defined in FreeRTOSConfig.h " \
59            "to call the function that sets up the tick interrupt."
60 #endif /* configSETUP_TICK_INTERRUPT */
61 
62 /* ----------------------------------------------------------------------------------- */
63 
64 #if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
65 
66     /* Check the configuration. */
67     #if( configMAX_PRIORITIES > 32 )
68         #error "configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when " \
69                 "configMAX_PRIORITIES is less than or equal to 32. " \
70                 "It is very rare that a system requires more than 10 to 15 difference " \
71                 "priorities as tasks that share a priority will time slice."
72     #endif /* ( configMAX_PRIORITIES > 32 ) */
73 
74     /**
75      * @brief Mark that a task of the given priority is ready.
76      *
77      * @ingroup Scheduler
78      *
79      * @param[in] uxPriority Priority of the task that is ready.
80      * @param[in] uxTopReadyPriority Bitmap of the ready tasks priorities.
81      */
82     #define portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority ) \
83         ( uxTopReadyPriority ) |= ( 1UL << ( uxPriority ) )
84 
85     /**
86      * @brief Mark that a task of the given priority is no longer ready.
87      *
88      * @ingroup Scheduler
89      *
90      * @param[in] uxPriority Priority of the task that is no longer ready.
91      * @param[in] uxTopReadyPriority Bitmap of the ready tasks priorities.
92      */
93     #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority ) \
94         ( uxTopReadyPriority ) &= ~( 1UL << ( uxPriority ) )
95 
96     /**
97      * @brief Determine the highest priority ready task's priority.
98      *
99      * @ingroup Scheduler
100      *
101      * @param[in] uxTopReadyPriority Bitmap of the ready tasks priorities.
102      * @param[in] uxTopPriority The highest priority ready task's priority.
103      */
104     #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ) \
105         ( uxTopPriority ) = ( 31UL - ulPortCountLeadingZeros( ( uxTopReadyPriority ) ) )
106 
107 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
108 
109 /* ------------------------------ Port Type Definitions ------------------------------ */
110 
111 #include "portmacro_asm.h"
112 
113 /**
114  * @brief Critical section nesting value.
115  *
116  * @ingroup Critical Sections
117  *
118  * @note A task exits critical section and enables IRQs when its nesting count
119  * reaches this value.
120  */
121 #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0x0 )
122 
123 /**
124  * @brief Bit in Current Program Status Register (CPSR) to indicate that CPU is
125  * in Thumb State.
126  *
127  * @ingroup Task Context
128  */
129 #define portTHUMB_MODE_BIT      ( ( StackType_t ) 0x20 )
130 
131 /**
132  * @brief Bitmask to check if an address is of Thumb Code.
133  *
134  * @ingroup Task Context
135  */
136 #define portTHUMB_MODE_ADDRESS  ( 0x01UL )
137 
138 /**
139  * @brief Data type used to represent a stack word.
140  *
141  * @ingroup Port Interface Specifications
142  */
143 typedef uint32_t StackType_t;
144 
145 /**
146  * @brief Signed data type equal to the data word operating size of the CPU.
147  *
148  * @ingroup Port Interface Specifications
149  */
150 typedef int32_t BaseType_t;
151 
152 /**
153  * @brief Unsigned data type equal to the data word operating size of the CPU.
154  *
155  * @ingroup Port Interface Specifications
156  */
157 typedef uint32_t UBaseType_t;
158 
159 /**
160  * @brief Data type used for the FreeRTOS Tick Counter.
161  *
162  * @note Using 32-bit tick type on a 32-bit architecture ensures that reads of
163  * the tick count do not need to be guarded with a critical section.
164  */
165 typedef uint32_t TickType_t;
166 
167 /**
168  * @brief Marks the direction the stack grows on the targeted CPU.
169  *
170  * @ingroup Port Interface Specifications
171  */
172 #define portSTACK_GROWTH   ( -1 )
173 
174 /**
175  * @brief Specifies stack pointer alignment requirements of the target CPU.
176  *
177  * @ingroup Port Interface Specifications
178  */
179 #define portBYTE_ALIGNMENT 8U
180 
181 /**
182  * @brief Task function prototype macro as described on FreeRTOS.org.
183  *
184  * @ingroup Port Interface Specifications
185  *
186  * @note This is not required for this port but included in case common demo
187  * code uses it.
188  */
189 #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) \
190     void vFunction( void * pvParameters )
191 
192 /**
193  * @brief Task function prototype macro as described on FreeRTOS.org.
194  *
195  * @ingroup Port Interface Specifications
196  *
197  * @note This is not required for this port but included in case common demo
198  * code uses it.
199  */
200 #define portTASK_FUNCTION( vFunction, pvParameters ) \
201     void vFunction( void * pvParameters )
202 
203 /**
204  * @brief The no-op ARM assembly instruction.
205  *
206  * @ingroup Port Interface Specifications
207  */
208 #define portNOP()                                    __asm volatile( "NOP" )
209 
210 /**
211  * @brief The inline GCC label.
212  *
213  * @ingroup Port Interface Specifications
214  */
215 #define portINLINE                                   __inline
216 
217 /**
218  * @brief The memory access synchronization barrier.
219  *
220  * @ingroup Port Interface Specifications
221  */
222 #define portMEMORY_BARRIER()                         __asm volatile( "" ::: "memory" )
223 
224 /**
225  * @brief Ensure a symbol isn't removed from the compilation unit.
226  *
227  * @ingroup Port Interface Specifications
228  */
229 #define portDONT_DISCARD                             __attribute__( ( used ) )
230 
231 /**
232  * @brief Defines if the tick count can be accessed atomically.
233  *
234  * @ingroup System Clock
235  */
236 #define portTICK_TYPE_IS_ATOMIC                      1
237 
238 /**
239  * @brief The number of miliseconds between system ticks.
240  *
241  * @ingroup System Clock
242  */
243 #define portTICK_PERIOD_MS                           ( ( TickType_t ) 1000UL / configTICK_RATE_HZ )
244 
245 /**
246  * @brief The largest possible delay value for any FreeRTOS API.
247  *
248  * @ingroup System Clock
249  */
250 #define portMAX_DELAY                                ( TickType_t ) 0xFFFFFFFFUL
251 
252 /* ----------------------------- Port Assembly Functions ----------------------------- */
253 
254 /**
255  * @brief FreeRTOS Supervisor Call (SVC) Handler.
256  *
257  * @ingroup Scheduler
258  */
259 void FreeRTOS_SVC_Handler( void );
260 
261 /**
262  * @brief FreeRTOS Interrupt Handler.
263  *
264  * @ingroup Scheduler
265  */
266 void FreeRTOS_IRQ_Handler( void );
267 
268 /**
269  * @brief Yield the CPU.
270  *
271  * @ingroup Scheduler
272  */
273 void vPortYield( void );
274 
275 #define portYIELD() vPortYield()
276 
277 /**
278  * @brief Enable interrupts.
279  *
280  * @ingroup Interrupt Management
281  */
282 void vPortEnableInterrupts( void );
283 
284 #define portENABLE_INTERRUPTS() vPortEnableInterrupts()
285 
286 /**
287  * @brief Disable interrupts.
288  *
289  * @ingroup Interrupt Management
290  */
291 void vPortDisableInterrupts( void );
292 
293 #define portDISABLE_INTERRUPTS() vPortDisableInterrupts()
294 
295 /**
296  * @brief Exit from a FreeRTO System Call.
297  *
298  * @ingroup Port Privilege
299  */
300 void vPortSystemCallExit( void );
301 
302 /**
303  * @brief Start executing first task.
304  *
305  * @ingroup Scheduler
306  */
307 void vPortStartFirstTask( void );
308 
309 /**
310  * @brief Enable the onboard MPU.
311  *
312  * @ingroup MPU Control
313  */
314 void vMPUEnable( void );
315 
316 /**
317  * @brief Disable the onboard MPU.
318  *
319  * @ingroup MPU Control
320  */
321 void vMPUDisable( void );
322 
323 /**
324  * @brief Enable the MPU Background Region.
325  *
326  * @ingroup MPU Control
327  */
328 void vMPUEnableBackgroundRegion( void );
329 
330 /**
331  * @brief Disable the MPU Background Region.
332  *
333  * @ingroup MPU Control
334  */
335 void vMPUDisableBackgroundRegion( void );
336 
337 /**
338  * @brief Set permissions for an MPU Region.
339  *
340  * @ingroup MPU Control
341  *
342  * @param[in] ulRegionNumber The MPU Region Number to set permissions for.
343  * @param[in] ulBaseAddress The base address of the MPU Region.
344  * @param[in] ulRegionSize The size of the MPU Region in bytes.
345  * @param[in] ulRegionPermissions The permissions associated with the MPU Region.
346  *
347  * @note This is an internal function and assumes that the inputs to this
348  * function are checked before calling this function.
349  */
350 void vMPUSetRegion( uint32_t ulRegionNumber,
351                     uint32_t ulBaseAddress,
352                     uint32_t ulRegionSize,
353                     uint32_t ulRegionPermissions );
354 
355 /* ------------------------------- Port.c Declarations ------------------------------- */
356 
357 /**
358  * @brief Enter critical section.
359  *
360  * @ingroup Critical Section
361  */
362 void vPortEnterCritical( void );
363 
364 #define portENTER_CRITICAL() vPortEnterCritical()
365 
366 /**
367  * @brief Exit critical section.
368  *
369  * @ingroup Critical Section
370  */
371 void vPortExitCritical( void );
372 
373 #define portEXIT_CRITICAL() vPortExitCritical()
374 
375 /**
376  * @brief Checks whether or not the processor is privileged.
377  *
378  * @ingroup Port Privilege
379  *
380  * @note The processor privilege level is determined by checking the
381  * mode bits [4:0] of the Current Program Status Register (CPSR).
382  *
383  * @return pdTRUE, if the processer is privileged, pdFALSE otherwise.
384  */
385 BaseType_t xPortIsPrivileged( void );
386 
387 #define portIS_PRIVILEGED() xPortIsPrivileged()
388 
389 /**
390  * @brief Checks whether or not a task is privileged.
391  *
392  * @ingroup Port Privilege
393  *
394  * @note A task's privilege level is associated with the task and is different from
395  * the processor's privilege level returned by xPortIsPrivileged. For example,
396  * the processor is privileged when an unprivileged task executes a system call.
397  *
398  * @return pdTRUE if the task is privileged, pdFALSE otherwise.
399  */
400 BaseType_t xPortIsTaskPrivileged( void );
401 
402 #define portIS_TASK_PRIVILEGED() xPortIsTaskPrivileged()
403 
404 /**
405  * @brief Default return address for tasks.
406  *
407  * @ingroup Task Context
408  *
409  * @note This function is used as the default return address for tasks if
410  * configTASK_RETURN_ADDRESS is not defined in FreeRTOSConfig.h.
411  */
412 void prvTaskExitError( void );
413 
414 #ifdef configTASK_RETURN_ADDRESS
415     #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
416 #else
417     #define portTASK_RETURN_ADDRESS prvTaskExitError
418 #endif /* configTASK_RETURN_ADDRESS */
419 
420 /**
421  * @brief Returns the number of leading zeros in a 32 bit variable.
422  *
423  * @param[in] ulBitmap 32-Bit number to count leading zeros in.
424  *
425  * @return The number of leading zeros in ulBitmap.
426  */
427 UBaseType_t ulPortCountLeadingZeros( UBaseType_t ulBitmap );
428 
429 /**
430  * @brief End the FreeRTOS scheduler.
431  *
432  * Not implemented on this port.
433  *
434  * @ingroup Scheduler
435  */
436 void vPortEndScheduler( void );
437 
438 /* --------------------------------- MPU Definitions --------------------------------- */
439 
440 /**
441  * @brief Mark that this port utilizes the onboard ARM MPU.
442  *
443  * @ingroup MPU Control
444  */
445 #define portUSING_MPU_WRAPPERS     1
446 
447 /**
448  * @brief Used to mark if a task should be created as a privileged task.
449  *
450  * @ingroup Task Context
451  * @ingroup MPU Control
452  *
453  * @note A privileged task is created by performing a bitwise OR of this value and
454  * the task priority. For example, to create a privileged task at priority 2, the
455  * uxPriority parameter should be set to ( 2 | portPRIVILEGE_BIT ).
456  */
457 #define portPRIVILEGE_BIT          ( 0x80000000UL )
458 
459 /**
460  * @brief Size of an Access Control List (ACL) entry in bits.
461  */
462 #define portACL_ENTRY_SIZE_BITS    ( 32UL )
463 
464 /**
465  * @brief Structure to hold the MPU Register Values.
466  *
467  * @struct xMPU_REGION_REGISTERS
468  *
469  * @ingroup MPU Control
470  *
471  * @note The ordering of this struct MUST be in sync with the ordering in
472  * portRESTORE_CONTEXT.
473  */
474 typedef struct MPU_REGION_REGISTERS
475 {
476     uint32_t ulRegionSize;        /* Information for MPU Region Size and Enable Register. */
477     uint32_t ulRegionAttribute;   /* Information for MPU Region Access Control Register. */
478     uint32_t ulRegionBaseAddress; /* Information for MPU Region Base Address Register. */
479 } xMPU_REGION_REGISTERS;
480 
481 /**
482  * @brief Structure to hold per-task System Call Stack information.
483  *
484  * @struct xSYSTEM_CALL_STACK_INFO
485  *
486  * @ingroup Port Privilege
487  *
488  * @note The ordering of this structure MUST be in sync with the assembly code
489  * of the port.
490  */
491 typedef struct SYSTEM_CALL_STACK_INFO
492 {
493     uint32_t * pulTaskStackPointer; /**< Stack Pointer of the task when it made a FreeRTOS System Call. */
494     uint32_t * pulLinkRegisterAtSystemCallEntry; /**< Link Register of the task when it made a FreeRTOS System Call. */
495     uint32_t * pulSystemCallStackPointer; /**< Stack Pointer to use for executing a FreeRTOS System Call. */
496     uint32_t * pulSystemCallExitAddress; /**< System call exit address. */
497     uint32_t ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE ]; /**< Buffer to be used as stack when performing a FreeRTOS System Call. */
498 } xSYSTEM_CALL_STACK_INFO;
499 
500 /**
501  * @brief Per-Task MPU settings structure stored in the TCB.
502  * @struct xMPU_SETTINGS
503  *
504  * @ingroup MPU Control
505  * @ingroup Task Context
506  * @ingroup Port Privilege
507  *
508  * @note The ordering of this structure MUST be in sync with the assembly code
509  * of the port.
510  */
511 typedef struct MPU_SETTINGS
512 {
513     xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS_IN_TCB ];
514     uint32_t ulTaskFlags;
515     xSYSTEM_CALL_STACK_INFO xSystemCallStackInfo;
516     uint32_t ulContext[ CONTEXT_SIZE ]; /**< Buffer used to store task context. */
517 
518     #if( configENABLE_ACCESS_CONTROL_LIST == 1 )
519         uint32_t ulAccessControlList[ ( configPROTECTED_KERNEL_OBJECT_POOL_SIZE
520                                         / portACL_ENTRY_SIZE_BITS )
521                                       + 1UL ];
522     #endif
523 } xMPU_SETTINGS;
524 
525 #ifdef __cplusplus
526 } /* extern C */
527 #endif
528 
529 #endif /* PORTMACRO_H */
530