diff --git a/portable/GCC/ARM_CRx_MPU/.clang-format b/portable/GCC/ARM_CRx_MPU/.clang-format deleted file mode 100644 index c745d9c66f..0000000000 --- a/portable/GCC/ARM_CRx_MPU/.clang-format +++ /dev/null @@ -1,104 +0,0 @@ ---- -Language: Cpp -AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: None -AlignConsecutiveBitFields: AcrossEmptyLinesAndComments -AlignConsecutiveDeclarations: None -AlignConsecutiveMacros: AcrossEmptyLinesAndComments -AlignEscapedNewlines: Left -AlignOperands: AlignAfterOperator -AlignTrailingComments: true -AllowAllArgumentsOnNextLine: false -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: Never -AllowShortCaseLabelsOnASingleLine: false -AllowShortEnumsOnASingleLine: false -AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: false -AllowShortLambdasOnASingleLine: All -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: Yes -BinPackArguments: false -BinPackParameters: false -BitFieldColonSpacing: Both -BraceWrapping: - AfterCaseLabel: true - AfterClass: true - AfterControlStatement: Always - AfterEnum: true - AfterExternBlock: false - AfterFunction: true - AfterNamespace: true - AfterStruct: true - AfterUnion: true - BeforeCatch: true - BeforeElse: true - BeforeLambdaBody: false - BeforeWhile: false - IndentBraces: false - SplitEmptyFunction: true - SplitEmptyRecord: true - SplitEmptyNamespace: true -BreakBeforeBinaryOperators: NonAssignment -BreakBeforeBraces: Custom -BreakBeforeConceptDeclarations: true -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: BeforeColon -BreakInheritanceList: BeforeColon -BreakStringLiterals: true -ColumnLimit: 90 -CompactNamespaces: false -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: false -DerivePointerAlignment: false -EmptyLineBeforeAccessModifier: Always -FixNamespaceComments: true -IncludeBlocks: Preserve -IndentCaseBlocks: false -IndentCaseLabels: true -IndentExternBlock: NoIndent -IndentGotoLabels: true -IndentPPDirectives: BeforeHash -IndentWidth: 4 -IndentWrappedFunctionNames: true -KeepEmptyLinesAtTheStartOfBlocks: false -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -PenaltyBreakAssignment: 1000 -PenaltyBreakBeforeFirstCallParameter: 200 -PenaltyBreakComment: 50 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 100 -PenaltyBreakTemplateDeclaration: 10 -PenaltyExcessCharacter: 100 -PenaltyIndentedWhitespace: 0 -PenaltyReturnTypeOnItsOwnLine: 10000 -PointerAlignment: Middle -ReflowComments: true -SortIncludes: false -SortUsingDeclarations: true -SpaceAfterCStyleCast: true -SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: false -SpaceBeforeCpp11BracedList: true -SpaceBeforeCtorInitializerColon: false -SpaceBeforeInheritanceColon: false -SpaceBeforeParens: Never -SpaceBeforeRangeBasedForLoopColon: false -SpaceBeforeSquareBrackets: false -SpaceInEmptyBlock: false -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInConditionalStatement: true -SpacesInContainerLiterals: true -SpacesInCStyleCastParentheses: true -SpacesInParentheses: true -SpacesInSquareBrackets: true -TabWidth: 4 -UseCRLF: false -UseTab: Never -... - diff --git a/portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.S b/portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.S index 6819bb2531..297b167845 100644 --- a/portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.S +++ b/portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.S @@ -31,6 +31,7 @@ .arm .syntax unified .section freertos_system_calls + #define FREERTOS_ASSEMBLY #include "FreeRTOSConfig.h" #include "portmacro_asm.h" @@ -39,728 +40,457 @@ /* ----------------------- Start of Port Specific System Calls ----------------------- */ -/** - * Function: void vPortYield - * Inputs: VOID -*/ +/* + * void vPortYield( void ); + */ .align 4 .global vPortYield .type vPortYield, %function vPortYield: - /* Make the SVC to swap tasks */ SVC #portSVC_YIELD - /* After yielding to another task, resume executing the calling task */ - BX LR + BX LR /* ----------------------------------------------------------------------------------- */ -/* vPortSystemCallExit */ + +/* + * void vPortSystemCallExit( void ); + */ .align 4 .global vPortSystemCallExit .type vPortSystemCallExit, %function vPortSystemCallExit: - /* Make the SVC to exit a system call */ SVC #portSVC_SYSTEM_CALL_EXIT - /* After performing the requested FreeRTOS API, return to the calling task */ BX LR /* ----------------------------------------------------------------------------------- */ -/** - * Function: BaseType_t xPortIsPrivileged - * Inputs: VOID -*/ + +/* + * BaseType_t xPortIsPrivileged( void ); + * + * According to the Procedure Call Standard for the ARM Architecture (AAPCS): + * - Return value must be in R0. + */ .align 4 .global xPortIsPrivileged .type xPortIsPrivileged, %function xPortIsPrivileged: - /* Load value of CPSR into R0 */ - MRS R0, CPSR - /* Get the relevant mode bits */ - AND R0, R0, #0x1F - /* Check if we're in user mode */ - CMP R0, #USER_MODE - /* If we are in user mode set R0 to 0 for the return */ - MOVEQ R0, #0x0 - /* Otherwise set R0 to 1 for the return */ - MOVNE R0, #0x01 - /* Return to the caller */ - BLX LR + MRS R0, CPSR /* R0 = CPSR. */ + AND R0, R0, #0x1F /* R0 = R0 & 0x1F. Extract mode bits.*/ + CMP R0, #USER_MODE /* If R0 == #USER_MODE. */ + MOVEQ R0, #0x0 /* Then, set R0 to 0 to indicate that the processer is not privileged. */ + MOVNE R0, #0x01 /* Otherwise, set R0 to 1 to indicate that the processer is privileged. */ + BX LR /* ----------------------------------------------------------------------------------- */ -/** - * Function: UBaseType_t ulPortCountLeadingZeros - * Inputs: UBaseType_t ulBitmap -*/ + +/* + * UBaseType_t ulPortCountLeadingZeros( UBaseType_t ulBitmap ); + * + * According to the Procedure Call Standard for the ARM Architecture (AAPCS): + * - Parameter ulBitmap is passed in R0. + * - Return value must be in R0. + */ .align 4 .weak ulPortCountLeadingZeros .type ulPortCountLeadingZeros, %function ulPortCountLeadingZeros: - /* Count the leading zeros and return in R0 */ CLZ R0, R0 BX LR /* ------------------- End of Port Specific System Calls ------------------- */ -.macro processorInUserMode - /* Push R0 before using it */ +.macro INVOKE_SYSTEM_CALL systemCallNumber, systemCallImpl PUSH {R0} - /* Load value of CPSR into R0 */ MRS R0, CPSR - /* Get the relevant mode bits */ AND R0, R0, #0x1F - /* Determine if the CPU is in user mode */ CMP R0, #USER_MODE - /* Restore the pushed register */ POP {R0} + SVCEQ \systemCallNumber + B \systemCallImpl .endm /* ----------------------------------------------------------------------------------- */ .extern MPU_xTaskGetTickCountImpl -/** - * Function: TickType_t MPU_xTaskGetTickCount - * Inputs: void - No Inputs -*/ .align 4 .global MPU_xTaskGetTickCount .type MPU_xTaskGetTickCount, function MPU_xTaskGetTickCount: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTaskGetTickCount - B MPU_xTaskGetTickCountImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGetTickCount, MPU_xTaskGetTickCountImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_uxTaskGetNumberOfTasksImpl -/** - * Function: UBaseType_t MPU_uxTaskGetNumberOfTasks - * Inputs: void - No Inputs -*/ .align 4 .global MPU_uxTaskGetNumberOfTasks .type MPU_uxTaskGetNumberOfTasks, function MPU_uxTaskGetNumberOfTasks: - processorInUserMode - SVCEQ #SYSTEM_CALL_uxTaskGetNumberOfTasks - B MPU_uxTaskGetNumberOfTasksImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxTaskGetNumberOfTasks, MPU_uxTaskGetNumberOfTasksImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_vTaskSetTimeOutStateImpl -/** - * Function: void MPU_vTaskSetTimeOutState - * Inputs: TimeOut_t * const pxTimeOut -*/ .align 4 .global MPU_vTaskSetTimeOutState .type MPU_vTaskSetTimeOutState, function MPU_vTaskSetTimeOutState: - processorInUserMode - SVCEQ #SYSTEM_CALL_vTaskSetTimeOutState - B MPU_vTaskSetTimeOutStateImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTaskSetTimeOutState, MPU_vTaskSetTimeOutStateImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xTaskCheckForTimeOutImpl -/** - * Function: BaseType_t MPU_xTaskCheckForTimeOut - * Inputs: TimeOut_t * const pxTimeOut - * Inputs: TickType_t * const pxTicksToWait -*/ .align 4 .global MPU_xTaskCheckForTimeOut .type MPU_xTaskCheckForTimeOut, function MPU_xTaskCheckForTimeOut: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTaskCheckForTimeOut - B MPU_xTaskCheckForTimeOutImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskCheckForTimeOut, MPU_xTaskCheckForTimeOutImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xQueueGenericSendImpl -/** - * Function: BaseType_t MPU_xQueueGenericSend - * Inputs: QueueHandle_t xQueue - * Inputs: const void * const pvItemToQueue - * Inputs: TickType_t xTicksToWait - * Inputs: constBaseType_t xCopyPosition -*/ .align 4 .global MPU_xQueueGenericSend .type MPU_xQueueGenericSend, function MPU_xQueueGenericSend: - processorInUserMode - SVCEQ #SYSTEM_CALL_xQueueGenericSend - B MPU_xQueueGenericSendImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueGenericSend, MPU_xQueueGenericSendImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_uxQueueMessagesWaitingImpl -/** - * Function: UBaseType_t MPU_uxQueueMessagesWaiting - * Inputs: const QueueHandle_t xQueue -*/ .align 4 .global MPU_uxQueueMessagesWaiting .type MPU_uxQueueMessagesWaiting, function MPU_uxQueueMessagesWaiting: - processorInUserMode - SVCEQ #SYSTEM_CALL_uxQueueMessagesWaiting - B MPU_uxQueueMessagesWaitingImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxQueueMessagesWaiting, MPU_uxQueueMessagesWaitingImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_uxQueueSpacesAvailableImpl -/** - * Function: UBaseType_t MPU_uxQueueSpacesAvailable - * Inputs: const QueueHandle_t xQueue -*/ .align 4 .global MPU_uxQueueSpacesAvailable .type MPU_uxQueueSpacesAvailable, function MPU_uxQueueSpacesAvailable: - processorInUserMode - SVCEQ #SYSTEM_CALL_uxQueueSpacesAvailable - B MPU_uxQueueSpacesAvailableImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxQueueSpacesAvailable, MPU_uxQueueSpacesAvailableImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xQueueReceiveImpl -/** - * Function: BaseType_t MPU_xQueueReceive - * Inputs: QueueHandle_t xQueue - * Inputs: void * const pvBuffer - * Inputs: TickType_t xTicksToWait -*/ .align 4 .global MPU_xQueueReceive .type MPU_xQueueReceive, function MPU_xQueueReceive: - processorInUserMode - SVCEQ #SYSTEM_CALL_xQueueReceive - B MPU_xQueueReceiveImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueReceive, MPU_xQueueReceiveImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xQueuePeekImpl -/** - * Function: BaseType_t MPU_xQueuePeek - * Inputs: QueueHandle_t xQueue - * Inputs: void * const pvBuffer - * Inputs: TickType_t xTicksToWait -*/ .align 4 .global MPU_xQueuePeek .type MPU_xQueuePeek, function MPU_xQueuePeek: - processorInUserMode - SVCEQ #SYSTEM_CALL_xQueuePeek - B MPU_xQueuePeekImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueuePeek, MPU_xQueuePeekImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xQueueSemaphoreTakeImpl -/** - * Function: BaseType_t MPU_xQueueSemaphoreTake - * Inputs: QueueHandle_t xQueue - * Inputs: TickType_t xTicksToWait -*/ .align 4 .global MPU_xQueueSemaphoreTake .type MPU_xQueueSemaphoreTake, function MPU_xQueueSemaphoreTake: - processorInUserMode - SVCEQ #SYSTEM_CALL_xQueueSemaphoreTake - B MPU_xQueueSemaphoreTakeImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueSemaphoreTake, MPU_xQueueSemaphoreTakeImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xEventGroupWaitBitsImpl -/** - * Function: EventBits_t MPU_xEventGroupWaitBitsEntry - * Inputs: const xEventGroupWaitBitsParams_t * pxParams -*/ .align 4 .global MPU_xEventGroupWaitBitsEntry .type MPU_xEventGroupWaitBitsEntry, function MPU_xEventGroupWaitBitsEntry: - processorInUserMode - SVCEQ #SYSTEM_CALL_xEventGroupWaitBits - B MPU_xEventGroupWaitBitsImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xEventGroupWaitBits, MPU_xEventGroupWaitBitsImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xEventGroupClearBitsImpl -/** - * Function: EventBits_t MPU_xEventGroupClearBits - * Inputs: EventGroupHandle_t xEventGroup - * Inputs: constEventBits_t uxBitsToClear -*/ .align 4 .global MPU_xEventGroupClearBits .type MPU_xEventGroupClearBits, function MPU_xEventGroupClearBits: - processorInUserMode - SVCEQ #SYSTEM_CALL_xEventGroupClearBits - B MPU_xEventGroupClearBitsImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xEventGroupClearBits, MPU_xEventGroupClearBitsImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xEventGroupSetBitsImpl -/** - * Function: EventBits_t MPU_xEventGroupSetBits - * Inputs: EventGroupHandle_t xEventGroup - * Inputs: constEventBits_t uxBitsToSet -*/ .align 4 .global MPU_xEventGroupSetBits .type MPU_xEventGroupSetBits, function MPU_xEventGroupSetBits: - processorInUserMode - SVCEQ #SYSTEM_CALL_xEventGroupSetBits - B MPU_xEventGroupSetBitsImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xEventGroupSetBits, MPU_xEventGroupSetBitsImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xEventGroupSyncImpl -/** - * Function: EventBits_t MPU_xEventGroupSync - * Inputs: EventGroupHandle_t xEventGroup - * Inputs: constEventBits_t uxBitsToSet - * Inputs: constEventBits_t uxBitsToWaitFor - * Inputs: TickType_t xTicksToWait -*/ .align 4 .global MPU_xEventGroupSync .type MPU_xEventGroupSync, function MPU_xEventGroupSync: - processorInUserMode - SVCEQ #SYSTEM_CALL_xEventGroupSync - B MPU_xEventGroupSyncImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xEventGroupSync, MPU_xEventGroupSyncImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xStreamBufferSendImpl -/** - * Function: size_t MPU_xStreamBufferSend - * Inputs: StreamBufferHandle_t xStreamBuffer - * Inputs: const void * pvTxData - * Inputs: size_t xDataLengthBytes - * Inputs: TickType_t xTicksToWait -*/ .align 4 .global MPU_xStreamBufferSend .type MPU_xStreamBufferSend, function MPU_xStreamBufferSend: - processorInUserMode - SVCEQ #SYSTEM_CALL_xStreamBufferSend - B MPU_xStreamBufferSendImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferSend, MPU_xStreamBufferSendImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xStreamBufferReceiveImpl -/** - * Function: size_t MPU_xStreamBufferReceive - * Inputs: StreamBufferHandle_t xStreamBuffer - * Inputs: void * pvRxData - * Inputs: size_t xBufferLengthBytes - * Inputs: TickType_t xTicksToWait -*/ .align 4 .global MPU_xStreamBufferReceive .type MPU_xStreamBufferReceive, function MPU_xStreamBufferReceive: - processorInUserMode - SVCEQ #SYSTEM_CALL_xStreamBufferReceive - B MPU_xStreamBufferReceiveImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferReceive, MPU_xStreamBufferReceiveImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xStreamBufferIsFullImpl -/** - * Function: BaseType_t MPU_xStreamBufferIsFull - * Inputs: StreamBufferHandle_t xStreamBuffer -*/ .align 4 .global MPU_xStreamBufferIsFull .type MPU_xStreamBufferIsFull, function MPU_xStreamBufferIsFull: - processorInUserMode - SVCEQ #SYSTEM_CALL_xStreamBufferIsFull - B MPU_xStreamBufferIsFullImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferIsFull, MPU_xStreamBufferIsFullImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xStreamBufferIsEmptyImpl -/** - * Function: BaseType_t MPU_xStreamBufferIsEmpty - * Inputs: StreamBufferHandle_t xStreamBuffer -*/ .align 4 .global MPU_xStreamBufferIsEmpty .type MPU_xStreamBufferIsEmpty, function MPU_xStreamBufferIsEmpty: - processorInUserMode - SVCEQ #SYSTEM_CALL_xStreamBufferIsEmpty - B MPU_xStreamBufferIsEmptyImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferIsEmpty, MPU_xStreamBufferIsEmptyImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xStreamBufferSpacesAvailableImpl -/** - * Function: size_t MPU_xStreamBufferSpacesAvailable - * Inputs: StreamBufferHandle_t xStreamBuffer -*/ .align 4 .global MPU_xStreamBufferSpacesAvailable .type MPU_xStreamBufferSpacesAvailable, function MPU_xStreamBufferSpacesAvailable: - processorInUserMode - SVCEQ #SYSTEM_CALL_xStreamBufferSpacesAvailable - B MPU_xStreamBufferSpacesAvailableImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferSpacesAvailable, MPU_xStreamBufferSpacesAvailableImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xStreamBufferBytesAvailableImpl -/** - * Function: size_t MPU_xStreamBufferBytesAvailable - * Inputs: StreamBufferHandle_t xStreamBuffer -*/ .align 4 .global MPU_xStreamBufferBytesAvailable .type MPU_xStreamBufferBytesAvailable, function MPU_xStreamBufferBytesAvailable: - processorInUserMode - SVCEQ #SYSTEM_CALL_xStreamBufferBytesAvailable - B MPU_xStreamBufferBytesAvailableImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferBytesAvailable, MPU_xStreamBufferBytesAvailableImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xStreamBufferSetTriggerLevelImpl -/** - * Function: BaseType_t MPU_xStreamBufferSetTriggerLevel - * Inputs: StreamBufferHandle_t xStreamBuffer - * Inputs: size_t xTriggerLevel -*/ .align 4 .global MPU_xStreamBufferSetTriggerLevel .type MPU_xStreamBufferSetTriggerLevel, function MPU_xStreamBufferSetTriggerLevel: - processorInUserMode - SVCEQ #SYSTEM_CALL_xStreamBufferSetTriggerLevel - B MPU_xStreamBufferSetTriggerLevelImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferSetTriggerLevel, MPU_xStreamBufferSetTriggerLevelImpl /* ----------------------------------------------------------------------------------- */ .extern MPU_xStreamBufferNextMessageLengthBytesImpl -/** - * Function: size_t MPU_xStreamBufferNextMessageLengthBytes - * Inputs: StreamBufferHandle_t xStreamBuffer -*/ .align 4 .global MPU_xStreamBufferNextMessageLengthBytes .type MPU_xStreamBufferNextMessageLengthBytes, function MPU_xStreamBufferNextMessageLengthBytes: - processorInUserMode - SVCEQ #SYSTEM_CALL_xStreamBufferNextMessageLengthBytes - B MPU_xStreamBufferNextMessageLengthBytesImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferNextMessageLengthBytes, MPU_xStreamBufferNextMessageLengthBytesImpl /* ----------------------------------------------------------------------------------- */ -#if ( INCLUDE_xTaskDelayUntil == 1 ) || ( INCLUDE_vTaskDelayUntil == 1 ) +#if ( ( INCLUDE_xTaskDelayUntil == 1 ) || ( INCLUDE_vTaskDelayUntil == 1 ) ) + .extern MPU_xTaskDelayUntilImpl - /** - * Function: TaskHandle_t MPU_xTaskDelayUntil - * Inputs: TickType_t * const pxPreviousWakeTime - * Inputs: constTickType_t xTimeIncrement - */ .align 4 .global MPU_xTaskDelayUntil .type MPU_xTaskDelayUntil, function MPU_xTaskDelayUntil: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTaskDelayUntil - B MPU_xTaskDelayUntilImpl - - /* ------------------------------------------------------------------------------- */ - -#endif /* if ( INCLUDE_xTaskDelayUntil == 1 ) || ( INCLUDE_vTaskDelayUntil == 1 ) */ + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskDelayUntil, MPU_xTaskDelayUntilImpl -#if INCLUDE_xTaskAbortDelay == 1 +#endif /* if ( ( INCLUDE_xTaskDelayUntil == 1 ) || ( INCLUDE_vTaskDelayUntil == 1 ) ) */ /* ----------------------------------------------------------------------------------- */ +#if ( INCLUDE_xTaskAbortDelay == 1 ) + .extern MPU_xTaskAbortDelayImpl - /** - * Function: TaskHandle_t MPU_xTaskAbortDelay - * Inputs: TaskHandle_t xTask - */ .align 4 .global MPU_xTaskAbortDelay .type MPU_xTaskAbortDelay, function MPU_xTaskAbortDelay: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTaskAbortDelay - B MPU_xTaskAbortDelayImpl - - /* ------------------------------------------------------------------------------- */ + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskAbortDelay, MPU_xTaskAbortDelayImpl #endif /* if ( INCLUDE_xTaskAbortDelay == 1 ) */ -#if INCLUDE_vTaskDelay == 1 +/* ------------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( INCLUDE_vTaskDelay == 1 ) .extern MPU_vTaskDelayImpl - /** - * Function: void MPU_vTaskDelay - * Inputs: const TickType_t xTicksToDelay - */ .align 4 .global MPU_vTaskDelay .type MPU_vTaskDelay, function MPU_vTaskDelay: - processorInUserMode - SVCEQ #SYSTEM_CALL_vTaskDelay - B MPU_vTaskDelayImpl - - /* ------------------------------------------------------------------------------- */ + INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTaskDelay, MPU_vTaskDelayImpl #endif /* if ( INCLUDE_vTaskDelay == 1 ) */ -#if INCLUDE_uxTaskPriorityGet == 1 +/* ------------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( INCLUDE_uxTaskPriorityGet == 1 ) .extern MPU_uxTaskPriorityGetImpl - /** - * Function: UBaseType_t MPU_uxTaskPriorityGet - * Inputs: const TaskHandle_t xTask - */ .align 4 .global MPU_uxTaskPriorityGet .type MPU_uxTaskPriorityGet, function MPU_uxTaskPriorityGet: - processorInUserMode - SVCEQ #SYSTEM_CALL_uxTaskPriorityGet - B MPU_uxTaskPriorityGetImpl - - /* ------------------------------------------------------------------------------- */ + INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxTaskPriorityGet, MPU_uxTaskPriorityGetImpl #endif /* if ( INCLUDE_uxTaskPriorityGet == 1 ) */ -#if INCLUDE_eTaskGetState == 1 +/* ------------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( INCLUDE_eTaskGetState == 1 ) .extern MPU_eTaskGetStateImpl - /** - * Function: eTaskState MPU_eTaskGetState - * Inputs: TaskHandle_t xTask - */ .align 4 .global MPU_eTaskGetState .type MPU_eTaskGetState, function MPU_eTaskGetState: - processorInUserMode - SVCEQ #SYSTEM_CALL_eTaskGetState - B MPU_eTaskGetStateImpl - - /* ------------------------------------------------------------------------------- */ + INVOKE_SYSTEM_CALL #SYSTEM_CALL_eTaskGetState, MPU_eTaskGetStateImpl #endif /* if ( INCLUDE_eTaskGetState == 1 ) */ -#if configUSE_TRACE_FACILITY == 1 +/* ------------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( configUSE_TRACE_FACILITY == 1 ) .extern MPU_vTaskGetInfoImpl - /** - * Function: void MPU_vTaskGetInfo - * Inputs: TaskHandle_t xTask - * Inputs: TaskStatus_t* pxTaskStatus - * Inputs: TaskHandle_t xGetFreeStackSpace - * Inputs: eTaskState eState - */ .align 4 .global MPU_vTaskGetInfo .type MPU_vTaskGetInfo, function MPU_vTaskGetInfo: - processorInUserMode - SVCEQ #SYSTEM_CALL_vTaskGetInfo - B MPU_vTaskGetInfoImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTaskGetInfo, MPU_vTaskGetInfoImpl /* ------------------------------------------------------------------------------- */ .extern MPU_uxTaskGetSystemStateImpl - /** - * Function: UBaseType_t MPU_uxTaskGetSystemState - * Inputs: TaskStatus_t * const pxTaskStatusArray - * Inputs: constUBaseType_t uxArraySize - * Inputs: configRUN_TIME_COUNTER_TYPE* const pulTotalRunTime - */ .align 4 .global MPU_uxTaskGetSystemState .type MPU_uxTaskGetSystemState, function MPU_uxTaskGetSystemState: - processorInUserMode - SVCEQ #SYSTEM_CALL_uxTaskGetSystemState - B MPU_uxTaskGetSystemStateImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxTaskGetSystemState, MPU_uxTaskGetSystemStateImpl /* ------------------------------------------------------------------------------- */ .extern MPU_uxEventGroupGetNumberImpl - /** - * Function: UBaseType_t MPU_uxEventGroupGetNumber - * Inputs: void * xEventGroup - */ .align 4 .global MPU_uxEventGroupGetNumber .type MPU_uxEventGroupGetNumber, function MPU_uxEventGroupGetNumber: - processorInUserMode - SVCEQ #SYSTEM_CALL_uxEventGroupGetNumber - B MPU_uxEventGroupGetNumberImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxEventGroupGetNumber, MPU_uxEventGroupGetNumberImpl /* ------------------------------------------------------------------------------- */ .extern MPU_vEventGroupSetNumberImpl - /** - * Function: void MPU_vEventGroupSetNumber - * Inputs: void * xEventGroup - * Inputs: UBaseType_t uxEventGroupNumber - */ .align 4 .global MPU_vEventGroupSetNumber .type MPU_vEventGroupSetNumber, function MPU_vEventGroupSetNumber: - processorInUserMode - SVCEQ #SYSTEM_CALL_vEventGroupSetNumber - B MPU_vEventGroupSetNumberImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_vEventGroupSetNumber, MPU_vEventGroupSetNumberImpl /* ------------------------------------------------------------------------------- */ + #endif /* if ( configUSE_TRACE_FACILITY == 1 ) */ -#if INCLUDE_xTaskGetIdleTaskHandle == 1 +/* ------------------------------------------------------------------------------- */ + +#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) - /* ------------------------------------------------------------------------------- */ .extern MPU_xTaskGetIdleTaskHandleImpl - /** - * Function: TaskHandle_t MPU_xTaskGetIdleTaskHandle - * Inputs: void - No Inputs - */ .align 4 .global MPU_xTaskGetIdleTaskHandle .type MPU_xTaskGetIdleTaskHandle, function MPU_xTaskGetIdleTaskHandle: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTaskGetIdleTaskHandle - B MPU_xTaskGetIdleTaskHandleImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGetIdleTaskHandle, MPU_xTaskGetIdleTaskHandleImpl - /* ------------------------------------------------------------------------------- */ #endif /* if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) */ -#if INCLUDE_vTaskSuspend == 1 +/* ------------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( INCLUDE_vTaskSuspend == 1 ) .extern MPU_vTaskSuspendImpl - /** - * Function: void MPU_vTaskSuspend - * Inputs: TaskHandle_t xTaskToSuspend - */ .align 4 .global MPU_vTaskSuspend .type MPU_vTaskSuspend, function MPU_vTaskSuspend: - processorInUserMode - SVCEQ #SYSTEM_CALL_vTaskSuspend - B MPU_vTaskSuspendImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTaskSuspend, MPU_vTaskSuspendImpl /* ------------------------------------------------------------------------------- */ .extern MPU_vTaskResumeImpl - /** - * Function: void MPU_vTaskResume - * Inputs: TaskHandle_t xTaskToResume - */ .align 4 .global MPU_vTaskResume .type MPU_vTaskResume, function MPU_vTaskResume: - processorInUserMode - SVCEQ #SYSTEM_CALL_vTaskResume - B MPU_vTaskResumeImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTaskResume, MPU_vTaskResumeImpl /* ------------------------------------------------------------------------------- */ #endif /* if ( INCLUDE_vTaskSuspend == 1 ) */ -#if configGENERATE_RUN_TIME_STATS == 1 +/* ------------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( configGENERATE_RUN_TIME_STATS == 1 ) .extern MPU_ulTaskGetRunTimeCounterImpl - /** - * Function: configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetRunTimeCounter - * Inputs: const TaskHandle_t xTask - */ .align 4 .global MPU_ulTaskGetRunTimeCounter .type MPU_ulTaskGetRunTimeCounter, function MPU_ulTaskGetRunTimeCounter: - processorInUserMode - SVCEQ #SYSTEM_CALL_ulTaskGetRunTimeCounter - B MPU_ulTaskGetRunTimeCounterImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_ulTaskGetRunTimeCounter, MPU_ulTaskGetRunTimeCounterImpl /* ------------------------------------------------------------------------------- */ .extern MPU_ulTaskGetRunTimePercentImpl - /** - * Function: configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetRunTimePercent - * Inputs: const TaskHandle_t xTask - */ .align 4 .global MPU_ulTaskGetRunTimePercent .type MPU_ulTaskGetRunTimePercent, function MPU_ulTaskGetRunTimePercent: - processorInUserMode - SVCEQ #SYSTEM_CALL_ulTaskGetRunTimePercent - B MPU_ulTaskGetRunTimePercentImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_ulTaskGetRunTimePercent, MPU_ulTaskGetRunTimePercentImpl /* ------------------------------------------------------------------------------- */ - #if INCLUDE_xTaskGetIdleTaskHandle == 1 - - /* --------------------------------------------------------------------------- */ + #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) .extern MPU_ulTaskGetIdleRunTimePercentImpl - /** - * Function: configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimePercent - * Inputs: void - */ .align 4 .global MPU_ulTaskGetIdleRunTimePercent .type MPU_ulTaskGetIdleRunTimePercent, function MPU_ulTaskGetIdleRunTimePercent: - processorInUserMode - SVCEQ #SYSTEM_CALL_ulTaskGetIdleRunTimePercent - B MPU_ulTaskGetIdleRunTimePercentImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_ulTaskGetIdleRunTimePercent, MPU_ulTaskGetIdleRunTimePercentImpl /* --------------------------------------------------------------------------- */ .extern MPU_ulTaskGetIdleRunTimeCounterImpl - /** - * Function: configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimeCounter - * Inputs: void - No Inputs - */ .align 4 .global MPU_ulTaskGetIdleRunTimeCounter .type MPU_ulTaskGetIdleRunTimeCounter, function MPU_ulTaskGetIdleRunTimeCounter: - processorInUserMode - SVCEQ #SYSTEM_CALL_ulTaskGetIdleRunTimeCounter - B MPU_ulTaskGetIdleRunTimeCounterImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_ulTaskGetIdleRunTimeCounter, MPU_ulTaskGetIdleRunTimeCounterImpl /* --------------------------------------------------------------------------- */ @@ -768,568 +498,357 @@ MPU_xStreamBufferNextMessageLengthBytes: #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 )*/ -#if configUSE_APPLICATION_TASK_TAG == 1 +/* --------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) .extern MPU_vTaskSetApplicationTaskTagImpl - /** - * Function: void MPU_vTaskSetApplicationTaskTag - * Inputs: TaskHandle_t xTask - * Inputs: TaskHookFunction_tpxHookFunction - */ .align 4 .global MPU_vTaskSetApplicationTaskTag .type MPU_vTaskSetApplicationTaskTag, function MPU_vTaskSetApplicationTaskTag: - processorInUserMode - SVCEQ #SYSTEM_CALL_vTaskSetApplicationTaskTag - B MPU_vTaskSetApplicationTaskTagImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTaskSetApplicationTaskTag, MPU_vTaskSetApplicationTaskTagImpl /* ------------------------------------------------------------------------------- */ .extern MPU_xTaskGetApplicationTaskTagImpl - /** - * Function: TaskHookFunction_t MPU_xTaskGetApplicationTaskTag - * Inputs: TaskHandle_t xTask - */ .align 4 .global MPU_xTaskGetApplicationTaskTag .type MPU_xTaskGetApplicationTaskTag, function MPU_xTaskGetApplicationTaskTag: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTaskGetApplicationTaskTag - B MPU_xTaskGetApplicationTaskTagImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGetApplicationTaskTag, MPU_xTaskGetApplicationTaskTagImpl /* ------------------------------------------------------------------------------- */ + #endif /* if ( configUSE_APPLICATION_TASK_TAG == 1 ) */ -#if configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 +/* ------------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) .extern MPU_vTaskSetThreadLocalStoragePointerImpl - /** - * Function: void MPU_vTaskSetThreadLocalStoragePointer - * Inputs: TaskHandle_t xTaskToSet - * Inputs: TaskHandle_t xIndex - * Inputs: void * pvValue - */ .align 4 .global MPU_vTaskSetThreadLocalStoragePointer .type MPU_vTaskSetThreadLocalStoragePointer, function MPU_vTaskSetThreadLocalStoragePointer: - processorInUserMode - SVCEQ #SYSTEM_CALL_vTaskSetThreadLocalStoragePointer - B MPU_vTaskSetThreadLocalStoragePointerImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTaskSetThreadLocalStoragePointer, MPU_vTaskSetThreadLocalStoragePointerImpl /* ------------------------------------------------------------------------------- */ .extern MPU_pvTaskGetThreadLocalStoragePointerImpl - /** - * Function: void * MPU_pvTaskGetThreadLocalStoragePointer - * Inputs: TaskHandle_t xTaskToQuery - * Inputs: TaskHandle_t xIndex - */ .align 4 .global MPU_pvTaskGetThreadLocalStoragePointer .type MPU_pvTaskGetThreadLocalStoragePointer, function MPU_pvTaskGetThreadLocalStoragePointer: - processorInUserMode - SVCEQ #SYSTEM_CALL_pvTaskGetThreadLocalStoragePointer - B MPU_pvTaskGetThreadLocalStoragePointerImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_pvTaskGetThreadLocalStoragePointer, MPU_pvTaskGetThreadLocalStoragePointerImpl /* ------------------------------------------------------------------------------- */ #endif /* if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) */ -#if INCLUDE_uxTaskGetStackHighWaterMark == 1 +/* ------------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) .extern MPU_uxTaskGetStackHighWaterMarkImpl - /** - * Function: UBaseType_t MPU_uxTaskGetStackHighWaterMark - * Inputs: TaskHandle_t xTask - */ .align 4 .global MPU_uxTaskGetStackHighWaterMark .type MPU_uxTaskGetStackHighWaterMark, function MPU_uxTaskGetStackHighWaterMark: - processorInUserMode - SVCEQ #SYSTEM_CALL_uxTaskGetStackHighWaterMark - B MPU_uxTaskGetStackHighWaterMarkImpl - - /* ------------------------------------------------------------------------------- */ + INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxTaskGetStackHighWaterMark, MPU_uxTaskGetStackHighWaterMarkImpl #endif /* if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) */ +/* ------------------------------------------------------------------------------- */ -#if INCLUDE_uxTaskGetStackHighWaterMark == 2 - - /* ------------------------------------------------------------------------------- */ +#if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) .extern MPU_uxTaskGetStackHighWaterMark2Impl - /** - * Function: configSTACK_DEPTH_TYPE MPU_uxTaskGetStackHighWaterMark2 - * Inputs: TaskHandle_t xTask - */ .align 4 .global MPU_uxTaskGetStackHighWaterMark2 .type MPU_uxTaskGetStackHighWaterMark2, function MPU_uxTaskGetStackHighWaterMark2: - processorInUserMode - SVCEQ #SYSTEM_CALL_uxTaskGetStackHighWaterMark2 - B MPU_uxTaskGetStackHighWaterMark2Impl - - /* ------------------------------------------------------------------------------- */ + INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxTaskGetStackHighWaterMark2, MPU_uxTaskGetStackHighWaterMark2Impl #endif /* if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) */ +/* ------------------------------------------------------------------------------- */ -#if INCLUDE_xTaskGetCurrentTaskHandle == 1 || configUSE_MUTEXES == 1 - - /* ------------------------------------------------------------------------------- */ +#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) .extern MPU_xTaskGetCurrentTaskHandleImpl - /** - * Function: TaskHandle_t MPU_xTaskGetCurrentTaskHandle - * Inputs: void - No Inputs - */ .align 4 .global MPU_xTaskGetCurrentTaskHandle .type MPU_xTaskGetCurrentTaskHandle, function MPU_xTaskGetCurrentTaskHandle: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTaskGetCurrentTaskHandle - B MPU_xTaskGetCurrentTaskHandleImpl - - /* ------------------------------------------------------------------------------- */ + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGetCurrentTaskHandle, MPU_xTaskGetCurrentTaskHandleImpl #endif /* if( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */ -#if INCLUDE_xTaskGetSchedulerState == 1 +/* ------------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( INCLUDE_xTaskGetSchedulerState == 1 ) .extern MPU_xTaskGetSchedulerStateImpl - /** - * Function: TaskHandle_t MPU_xTaskGetSchedulerState - * Inputs: void - No Inputs - */ .align 4 .global MPU_xTaskGetSchedulerState .type MPU_xTaskGetSchedulerState, function MPU_xTaskGetSchedulerState: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTaskGetSchedulerState - B MPU_xTaskGetSchedulerStateImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGetSchedulerState, MPU_xTaskGetSchedulerStateImpl - /* ------------------------------------------------------------------------------- */ #endif /* if ( INCLUDE_xTaskGetSchedulerState == 1 ) */ -#if configUSE_MUTEXES == 1 && INCLUDE_xSemaphoreGetMutexHolder +/* ------------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) .extern MPU_xQueueGetMutexHolderImpl - /** - * Function: TaskHandle_t MPU_xQueueGetMutexHolder - * Inputs: QueueHandle_t xSemaphore - */ .align 4 .global MPU_xQueueGetMutexHolder .type MPU_xQueueGetMutexHolder, function MPU_xQueueGetMutexHolder: - processorInUserMode - SVCEQ #SYSTEM_CALL_xQueueGetMutexHolder - B MPU_xQueueGetMutexHolderImpl - - /* ------------------------------------------------------------------------------- */ + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueGetMutexHolder, MPU_xQueueGetMutexHolderImpl #endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */ -#if configUSE_RECURSIVE_MUTEXES == 1 +/* ------------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( configUSE_RECURSIVE_MUTEXES == 1 ) .extern MPU_xQueueTakeMutexRecursiveImpl - /** - * Function: TaskHandle_t MPU_xQueueTakeMutexRecursive - * Inputs: QueueHandle_t xMutex - * Inputs: TickType_t xTicksToWait - */ .align 4 .global MPU_xQueueTakeMutexRecursive .type MPU_xQueueTakeMutexRecursive, function MPU_xQueueTakeMutexRecursive: - processorInUserMode - SVCEQ #SYSTEM_CALL_xQueueTakeMutexRecursive - B MPU_xQueueTakeMutexRecursiveImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueTakeMutexRecursive, MPU_xQueueTakeMutexRecursiveImpl /* ------------------------------------------------------------------------------- */ .extern MPU_xQueueGiveMutexRecursiveImpl - /** - * Function: TaskHandle_t MPU_xQueueGiveMutexRecursive - * Inputs: QueueHandle_t pxMutex - */ .align 4 .global MPU_xQueueGiveMutexRecursive .type MPU_xQueueGiveMutexRecursive, function MPU_xQueueGiveMutexRecursive: - processorInUserMode - SVCEQ #SYSTEM_CALL_xQueueGiveMutexRecursive - B MPU_xQueueGiveMutexRecursiveImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueGiveMutexRecursive, MPU_xQueueGiveMutexRecursiveImpl /* ------------------------------------------------------------------------------- */ #endif /* if ( configUSE_RECURSIVE_MUTEXES == 1 ) */ -#if configUSE_QUEUE_SETS == 1 +/* ------------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( configUSE_QUEUE_SETS == 1 ) .extern MPU_xQueueSelectFromSetImpl - /** - * Function: QueueSetMemberHandle_t MPU_xQueueSelectFromSet - * Inputs: QueueSetHandle_t xQueueSet - * Inputs: constTickType_t xTicksToWait - */ .align 4 .global MPU_xQueueSelectFromSet .type MPU_xQueueSelectFromSet, function MPU_xQueueSelectFromSet: - processorInUserMode - SVCEQ #SYSTEM_CALL_xQueueSelectFromSet - B MPU_xQueueSelectFromSetImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueSelectFromSet, MPU_xQueueSelectFromSetImpl /* ------------------------------------------------------------------------------- */ .extern MPU_xQueueAddToSetImpl - /** - * Function: TaskHandle_t MPU_xQueueAddToSet - * Inputs: QueueSetMemberHandle_t xQueueOrSemaphore - * Inputs: QueueSetHandle_t xQueueSet - */ .align 4 .global MPU_xQueueAddToSet .type MPU_xQueueAddToSet, function MPU_xQueueAddToSet: - processorInUserMode - SVCEQ #SYSTEM_CALL_xQueueAddToSet - B MPU_xQueueAddToSetImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueAddToSet, MPU_xQueueAddToSetImpl /* ------------------------------------------------------------------------------- */ #endif /* if ( configUSE_QUEUE_SETS == 1 ) */ -#if configQUEUE_REGISTRY_SIZE > 0 +/* ------------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( configQUEUE_REGISTRY_SIZE > 0 ) .extern MPU_vQueueAddToRegistryImpl - /** - * Function: void MPU_vQueueAddToRegistry - * Inputs: QueueHandle_t xQueue - * Inputs: constchar * pcName - */ .align 4 .global MPU_vQueueAddToRegistry .type MPU_vQueueAddToRegistry, function MPU_vQueueAddToRegistry: - processorInUserMode - SVCEQ #SYSTEM_CALL_vQueueAddToRegistry - B MPU_vQueueAddToRegistryImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_vQueueAddToRegistry, MPU_vQueueAddToRegistryImpl /* ------------------------------------------------------------------------------- */ .extern MPU_vQueueUnregisterQueueImpl - /** - * Function: void MPU_vQueueUnregisterQueue - * Inputs: QueueHandle_t xQueue - */ .align 4 .global MPU_vQueueUnregisterQueue .type MPU_vQueueUnregisterQueue, function MPU_vQueueUnregisterQueue: - processorInUserMode - SVCEQ #SYSTEM_CALL_vQueueUnregisterQueue - B MPU_vQueueUnregisterQueueImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_vQueueUnregisterQueue, MPU_vQueueUnregisterQueueImpl /* ------------------------------------------------------------------------------- */ .extern MPU_pcQueueGetNameImpl - /** - * Function: const char * MPU_pcQueueGetName - * Inputs: QueueHandle_t xQueue - */ .align 4 .global MPU_pcQueueGetName .type MPU_pcQueueGetName, function MPU_pcQueueGetName: - processorInUserMode - SVCEQ #SYSTEM_CALL_pcQueueGetName - B MPU_pcQueueGetNameImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_pcQueueGetName, MPU_pcQueueGetNameImpl /* ------------------------------------------------------------------------------- */ #endif /* if ( configQUEUE_REGISTRY_SIZE > 0 ) */ -#if configUSE_TIMERS == 1 +/* ------------------------------------------------------------------------------- */ - /* ------------------------------------------------------------------------------- */ +#if ( configUSE_TIMERS == 1 ) .extern MPU_pvTimerGetTimerIDImpl - /** - * Function: void * MPU_pvTimerGetTimerID - * Inputs: const TimerHandle_t xTimer - */ .align 4 .global MPU_pvTimerGetTimerID .type MPU_pvTimerGetTimerID, function MPU_pvTimerGetTimerID: - processorInUserMode - SVCEQ #SYSTEM_CALL_pvTimerGetTimerID - B MPU_pvTimerGetTimerIDImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_pvTimerGetTimerID, MPU_pvTimerGetTimerIDImpl /* ------------------------------------------------------------------------------- */ .extern MPU_vTimerSetTimerIDImpl - /** - * Function: void MPU_vTimerSetTimerID - * Inputs: TimerHandle_t xTimer - * Inputs: void * pvNewID - */ .align 4 .global MPU_vTimerSetTimerID .type MPU_vTimerSetTimerID, function MPU_vTimerSetTimerID: - processorInUserMode - SVCEQ #SYSTEM_CALL_vTimerSetTimerID - B MPU_vTimerSetTimerIDImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTimerSetTimerID, MPU_vTimerSetTimerIDImpl /* ------------------------------------------------------------------------------- */ .extern MPU_xTimerIsTimerActiveImpl - /** - * Function: TaskHandle_t MPU_xTimerIsTimerActive - * Inputs: TimerHandle_t xTimer - */ .align 4 .global MPU_xTimerIsTimerActive .type MPU_xTimerIsTimerActive, function MPU_xTimerIsTimerActive: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTimerIsTimerActive - B MPU_xTimerIsTimerActiveImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTimerIsTimerActive, MPU_xTimerIsTimerActiveImpl /* ------------------------------------------------------------------------------- */ .extern MPU_xTimerGetTimerDaemonTaskHandleImpl - /** - * Function: TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle - * Inputs: void - No Inputs - */ .align 4 .global MPU_xTimerGetTimerDaemonTaskHandle .type MPU_xTimerGetTimerDaemonTaskHandle, function MPU_xTimerGetTimerDaemonTaskHandle: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTimerGetTimerDaemonTaskHandle - B MPU_xTimerGetTimerDaemonTaskHandleImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTimerGetTimerDaemonTaskHandle, MPU_xTimerGetTimerDaemonTaskHandleImpl /* ------------------------------------------------------------------------------- */ .extern MPU_xTimerGenericCommandFromTaskImpl - /** - * Function: TaskHandle_t MPU_xTimerGenericCommandFromTaskEntry - * Inputs: const xTimerGenericCommandParams_t * pxParams - */ .align 4 .global MPU_xTimerGenericCommandFromTaskEntry .type MPU_xTimerGenericCommandFromTaskEntry, function MPU_xTimerGenericCommandFromTaskEntry: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTimerGenericCommandFromTask - B MPU_xTimerGenericCommandFromTaskImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTimerGenericCommandFromTask, MPU_xTimerGenericCommandFromTaskImpl /* ------------------------------------------------------------------------------- */ - .extern MPU_pcTimerGetNameImpl - /** - * Function: const char * MPU_pcTimerGetName - * Inputs: TimerHandle_t xTimer - */ .align 4 .global MPU_pcTimerGetName .type MPU_pcTimerGetName, function MPU_pcTimerGetName: - processorInUserMode - SVCEQ #SYSTEM_CALL_pcTimerGetName - B MPU_pcTimerGetNameImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_pcTimerGetName, MPU_pcTimerGetNameImpl /* ------------------------------------------------------------------------------- */ .extern MPU_vTimerSetReloadModeImpl - /** - * Function: void MPU_vTimerSetReloadMode - * Inputs: TimerHandle_t xTimer - * Inputs: constBaseType_t uxAutoReload - */ .align 4 .global MPU_vTimerSetReloadMode .type MPU_vTimerSetReloadMode, function MPU_vTimerSetReloadMode: - processorInUserMode - SVCEQ #SYSTEM_CALL_vTimerSetReloadMode - B MPU_vTimerSetReloadModeImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTimerSetReloadMode, MPU_vTimerSetReloadModeImpl /* ------------------------------------------------------------------------------- */ .extern MPU_xTimerGetReloadModeImpl - /** - * Function: TaskHandle_t MPU_xTimerGetReloadMode - * Inputs: TimerHandle_t xTimer - */ .align 4 .global MPU_xTimerGetReloadMode .type MPU_xTimerGetReloadMode, function MPU_xTimerGetReloadMode: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTimerGetReloadMode - B MPU_xTimerGetReloadModeImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTimerGetReloadMode, MPU_xTimerGetReloadModeImpl /* ------------------------------------------------------------------------------- */ .extern MPU_uxTimerGetReloadModeImpl - /** - * Function: UBaseType_t MPU_uxTimerGetReloadMode - * Inputs: TimerHandle_t xTimer - */ .align 4 .global MPU_uxTimerGetReloadMode .type MPU_uxTimerGetReloadMode, function MPU_uxTimerGetReloadMode: - processorInUserMode - SVCEQ #SYSTEM_CALL_uxTimerGetReloadMode - B MPU_uxTimerGetReloadModeImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxTimerGetReloadMode, MPU_uxTimerGetReloadModeImpl /* ------------------------------------------------------------------------------- */ .extern MPU_xTimerGetPeriodImpl - /** - * Function: TickType_t MPU_xTimerGetPeriod - * Inputs: TimerHandle_t xTimer - */ .align 4 .global MPU_xTimerGetPeriod .type MPU_xTimerGetPeriod, function MPU_xTimerGetPeriod: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTimerGetPeriod - B MPU_xTimerGetPeriodImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTimerGetPeriod, MPU_xTimerGetPeriodImpl /* ------------------------------------------------------------------------------- */ .extern MPU_xTimerGetExpiryTimeImpl - /** - * Function: TickType_t MPU_xTimerGetExpiryTime - * Inputs: TimerHandle_t xTimer - */ .align 4 .global MPU_xTimerGetExpiryTime .type MPU_xTimerGetExpiryTime, function MPU_xTimerGetExpiryTime: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTimerGetExpiryTime - B MPU_xTimerGetExpiryTimeImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTimerGetExpiryTime, MPU_xTimerGetExpiryTimeImpl /* ------------------------------------------------------------------------------- */ #endif /* if ( configUSE_TIMERS == 1 ) */ -#if configUSE_TASK_NOTIFICATIONS == 1 +/* ------------------------------------------------------------------------------- */ + +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) + .extern MPU_xTaskGenericNotifyImpl - /** - * Function: TaskHandle_t MPU_xTaskGenericNotifyEntry - * Inputs: const xTaskGenericNotifyParams_t * pxParams - */ .align 4 .global MPU_xTaskGenericNotifyEntry .type MPU_xTaskGenericNotifyEntry, function MPU_xTaskGenericNotifyEntry: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTaskGenericNotify - B MPU_xTaskGenericNotifyImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGenericNotify, MPU_xTaskGenericNotifyImpl /* ------------------------------------------------------------------------------- */ .extern MPU_xTaskGenericNotifyWaitImpl - /** - * Function: TaskHandle_t MPU_xTaskGenericNotifyWaitEntry - * Inputs: const xTaskGenericNotifyWaitParams_t * pxParams - */ .align 4 .global MPU_xTaskGenericNotifyWaitEntry .type MPU_xTaskGenericNotifyWaitEntry, function MPU_xTaskGenericNotifyWaitEntry: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTaskGenericNotifyWait - B MPU_xTaskGenericNotifyWaitImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGenericNotifyWait, MPU_xTaskGenericNotifyWaitImpl /* ------------------------------------------------------------------------------- */ .extern MPU_ulTaskGenericNotifyTakeImpl - /** - * Function: uint32_t MPU_ulTaskGenericNotifyTake - * Inputs: UBaseType_t uxIndexToWaitOn - * Inputs: TaskHandle_t xClearCountOnExit - * Inputs: TickType_t xTicksToWait - */ .align 4 .global MPU_ulTaskGenericNotifyTake .type MPU_ulTaskGenericNotifyTake, function MPU_ulTaskGenericNotifyTake: - processorInUserMode - SVCEQ #SYSTEM_CALL_ulTaskGenericNotifyTake - B MPU_ulTaskGenericNotifyTakeImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_ulTaskGenericNotifyTake, MPU_ulTaskGenericNotifyTakeImpl /* ------------------------------------------------------------------------------- */ .extern MPU_xTaskGenericNotifyStateClearImpl - /** - * Function: TaskHandle_t MPU_xTaskGenericNotifyStateClear - * Inputs: TaskHandle_t xTask - * Inputs: UBaseType_t uxIndexToClear - */ .align 4 .global MPU_xTaskGenericNotifyStateClear .type MPU_xTaskGenericNotifyStateClear, function MPU_xTaskGenericNotifyStateClear: - processorInUserMode - SVCEQ #SYSTEM_CALL_xTaskGenericNotifyStateClear - B MPU_xTaskGenericNotifyStateClearImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGenericNotifyStateClear, MPU_xTaskGenericNotifyStateClearImpl /* ------------------------------------------------------------------------------- */ .extern MPU_ulTaskGenericNotifyValueClearImpl - /** - * Function: uint32_t MPU_ulTaskGenericNotifyValueClear - * Inputs: TaskHandle_t xTask - * Inputs: UBaseType_t uxIndexToClear - * Inputs: uint32_t ulBitsToClear - */ .align 4 .global MPU_ulTaskGenericNotifyValueClear .type MPU_ulTaskGenericNotifyValueClear, function MPU_ulTaskGenericNotifyValueClear: - processorInUserMode - SVCEQ #SYSTEM_CALL_ulTaskGenericNotifyValueClear - B MPU_ulTaskGenericNotifyValueClearImpl + INVOKE_SYSTEM_CALL #SYSTEM_CALL_ulTaskGenericNotifyValueClear, MPU_ulTaskGenericNotifyValueClearImpl /* ------------------------------------------------------------------------------- */ #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ + +/* ------------------------------------------------------------------------------- */ + +.end diff --git a/portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.h b/portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.h deleted file mode 100644 index 17fec8f6c8..0000000000 --- a/portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.h +++ /dev/null @@ -1,495 +0,0 @@ -/* - * FreeRTOS Kernel - * Copyright (C) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * SPDX-License-Identifier: MIT - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * https://www.FreeRTOS.org - * https://github.com/FreeRTOS - * - */ - -#ifndef MPU_PROTOTYPES_H -#define MPU_PROTOTYPES_H - -#include - -/** Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from - * redefining all the API functions to use the MPU wrappers. That should only - * be done when task.h is included from an application file. */ -#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE - #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE -#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -#include "queue.h" -#include "timers.h" -#include "event_groups.h" -#include "stream_buffer.h" -#include "mpu_prototypes.h" -#include "mpu_syscall_numbers.h" - -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -typedef struct xTaskGenericNotifyParams -{ - TaskHandle_t xTaskToNotify; - UBaseType_t uxIndexToNotify; - uint32_t ulValue; - eNotifyAction eAction; - uint32_t * pulPreviousNotificationValue; -} xTaskGenericNotifyParams_t; - -typedef struct xTaskGenericNotifyWaitParams -{ - UBaseType_t uxIndexToWaitOn; - uint32_t ulBitsToClearOnEntry; - uint32_t ulBitsToClearOnExit; - uint32_t * pulNotificationValue; - TickType_t xTicksToWait; -} xTaskGenericNotifyWaitParams_t; - -typedef struct xTimerGenericCommandParams -{ - TimerHandle_t xTimer; - BaseType_t xCommandID; - TickType_t xOptionalValue; - BaseType_t * pxHigherPriorityTaskWoken; - TickType_t xTicksToWait; -} xTimerGenericCommandParams_t; - -typedef struct xEventGroupWaitBitsParams -{ - EventGroupHandle_t xEventGroup; - EventBits_t uxBitsToWaitFor; - BaseType_t xClearOnExit; - BaseType_t xWaitForAllBits; - TickType_t xTicksToWait; -} xEventGroupWaitBitsParams_t; - -/* ----------------------------------------------------------------------------------- */ - -extern TickType_t MPU_xTaskGetTickCount( void ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, - TickType_t * const pxTicksToWait ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, - const void * const pvItemToQueue, - TickType_t xTicksToWait, - const BaseType_t xCopyPosition ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -BaseType_t MPU_xQueueReceive( QueueHandle_t xQueue, - void * const pvBuffer, - TickType_t xTicksToWait ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; -/* ----------------------------------------------------------------------------------- */ - -BaseType_t MPU_xQueuePeek( QueueHandle_t xQueue, - void * const pvBuffer, - TickType_t xTicksToWait ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -BaseType_t MPU_xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, - const void * pvTxData, - size_t xDataLengthBytes, - TickType_t xTicksToWait ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, - void * pvRxData, - size_t xBufferLengthBytes, - TickType_t xTicksToWait ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -BaseType_t MPU_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -size_t MPU_xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -BaseType_t MPU_xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, - size_t xTriggerLevel ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup, - const EventBits_t uxBitsToWaitFor, - const BaseType_t xClearOnExit, - const BaseType_t xWaitForAllBits, - TickType_t xTicksToWait ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; -/* ----------------------------------------------------------------------------------- */ - -EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup, - const EventBits_t uxBitsToClear ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup, - const EventBits_t uxBitsToSet ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup, - const EventBits_t uxBitsToSet, - const EventBits_t uxBitsToWaitFor, - TickType_t xTicksToWait ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -/* ----------------------------------------------------------------------------------- */ - -#if( INCLUDE_xTaskDelayUntil == 1 ) - -BaseType_t MPU_xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, - const TickType_t xTimeIncrement ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( INCLUDE_xTaskDelayUntil == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( INCLUDE_xTaskAbortDelay == 1 ) - -BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( INCLUDE_xTaskAbortDelay == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( INCLUDE_vTaskDelay == 1 ) - -void MPU_vTaskDelay( const TickType_t xTicksToDelay ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( INCLUDE_vTaskDelay == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( INCLUDE_uxTaskPriorityGet == 1 ) - -UBaseType_t MPU_uxTaskPriorityGet( const TaskHandle_t xTask ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( INCLUDE_uxTaskPriorityGet == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( INCLUDE_eTaskGetState == 1 ) - -eTaskState MPU_eTaskGetState( TaskHandle_t xTask ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( INCLUDE_eTaskGetState == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( INCLUDE_xTaskGetIdleTaskHandle == 1 ) - -TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( INCLUDE_vTaskSuspend == 1 ) - -void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -void MPU_vTaskResume( TaskHandle_t xTaskToResume ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( INCLUDE_vTaskSuspend == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( configGENERATE_RUN_TIME_STATS == 1 ) -configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetRunTimeCounter( const TaskHandle_t xTask ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetRunTimePercent( const TaskHandle_t xTask ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - - #if( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) -configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimePercent( void ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; -configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimeCounter( void ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - #endif /* ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) */ - -#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( configUSE_APPLICATION_TASK_TAG == 1 ) - -void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, - TaskHookFunction_t pxHookFunction ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( configUSE_APPLICATION_TASK_TAG == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) - -void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, - BaseType_t xIndex, - void * pvValue ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, - BaseType_t xIndex ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) - -UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) - -configSTACK_DEPTH_TYPE MPU_uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) - -TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) \ - */ -/* ----------------------------------------------------------------------------------- */ - -#if( INCLUDE_xTaskGetSchedulerState == 1 ) - -BaseType_t MPU_xTaskGetSchedulerState( void ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( INCLUDE_xTaskGetSchedulerState == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( configUSE_TRACE_FACILITY == 1 ) - -void MPU_vTaskGetInfo( TaskHandle_t xTask, - TaskStatus_t * pxTaskStatus, - BaseType_t xGetFreeStackSpace, - eTaskState eState ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, - const UBaseType_t uxArraySize, - configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -UBaseType_t MPU_uxEventGroupGetNumber( void * xEventGroup ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -void MPU_vEventGroupSetNumber( void * xEventGroup, UBaseType_t uxEventGroupNumber ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( configUSE_TRACE_FACILITY == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( configUSE_TASK_NOTIFICATIONS == 1 ) - -BaseType_t MPU_xTaskGenericNotifyEntry( const xTaskGenericNotifyParams_t * pxParams ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -BaseType_t MPU_xTaskGenericNotifyWaitEntry( - const xTaskGenericNotifyWaitParams_t * pxParams ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -uint32_t MPU_ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, - BaseType_t xClearCountOnExit, - TickType_t xTicksToWait ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -BaseType_t MPU_xTaskGenericNotifyStateClear( TaskHandle_t xTask, - UBaseType_t uxIndexToClear ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -uint32_t MPU_ulTaskGenericNotifyValueClear( TaskHandle_t xTask, - UBaseType_t uxIndexToClear, - uint32_t ulBitsToClear ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( configUSE_TASK_NOTIFICATIONS == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( configUSE_RECURSIVE_MUTEXES == 1 ) - -BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - - #if( INCLUDE_xSemaphoreGetMutexHolder == 1 ) - -TaskHandle_t MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - - #endif /* ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */ - -#endif /* ( configUSE_RECURSIVE_MUTEXES == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( configUSE_QUEUE_SETS == 1 ) - -QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, - const TickType_t xTicksToWait ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, - QueueSetHandle_t xQueueSet ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( configUSE_QUEUE_SETS == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( configQUEUE_REGISTRY_SIZE > 0 ) - -void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, const char * pcName ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -const char * MPU_pcQueueGetName( QueueHandle_t xQueue ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( configQUEUE_REGISTRY_SIZE > 0 ) */ -/* ----------------------------------------------------------------------------------- */ - -#if( configUSE_TIMERS == 1 ) - -void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -void MPU_vTimerSetTimerID( TimerHandle_t xTimer, void * pvNewID ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -BaseType_t MPU_xTimerGenericCommandEntry( const xTimerGenericCommandParams_t * pxParams ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -void MPU_vTimerSetReloadMode( TimerHandle_t xTimer, const BaseType_t uxAutoReload ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -BaseType_t MPU_xTimerGetReloadMode( TimerHandle_t xTimer ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -UBaseType_t MPU_uxTimerGetReloadMode( TimerHandle_t xTimer ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) - __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL; - -#endif /* ( configUSE_TIMERS == 1 ) */ -/* ----------------------------------------------------------------------------------- */ - -#endif /* MPU_PROTOTYPES_H */ diff --git a/portable/GCC/ARM_CRx_MPU/port.c b/portable/GCC/ARM_CRx_MPU/port.c index fab89eb46d..6504c92edf 100644 --- a/portable/GCC/ARM_CRx_MPU/port.c +++ b/portable/GCC/ARM_CRx_MPU/port.c @@ -44,344 +44,335 @@ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE +/* Max value that fits in a uint32_t type. */ +#define portUINT32_MAX ( ~( ( uint32_t ) 0 ) ) + +/* Check if adding a and b will result in overflow. */ +#define portADD_UINT32_WILL_OVERFLOW( a, b ) ( ( a ) > ( portUINT32_MAX - ( b ) ) ) +/* ----------------------------------------------------------------------------------- */ + /** * @brief Variable used to keep track of critical section nesting. + * * @ingroup Critical Sections - * @note - * This variable has to be stored as part of the task context and must be - * initialised to a non zero value to ensure interrupts don't inadvertently - * become unmasked before the scheduler starts. As it is stored as part of the - * task context it will be set to 0 when the first task is started. + * + * This variable is stored as part of the task context and must be initialised + * to a non zero value to ensure interrupts don't inadvertently become unmasked + * before the scheduler starts. As it is stored as part of the task context, it + * will be set to 0 when the first task is started. */ PRIVILEGED_DATA volatile UBaseType_t ulCriticalNesting = 0xFFFF; -/** @brief Set to 1 to pend a context switch from an ISR. +/** + * @brief Set to 1 to pend a context switch from an ISR. + * * @ingroup Interrupt Management */ PRIVILEGED_DATA volatile UBaseType_t ulPortYieldRequired = pdFALSE; /** * @brief Interrupt nesting depth, used to count the number of interrupts to unwind. + * * @ingroup Interrupt Management */ PRIVILEGED_DATA volatile UBaseType_t ulPortInterruptNesting = 0UL; /** * @brief Variable to track whether or not the scheduler has been started. + * * @ingroup Scheduler - * @note This is the port specific version of the Kernel's xSchedulerRunning + * + * This is the port specific version of the xSchedulerRunning in tasks.c. */ PRIVILEGED_DATA static BaseType_t prvPortSchedulerRunning = pdFALSE; /* -------------------------- Private Function Declarations -------------------------- */ /** - * @brief Determine if a FreeRTOS Task has been granted access to a memory region. - * - * @param xTaskMPURegion Pointer to a single set of MPU region registers. - * @param ulRegionStart Base address of the memory region access is being requested. - * @param ulRegionLength The length of the memory region that access is being requested. - * @param ulAccessRequested The type of access being requested, either read or write. - * @return BaseType_t pdTRUE if the task can access the region, pdFALSE otherwise + * @brief Determine if the given MPU region settings authorizes the requested + * access to the given buffer. * * @ingroup Task Context * @ingroup MPU Control + * + * @param xTaskMPURegion MPU region settings. + * @param ulBufferStart Start address of the given buffer. + * @param ulBufferLength Length of the given buffer. + * @param ulAccessRequested Access requested. + * + * @return pdTRUE if MPU region settins authorizes the requested access to the + * given buffer, pdFALSE otherwise. */ -PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion( - const xMPU_REGION_REGISTERS * xTaskMPURegion, - const uint32_t ulRegionStart, - const uint32_t ulRegionLength, - const uint32_t ulAccessRequested ); +PRIVILEGED_FUNCTION static BaseType_t prvMPURegionAuthorizesBuffer( const xMPU_REGION_REGISTERS * xTaskMPURegion, + const uint32_t ulBufferStart, + const uint32_t ulBufferLength, + const uint32_t ulAccessRequested ); /** - * @brief Determine smallest MPU Region Setting for a number of bytes. + * @brief Determine the smallest MPU Region Size Encoding for the given MPU + * region size. * * @ingroup MPU Control * - * @param ulActualSizeInBytes Number of bytes to find a valid MPU region size for. - * @return uint32_t The smallest MPU region size that can hold the requested bytes. + * @param ulActualMPURegionSize MPU region size in bytes. + * + * @return The smallest MPU Region Size Encoding for the given MPU region size. */ -PRIVILEGED_FUNCTION static uint32_t prvGetMPURegionSizeSetting( - uint32_t ulActualSizeInBytes ); +PRIVILEGED_FUNCTION static uint32_t prvGetMPURegionSizeEncoding( uint32_t ulActualMPURegionSize ); -/** @brief Set up a default MPU memory Map - * @return PRIVILEGED_FUNCTION VOID +/** + * @brief Set up MPU. + * * @ingroup MPU Control - * @note This function shall be called before calling vPortStartFirstTask(). - * @note This function works by pulling variables from the linker script. - * Ensure that the variables used in your linker script match up with the variable names - * used at the start of this function. */ PRIVILEGED_FUNCTION static void prvSetupMPU( void ); +/* -------------------------- Exported Function Declarations -------------------------- */ + /** - * @brief Determine if a FreeRTOS Task has been granted access to a memory region. + * @brief Enter critical section. * - * @param xTaskMPURegion Pointer to a single set of MPU region registers. - * @param ulRegionStart Base address of the memory region access is being requested. - * @param ulRegionLength The length of the memory region that access is being requested. - * @param ulAccessRequested The type of access being requested, either read or write. - * @return BaseType_t pdTRUE if the task can access the region, pdFALSE otherwise + * @ingroup Critical Section + */ +PRIVILEGED_FUNCTION void vPortEnterCritical( void ); + +/** + * @brief Exit critical section. * - * @ingroup Task Context - * @ingroup MPU Control + * @ingroup Critical Section */ -PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion( - const xMPU_REGION_REGISTERS * xTaskMPURegion, - const uint32_t ulRegionStart, - const uint32_t ulRegionLength, - const uint32_t ulAccessRequested ); +PRIVILEGED_FUNCTION void vPortExitCritical( void ); /* ----------------------------------------------------------------------------------- */ /** - * @brief Set a FreeRTOS Task's initial context. - * - * @param pxTopOfStack Pointer to where the task's stack starts. - * @param pxCode Pointer to the function a task will run. - * @param pvParameters Pointer to any arguments to be passed to the task's function. - * @param xRunPrivileged Marks if the task is to be run in a privileged CPU mode. - * @param xMPUSettings MPU settings to be loaded as part of a task's context. - * @return StackType_t* Pointer to where to restore the task's context from. + * @brief Setup a FreeRTOS task's initial context. * * @ingroup Task Context - * @note pxTopOfStack must be a region of memory that is a valid MPU region size. + * + * @param pxTopOfStack Top of stack. + * @param pxCode The task function. + * @param pvParameters Argument passed to the task function. + * @param xRunPrivileged Marks if the task is privileged. + * @param xMPUSettings MPU settings of the task. + * + * @return Location where to restore the task's context from. */ -/* PRIVILEGED_FUNCTION */ StackType_t * pxPortInitialiseStack( - StackType_t * pxTopOfStack, - TaskFunction_t pxCode, - void * pvParameters, - BaseType_t xRunPrivileged, - xMPU_SETTINGS * xMPUSettings ) +/* PRIVILEGED_FUNCTION */ +StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + TaskFunction_t pxCode, + void * pvParameters, + BaseType_t xRunPrivileged, + xMPU_SETTINGS * xMPUSettings ) { - /** Setup the initial context of the task. The context is set exactly as - * expected by the portRESTORE_CONTEXT() macro and as described above the - * MAX_CONTEXT_SIZE declaration in portmacro_asm.h */ - UBaseType_t ulIndex = MAX_CONTEXT_SIZE - 1U; + /* Setup the initial context of the task. The context is set exactly as + * expected by the portRESTORE_CONTEXT() macro. */ + UBaseType_t ulIndex = CONTEXT_SIZE - 1U; xSYSTEM_CALL_STACK_INFO * xSysCallInfo = NULL; - if( pdTRUE == xRunPrivileged ) + if( xRunPrivileged == pdTRUE ) { - /* Current Program Status Register (CPSR) */ xMPUSettings->ulTaskFlags |= portTASK_IS_PRIVILEGED_FLAG; + /* Current Program Status Register (CPSR). */ xMPUSettings->ulContext[ ulIndex ] = SYS_MODE; } else { - /* Current Program Status Register (CPSR) */ xMPUSettings->ulTaskFlags &= ( ~portTASK_IS_PRIVILEGED_FLAG ); + /* Current Program Status Register (CPSR). */ xMPUSettings->ulContext[ ulIndex ] = USER_MODE; } - if( 0x0UL != ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) ) + if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x0UL ) { - /* The task will start in THUMB mode, set the bit in the CPSR. */ + /* The task will cause the processor to start in THUMB state, set the + * Thumb state bit in the CPSR. */ xMPUSettings->ulContext[ ulIndex ] |= portTHUMB_MODE_BIT; } - /* Decrement ulIndex here after setting the CPSR */ ulIndex--; - /** Set Task Program Counter to provided Task Function */ - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) pxCode; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) pxCode; /* PC. */ ulIndex--; - /** A FreeRTOS Task is not designed to return or exit from its function. - * As such a default Link Register is provided that will return to an - * error handling function. */ - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) portTASK_RETURN_ADDRESS; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */ ulIndex--; - /** CPU Stack Grows up, set Task's Stack Pointer's to bottom of stack */ - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) pxTopOfStack; /* SP */ + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) pxTopOfStack; /* SP. */ ulIndex--; - /* Next the General Purpose Registers */ - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x12121212; /* R12 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x11111111; /* R11 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x10101010; /* R10 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x09090909; /* R9 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x08080808; /* R8 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x07070707; /* R7 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x06060606; /* R6 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x05050505; /* R5 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x04040404; /* R4 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x03030303; /* R3 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x02020202; /* R2 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x01010101; /* R1 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) pvParameters; /* R0 */ - ulIndex--; - -#ifdef portENABLE_FPU - /* Initial Floating Point Context is the Floating Point Registers (FPRs) */ - /* There are 16 Double FPRs, D0-D15 on the Cortex-R FPU enabled chips */ - /* These map to the Single Precision FPRs, S0-S31 */ - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000015; /* S31 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1500000; /* S30 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000014; /* S29 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1400000; /* S28 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000013; /* S27 */ + /* General Purpose Registers. */ + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x12121212; /* R12. */ ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1300000; /* S26 */ + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x11111111; /* R11. */ ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000012; /* S25 */ + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x10101010; /* R10. */ ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1200000; /* S24 */ + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x09090909; /* R9. */ ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000011; /* S23 */ + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x08080808; /* R8. */ ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1100000; /* S22 */ + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x07070707; /* R7. */ ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000010; /* S21 */ + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x06060606; /* R6. */ ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1000000; /* S20 */ + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x05050505; /* R5. */ ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000009; /* S19 */ + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x04040404; /* R4. */ ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD9000000; /* S18 */ + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x03030303; /* R3. */ ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000008; /* S17 */ + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x02020202; /* R2. */ ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD8000000; /* S16 */ + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x01010101; /* R1. */ ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000007; /* S15 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD7000000; /* S14 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000006; /* S13 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD6000000; /* S12 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000005; /* S11 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD5000000; /* S10 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000004; /* S9 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD4000000; /* S8 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000003; /* S7 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD3000000; /* S6 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000002; /* S5 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD2000000; /* S4 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000001; /* S3 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1000000; /* S2 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000000; /* S1 */ - ulIndex--; - xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000000; /* S0 */ + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) pvParameters; /* R0. */ ulIndex--; - /* Floating Point Status and Control Register */ - xMPUSettings->ulContext[ ulIndex-- ] = ( StackType_t ) 0x00000000; /* FPSR */ -#endif /* portENABLE_FPU */ + #if( portENABLE_FPU == 1 ) + { + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000015; /* S31. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1500000; /* S30. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000014; /* S29. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1400000; /* S28. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000013; /* S27. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1300000; /* S26. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000012; /* S25. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1200000; /* S24. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000011; /* S23. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1100000; /* S22. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000010; /* S21. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1000000; /* S20. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000009; /* S19. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD9000000; /* S18. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000008; /* S17. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD8000000; /* S16. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000007; /* S15. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD7000000; /* S14. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000006; /* S13. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD6000000; /* S12. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000005; /* S11. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD5000000; /* S10. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000004; /* S9. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD4000000; /* S8. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000003; /* S7. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD3000000; /* S6. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000002; /* S5. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD2000000; /* S4. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000001; /* S3. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1000000; /* S2. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000000; /* S1. */ + ulIndex--; + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000000; /* S0. */ + ulIndex--; + + xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x00000000; /* FPSR. */ + ulIndex--; + } + #endif /* portENABLE_FPU */ /* The task will start with a critical nesting count of 0. */ xMPUSettings->ulContext[ ulIndex ] = portNO_CRITICAL_NESTING; /* Ensure that the system call stack is double word aligned. */ xSysCallInfo = &( xMPUSettings->xSystemCallStackInfo ); - xSysCallInfo->pulSystemCallStackPointer = &( - xSysCallInfo->ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE - 1U ] ); - - xSysCallInfo->pulSystemCallStackPointer = - ( uint32_t * ) ( ( uint32_t ) ( xSysCallInfo->pulSystemCallStackPointer ) - & ( uint32_t ) ( ~( portBYTE_ALIGNMENT_MASK ) ) ); + xSysCallInfo->pulSystemCallStackPointer = &( xSysCallInfo->ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE - 1U ] ); + xSysCallInfo->pulSystemCallStackPointer = ( uint32_t * ) ( ( ( uint32_t ) ( xSysCallInfo->pulSystemCallStackPointer ) ) & + ( ( uint32_t ) ( ~( portBYTE_ALIGNMENT_MASK ) ) ) ); /* This is not NULL only for the duration of a system call. */ xSysCallInfo->pulTaskStackPointer = NULL; - /* Set the System Call LR to go directly to vPortSystemCallExit */ - xSysCallInfo->pulSystemCallLinkRegister = &vPortSystemCallExit; + /* Set the System Call to return to vPortSystemCallExit. */ + xSysCallInfo->pulSystemCallExitAddress = ( uint32_t * ) ( &vPortSystemCallExit ); - /* Return the address where the context of this task should be restored from */ - return ( &xMPUSettings->ulContext[ ulIndex ] ); + /* Return the address where this task's context should be restored from. */ + return &( xMPUSettings->ulContext[ ulIndex ] ); } /* ----------------------------------------------------------------------------------- */ /** - * @brief Stores a FreeRTOS Task's MPU Settings in its TCB. - * - * @param xMPUSettings The memory location in the TCB to store MPU settings - * @param xRegions The MPU settings being requested by the task. - * @param pxBottomOfStack The base address of the Task's Stack - * @param ulStackDepth The length of the task's stack. + * @brief Store a FreeRTOS task's MPU settings in its TCB. * * @ingroup Task Context * @ingroup MPU Control * - * @note pxBottomOfStack must be aligned to a region size of length ulStackDepth. - * @note ulStackDepth must be a power of 2 larger than 32 bytes. + * @param xMPUSettings The MPU settings in TCB. + * @param xRegions The updated MPU settings requested by the task. + * @param pxBottomOfStack The base address of the task's Stack. + * @param ulStackDepth The length of the task's stack. */ -/* PRIVILEGED_FUNCTION */ void vPortStoreTaskMPUSettings( - xMPU_SETTINGS * xMPUSettings, - const struct xMEMORY_REGION * const xRegions, - StackType_t * pxBottomOfStack, - uint32_t ulStackDepth ) +/* PRIVILEGED_FUNCTION */ +void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, + const struct xMEMORY_REGION * const xRegions, + StackType_t * pxBottomOfStack, + uint32_t ulStackDepth ) { -#if defined( __ARMCC_VERSION ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __SRAM_segment_start__; + extern uint32_t * __SRAM_segment_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __SRAM_segment_start__[]; + extern uint32_t __SRAM_segment_end__[]; + #endif /* if defined( __ARMCC_VERSION ) */ - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - extern uint32_t * __SRAM_segment_start__; - extern uint32_t * __SRAM_segment_end__; -#else - /* Declaration when these variable are exported from linker scripts. */ - extern uint32_t __SRAM_segment_start__[]; - extern uint32_t __SRAM_segment_end__[]; - -#endif /* if defined( __ARMCC_VERSION ) */ uint32_t ulIndex = 0x0; - uint32_t ulRegionStart; - uint32_t ulRegionEnd; - uint32_t ulRegionLen; - uint32_t ulAlignment; - - /* Allow Read/Write from User and Privileged modes */ - uint32_t ulRegionAttr = portMPU_PRIV_RW_USER_RW_NOEXEC - | portMPU_NORMAL_OIWTNOWA_SHARED; + uint32_t ulRegionLength; + uint32_t ulRegionLengthEncoded; + uint32_t ulRegionLengthDecoded; - if( NULL == xRegions ) + if( xRegions == NULL ) { /* No MPU regions are specified so allow access to all of the RAM. */ - ulRegionStart = ( uint32_t ) __SRAM_segment_start__; - ulRegionEnd = ( uint32_t ) __SRAM_segment_end__; - ulRegionLen = ulRegionEnd - ulRegionStart; - ulRegionLen = prvGetMPURegionSizeSetting( ulRegionLen ); - ulRegionLen |= portMPU_REGION_ENABLE; - - /* MPU Settings is zero'd out in the TCB before reaching this function. - * Set this region as the highest configurable MPU Region so it overrides - * the lower unused regions. - */ - ulIndex = portNUM_CONFIGURABLE_REGIONS; - - xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = ulRegionStart; - xMPUSettings->xRegion[ ulIndex ].ulRegionSize = ulRegionLen; - xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = ulRegionAttr; + ulRegionLength = ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__; + ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength ); + ulRegionLength |= portMPU_REGION_ENABLE; + + /* MPU Settings is zero'd out in the TCB before this function is called. + * We, therefore, do not need to explicitly zero out unused MPU regions + * in xMPUSettings. */ + ulIndex = portSTACK_REGION; + + xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = ( uint32_t ) __SRAM_segment_start__; + xMPUSettings->xRegion[ ulIndex ].ulRegionSize = ( ulRegionLengthEncoded | + portMPU_REGION_ENABLE ); + xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = ( portMPU_REGION_PRIV_RW_USER_RW_NOEXEC | + portMPU_REGION_NORMAL_OIWTNOWA_SHARED ); } else { @@ -390,81 +381,61 @@ PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion( /* If a length has been provided, the region is in use. */ if( ( xRegions[ ulIndex ] ).ulLengthInBytes > 0UL ) { - ulRegionStart = ( uint32_t ) xRegions[ ulIndex ].pvBaseAddress; - ulRegionAttr = xRegions[ ulIndex ].ulParameters; - - ulRegionLen = xRegions[ ulIndex ].ulLengthInBytes; - ulRegionLen = prvGetMPURegionSizeSetting( ulRegionLen ); - ulRegionLen |= portMPU_REGION_ENABLE; - - /* MPU Regions must be aligned to a power of 2 equal to length */ - ulAlignment = 2UL << ( ulRegionLen >> 1UL ); - configASSERT( 0U == ( ulRegionStart % 2UL ) ); - configASSERT( 0U == ( ulRegionStart % ( ulAlignment ) ) ); + ulRegionLength = xRegions[ ulIndex ].ulLengthInBytes; + ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength ); + + /* MPU region base address must be aligned to the region size + * boundary. */ + ulRegionLengthDecoded = 2UL << ( ulRegionLengthEncoded >> 1UL ); + configASSERT( ( ( ( uint32_t ) xRegions[ ulIndex ].pvBaseAddress ) % ( ulRegionLengthDecoded ) ) == 0UL ); + + xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = ( uint32_t ) xRegions[ ulIndex ].pvBaseAddress; + xMPUSettings->xRegion[ ulIndex ].ulRegionSize = ( ulRegionLengthEncoded | + portMPU_REGION_ENABLE ); + xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = xRegions[ ulIndex ].ulParameters; } else { - /* Otherwise ensure the region is zero'd out */ - ulRegionStart = 0x0UL; - ulRegionLen = 0x0UL; - ulRegionAttr = 0x0UL; + xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = 0x0UL; + xMPUSettings->xRegion[ ulIndex ].ulRegionSize = 0x0UL; + xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = 0x0UL; } - - xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = ulRegionStart; - xMPUSettings->xRegion[ ulIndex ].ulRegionSize = ulRegionLen; - xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = ulRegionAttr; } + /* This function is called automatically when the task is created - in * which case the stack region parameters will be valid. At all other * times the stack parameters will not be valid and it is assumed that the * stack region has already been configured. */ - - /* Cannot have a task stack of size 0 */ - if( 0x0UL != ulStackDepth ) + if( ulStackDepth != 0x0UL ) { - /* Define the region that allows access to the stack. */ - ulRegionStart = ( uint32_t ) pxBottomOfStack; - ulRegionAttr = portMPU_PRIV_RW_USER_RW_NOEXEC - | portMPU_NORMAL_OIWTNOWA_SHARED; - ulRegionLen = prvGetMPURegionSizeSetting( ulStackDepth << 2UL ); - ulRegionLen |= portMPU_REGION_ENABLE; - - /* MPU Regions must be aligned to a power of 2 equal to length */ - ulAlignment = 2UL << ( ulRegionLen >> 1UL ); - configASSERT( 0U == ( ulRegionStart % 2UL ) ); - configASSERT( 0U == ( ulRegionStart % ( ulAlignment ) ) ); - - /* xRegion[portNUM_CONFIGURABLE_REGIONS] is the Task Stack */ - ulIndex = portNUM_CONFIGURABLE_REGIONS; - - xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = ulRegionStart; - xMPUSettings->xRegion[ ulIndex ].ulRegionSize = ulRegionLen; - xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = ulRegionAttr; + ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ); + + /* MPU region base address must be aligned to the region size + * boundary. */ + ulRegionLengthDecoded = 2UL << ( ulRegionLengthEncoded >> 1UL ); + configASSERT( ( ( uint32_t ) pxBottomOfStack % ( ulRegionLengthDecoded ) ) == 0U ); + + ulIndex = portSTACK_REGION; + xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = ( uint32_t ) pxBottomOfStack; + xMPUSettings->xRegion[ ulIndex ].ulRegionSize = ( ulRegionLengthEncoded | + portMPU_REGION_ENABLE );; + xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = ( portMPU_REGION_PRIV_RW_USER_RW_NOEXEC | + portMPU_REGION_NORMAL_OIWTNOWA_SHARED ); } } } /* ----------------------------------------------------------------------------------- */ -/** - * @brief Determine if the FreeRTOS Task was created as a privileged task. - * - * @ingroup MPU Control - * @ingroup Task Context - * - * @return pdTRUE if the Task was created as a privileged task. - * pdFALSE if the task was not created as a privileged task. - * - */ -/* PRIVILEGED_FUNCTION */ BaseType_t xPortIsTaskPrivileged( void ) +/* PRIVILEGED_FUNCTION */ +BaseType_t xPortIsTaskPrivileged( void ) { BaseType_t xTaskIsPrivileged = pdFALSE; /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); - if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) - == portTASK_IS_PRIVILEGED_FLAG ) + if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) { xTaskIsPrivileged = pdTRUE; } @@ -472,29 +443,20 @@ PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion( return xTaskIsPrivileged; } -/** - * @brief Start the System Tick Timer, starting the FreeRTOS-Kernel. - * - * @ingroup Scheduler - * @return BaseType_t This function is not meant to be returned from. - * If it does return it returns pdFALSE to mark that the scheduler - * could not be started. - */ -/* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) +/* ----------------------------------------------------------------------------------- */ + +/* PRIVILEGED_FUNCTION */ +BaseType_t xPortStartScheduler( void ) { /* Start the timer that generates the tick ISR. */ configSETUP_TICK_INTERRUPT(); - /* Reset the critical section nesting count read to execute the first task. */ - ulCriticalNesting = 0UL; - - /* Configure the regions in the MPU that are common to all tasks. */ + /* Configure MPU regions that are common to all tasks. */ prvSetupMPU(); - /* Mark the port specific scheduler running variable as true */ prvPortSchedulerRunning = pdTRUE; - /* Load the context of the first task, starting the FreeRTOS-Scheduler's control. */ + /* Load the context of the first task. */ vPortStartFirstTask(); /* Will only get here if vTaskStartScheduler() was called with the CPU in @@ -508,15 +470,15 @@ PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion( /* ----------------------------------------------------------------------------------- */ -/* PRIVILEGED_FUNCTION */ static uint32_t prvGetMPURegionSizeSetting( - uint32_t ulActualSizeInBytes ) +/* PRIVILEGED_FUNCTION */ +static uint32_t prvGetMPURegionSizeEncoding( uint32_t ulActualMPURegionSize ) { uint32_t ulRegionSize, ulReturnValue = 4U; - /* 32 bytes is the smallest valid region for Cortex R4 and R5 CPUs */ + /* 32 bytes is the smallest valid region for Cortex R4 and R5 CPUs. */ for( ulRegionSize = 0x20UL; ulReturnValue < 0x1FUL; ( ulRegionSize <<= 1UL ) ) { - if( ulActualSizeInBytes <= ulRegionSize ) + if( ulActualMPURegionSize <= ulRegionSize ) { break; } @@ -533,181 +495,172 @@ PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion( /* ----------------------------------------------------------------------------------- */ -/* PRIVILEGED_FUNCTION */ static void prvSetupMPU( void ) +/* PRIVILEGED_FUNCTION */ +static void prvSetupMPU( void ) { #if defined( __ARMCC_VERSION ) /* Declaration when these variable are defined in code. */ - /* Sections used for FLASH */ + /* Sections used for FLASH. */ extern uint32_t * __FLASH_segment_start__; extern uint32_t * __FLASH_segment_end__; extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_end__; - /* Sections used for RAM */ + /* Sections used for RAM. */ extern uint32_t * __SRAM_segment_start__; extern uint32_t * __SRAM_segment_end__; extern uint32_t * __privileged_data_start__; extern uint32_t * __privileged_data_end__; - #else /* Declaration when these variable are exported from linker scripts. */ - /* Sections used for FLASH */ + /* Sections used for FLASH. */ extern uint32_t __FLASH_segment_start__[]; extern uint32_t __FLASH_segment_end__[]; extern uint32_t __privileged_functions_start__[]; extern uint32_t __privileged_functions_end__[]; - /* Sections used for RAM */ + /* Sections used for RAM. */ extern uint32_t __SRAM_segment_start__[]; extern uint32_t __SRAM_segment_end__[]; extern uint32_t __privileged_data_start__[]; extern uint32_t __privileged_data_end__[]; - #endif /* if defined( __ARMCC_VERSION ) */ - uint32_t ulRegionStart; - uint32_t ulRegionEnd; + uint32_t ulRegionLength; + uint32_t ulRegionLengthEncoded; - /* Ensure the MPU is disabled */ + /* Disable the MPU before programming it. */ vMPUDisable(); - /* Unprivileged and Privileged Read and Exec MPU Region for Flash */ - ulRegionStart = ( uint32_t ) __FLASH_segment_start__; - ulRegionEnd = ( uint32_t ) __FLASH_segment_end__; - ulRegionLength = ulRegionEnd - ulRegionStart; - ulRegionLength = prvGetMPURegionSizeSetting( ulRegionLength ); - ulRegionLength |= portMPU_REGION_ENABLE; - + /* Priv: RX, Unpriv: RX for entire Flash. */ + ulRegionLength = ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__; + ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength ); vMPUSetRegion( portUNPRIVILEGED_FLASH_REGION, - ulRegionStart, - ulRegionLength, - portMPU_PRIV_RO_USER_RO_EXEC | portMPU_NORMAL_OIWTNOWA_SHARED ); - - /* Privileged Read and Exec MPU Region for PRIVILEGED_FUNCTIONS. */ - ulRegionStart = ( uint32_t ) __privileged_functions_start__; - ulRegionEnd = ( uint32_t ) __privileged_functions_end__; - ulRegionLength = ulRegionEnd - ulRegionStart; - ulRegionLength = prvGetMPURegionSizeSetting( ulRegionLength ); - ulRegionLength |= portMPU_REGION_ENABLE; - + ( uint32_t ) __FLASH_segment_start__, + ( ulRegionLengthEncoded | portMPU_REGION_ENABLE ), + ( portMPU_REGION_PRIV_RO_USER_RO_EXEC | + portMPU_REGION_NORMAL_OIWTNOWA_SHARED ) ); + + /* Priv: RX, Unpriv: No access for privileged functions. */ + ulRegionLength = ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__; + ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength ); vMPUSetRegion( portPRIVILEGED_FLASH_REGION, - ulRegionStart, - ulRegionLength, - portMPU_PRIV_RO_USER_NA_EXEC | portMPU_NORMAL_OIWTNOWA_SHARED ); - - /* Privileged Write and Read Access for PRIVILEGED_DATA. */ - ulRegionStart = ( uint32_t ) __privileged_data_start__; - ulRegionEnd = ( uint32_t ) __privileged_data_end__; - ulRegionLength = ulRegionEnd - ulRegionStart; - ulRegionLength = prvGetMPURegionSizeSetting( ulRegionLength ); - ulRegionLength |= portMPU_REGION_ENABLE; - + ( uint32_t ) __privileged_functions_start__, + ( ulRegionLengthEncoded | portMPU_REGION_ENABLE ), + ( portMPU_REGION_PRIV_RO_USER_NA_EXEC | + portMPU_REGION_NORMAL_OIWTNOWA_SHARED ) ); + + /* Priv: RW, Unpriv: No Access for privileged data. */ + ulRegionLength = ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__; + ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength ); vMPUSetRegion( portPRIVILEGED_RAM_REGION, - ulRegionStart, - ulRegionLength, - portMPU_PRIV_RW_USER_NA_NOEXEC | portMPU_NORMAL_OIWTNOWA_SHARED ); + ( uint32_t ) __privileged_data_start__, + ( ulRegionLengthEncoded | portMPU_REGION_ENABLE ), + ( portMPU_REGION_PRIV_RW_USER_NA_NOEXEC | + portMPU_REGION_PRIV_RW_USER_NA_NOEXEC ) ); - /* Enable the MPU Background region, allows privileged operating modes access to - * unmapped regions of memory without generating a fault. */ + /* Enable the MPU background region - it allows privileged operating modes + * access to unmapped regions of memory without generating a fault. */ vMPUEnableBackgroundRegion(); - /* After setting default regions, enable the MPU */ + /* After setting default regions, enable the MPU. */ vMPUEnable(); } /* ----------------------------------------------------------------------------------- */ -/* PRIVILEGED_FUNCTION */ static BaseType_t prvTaskCanAccessRegion( - const xMPU_REGION_REGISTERS * xTaskMPURegion, - const uint32_t ulRegionStart, - const uint32_t ulRegionLength, - const uint32_t ulAccessRequested ) +/* PRIVILEGED_FUNCTION */ +static BaseType_t prvMPURegionAuthorizesBuffer( const xMPU_REGION_REGISTERS * xTaskMPURegion, + const uint32_t ulBufferStart, + const uint32_t ulBufferLength, + const uint32_t ulAccessRequested ) { - BaseType_t xAccessGranted; - uint32_t ulRegionEnd = ulRegionStart + ulRegionLength; - - /* Get Region Size value in words, need to clear the enable bit */ - uint32_t ulTaskRegionLength = 2UL << ( xTaskMPURegion->ulRegionSize >> 1UL ); - uint32_t ulTaskRegionEnd = xTaskMPURegion->ulRegionBaseAddress + ulTaskRegionLength; - - /* Perform three different checks: - * 1. Ensure region being accessed is after the start of an MPU Region - * 2. Ensure region being accessed is before the end of the MPU Region - * 3. Ensure region being accessed ends after the start of the MPU region */ - if( ( ulRegionStart >= xTaskMPURegion->ulRegionBaseAddress ) - && ( ulRegionEnd <= ulTaskRegionEnd ) && ( ulRegionEnd >= ulRegionStart ) ) + BaseType_t xAccessGranted = pdFALSE; + uint32_t ulBufferEnd; + uint32_t ulMPURegionLength; + uint32_t ulMPURegionStart; + uint32_t ulMPURegionEnd; + uint32_t ulMPURegionAccessPermissions; + + if( portADD_UINT32_WILL_OVERFLOW( ulBufferStart, ( ulBufferLength - 1UL ) ) == pdFALSE ) { - /* Unprivileged read is MPU Ctrl Access Bit Value bX1X */ - if( ( tskMPU_READ_PERMISSION == ulAccessRequested ) - && ( ( portMPU_PRIV_RW_USER_RO_NOEXEC ) &xTaskMPURegion->ulRegionAttribute ) ) + ulBufferEnd = ulBufferStart + ulBufferLength - 1UL; + ulMPURegionLength = 2UL << ( xTaskMPURegion->ulRegionSize >> 1UL ); + ulMPURegionStart = xTaskMPURegion->ulRegionBaseAddress; + ulMPURegionEnd = xTaskMPURegion->ulRegionBaseAddress + ulMPURegionLength - 1UL; + + if( ( ulBufferStart >= ulMPURegionStart ) && + ( ulBufferEnd <= ulMPURegionEnd ) && + ( ulBufferStart <= ulBufferEnd ) ) { - xAccessGranted = pdTRUE; - } + ulMPURegionAccessPermissions = xTaskMPURegion->ulRegionAttribute & portMPU_REGION_AP_BITMASK; - /* Unprivileged Write is MPU Ctrl Access Bit Value b011 */ - else if( ( tskMPU_WRITE_PERMISSION & ulAccessRequested ) - && ( xTaskMPURegion->ulRegionAttribute & portMPU_PRIV_RW_USER_RW_NOEXEC ) - == ( portMPU_PRIV_RW_USER_RW_NOEXEC ) ) - { - xAccessGranted = pdTRUE; - } - - else - { - xAccessGranted = pdFALSE; + if( ulAccessRequested == tskMPU_READ_PERMISSION ) /* RO. */ + { + if( ( ulMPURegionAccessPermissions == portMPU_REGION_PRIV_RW_USER_RO ) || + ( ulMPURegionAccessPermissions == portMPU_REGION_PRIV_RO_USER_RO ) ) + { + xAccessGranted = pdTRUE; + } + } + else if( ( ulAccessRequested & tskMPU_WRITE_PERMISSION ) != 0UL ) /* W or RW. */ + { + if( ulMPURegionAccessPermissions == portMPU_REGION_PRIV_RW_USER_RW ) + { + xAccessGranted = pdTRUE; + } + } } } - else - { - xAccessGranted = pdFALSE; - } return xAccessGranted; } /* ----------------------------------------------------------------------------------- */ -/* PRIVILEGED_FUNCTION */ BaseType_t xPortIsAuthorizedToAccessBuffer( - const void * pvBuffer, - uint32_t ulBufferLength, - uint32_t ulAccessRequested ) +/* PRIVILEGED_FUNCTION */ +BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer, + uint32_t ulBufferLength, + uint32_t ulAccessRequested ) { - BaseType_t xAccessGranted; - - /* Calling task's MPU settings. */ + BaseType_t xAccessGranted = pdFALSE; + uint32_t ulRegionIndex; xMPU_SETTINGS * xTaskMPUSettings = NULL; - xMPU_REGION_REGISTERS * xTaskMPURegion = NULL; - if( pdFALSE == prvPortSchedulerRunning ) + if( prvPortSchedulerRunning == pdFALSE ) { - /* Before the scheduler starts an unknown task will be pxCurrentTCB */ + /* Grant access to all the memory before the scheduler is started. It is + * necessary because there is no task running yet and therefore, we + * cannot use the permissions of any task. */ xAccessGranted = pdTRUE; } else { - /* Only way to receive a NULL here is if no task has been created, - * but the scheduler has been started. */ + /* Calling task's MPU settings. */ xTaskMPUSettings = xTaskGetMPUSettings( NULL ); - if( xTaskMPUSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) + if( ( xTaskMPUSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) { - /* If a task is privileged it is assumed that it can access the buffer */ + /* Privileged tasks have access to all the memory. */ xAccessGranted = pdTRUE; } else { - uint32_t ulRegionIndex = 0x0UL; - do + for( ulRegionIndex = 0x0UL; ulRegionIndex < portTOTAL_NUM_REGIONS_IN_TCB; ulRegionIndex++ ) { - xTaskMPURegion = &( xTaskMPUSettings->xRegion[ ulRegionIndex++ ] ); - xAccessGranted = prvTaskCanAccessRegion( xTaskMPURegion, - ( uint32_t ) pvBuffer, - ulBufferLength, - ulAccessRequested ); - } while( ( ulRegionIndex < portTOTAL_NUM_REGIONS_IN_TCB ) - && ( pdFALSE == xAccessGranted ) ); + xAccessGranted = prvMPURegionAuthorizesBuffer( &( xTaskMPUSettings->xRegion[ ulRegionIndex ] ), + ( uint32_t ) pvBuffer, + ulBufferLength, + ulAccessRequested ); + + if( xAccessGranted == pdTRUE ) + { + break; + } + } } } + return xAccessGranted; } @@ -715,14 +668,14 @@ PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion( #if( configENABLE_ACCESS_CONTROL_LIST == 1 ) -/* PRIVILEGED_FUNCTION */ BaseType_t xPortIsAuthorizedToAccessKernelObject( - int32_t lInternalIndexOfKernelObject ) +/* PRIVILEGED_FUNCTION */ +BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject ) { uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit; BaseType_t xAccessGranted = pdFALSE; const xMPU_SETTINGS * xTaskMpuSettings; - if( pdFALSE == prvPortSchedulerRunning ) + if( prvPortSchedulerRunning == pdFALSE ) { /* Grant access to all the kernel objects before the scheduler * is started. It is necessary because there is no task running @@ -740,16 +693,14 @@ PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion( ulAccessControlListEntryBit = ( ( uint32_t ) lInternalIndexOfKernelObject % portACL_ENTRY_SIZE_BITS ); - if( portTASK_IS_PRIVILEGED_FLAG - == ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) ) + if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) { xAccessGranted = pdTRUE; } else { - if( ( 1U << ulAccessControlListEntryBit ) - & ( xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] ) - != 0UL ) + if( ( ( xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] ) & + ( 1U << ulAccessControlListEntryBit ) ) != 0UL ) { xAccessGranted = pdTRUE; } @@ -759,9 +710,27 @@ PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion( return xAccessGranted; } -/* PRIVILEGED_FUNCTION */ void vPortGrantAccessToKernelObject( - TaskHandle_t xInternalTaskHandle, - int32_t lInternalIndexOfKernelObject ) +#else + +/* PRIVILEGED_FUNCTION */ +BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject ) +{ + ( void ) lInternalIndexOfKernelObject; + + /* If Access Control List feature is not used, all the tasks have + * access to all the kernel objects. */ + return pdTRUE; +} + +#endif /* #if ( configENABLE_ACCESS_CONTROL_LIST == 1 ) */ + +/* ----------------------------------------------------------------------------------- */ + +#if( configENABLE_ACCESS_CONTROL_LIST == 1 ) + +/* PRIVILEGED_FUNCTION */ +void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle, + int32_t lInternalIndexOfKernelObject ) { uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit; xMPU_SETTINGS * xTaskMpuSettings; @@ -773,13 +742,18 @@ PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion( xTaskMpuSettings = xTaskGetMPUSettings( xInternalTaskHandle ); - xTaskMpuSettings->ulAccessControlList - [ ulAccessControlListEntryIndex ] |= ( 1U << ulAccessControlListEntryBit ); + xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] |= ( 1U << ulAccessControlListEntryBit ); } -/* PRIVILEGED_FUNCTION */ void vPortRevokeAccessToKernelObject( - TaskHandle_t xInternalTaskHandle, - int32_t lInternalIndexOfKernelObject ) +#endif /* #if ( configENABLE_ACCESS_CONTROL_LIST == 1 ) */ + +/* ----------------------------------------------------------------------------------- */ + +#if( configENABLE_ACCESS_CONTROL_LIST == 1 ) + +/* PRIVILEGED_FUNCTION */ +void vPortRevokeAccessToKernelObject( TaskHandle_t xInternalTaskHandle, + int32_t lInternalIndexOfKernelObject ) { uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit; xMPU_SETTINGS * xTaskMpuSettings; @@ -791,20 +765,7 @@ PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion( xTaskMpuSettings = xTaskGetMPUSettings( xInternalTaskHandle ); - xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] &= ~( - 1U << ulAccessControlListEntryBit ); -} - -#else - -/* PRIVILEGED_FUNCTION */ BaseType_t xPortIsAuthorizedToAccessKernelObject( - int32_t lInternalIndexOfKernelObject ) -{ - ( void ) lInternalIndexOfKernelObject; - - /* If Access Control List feature is not used, all the tasks have - * access to all the kernel objects. */ - return pdTRUE; + xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] &= ~( 1U << ulAccessControlListEntryBit ); } #endif /* #if ( configENABLE_ACCESS_CONTROL_LIST == 1 ) */ @@ -831,9 +792,52 @@ void prvTaskExitError( void ) void vPortEndScheduler( void ) { prvPortSchedulerRunning = pdFALSE; - /* Not implemented in ports where there is nothing to return to. - * Artificially force an assert. */ - configASSERT( prvPortSchedulerRunning ); + + /* Not implemented in this port. Artificially force an assert. */ + configASSERT( prvPortSchedulerRunning == pdTRUE ); } /* ----------------------------------------------------------------------------------- */ + +/* PRIVILEGED_FUNCTION */ +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + + /* Now that interrupts are disabled, ulCriticalNesting can be accessed + * directly. Increment ulCriticalNesting to keep a count of how many times + * portENTER_CRITICAL() has been called. */ + ulCriticalNesting++; + + /* This is not the interrupt safe version of the enter critical function so + * assert() if it is being called from an interrupt context. Only API + * functions that end in "FromISR" can be used in an interrupt. Only assert + * if the critical nesting count is 1 to protect against recursive calls if + * the assert function also uses a critical section. */ + if( ulCriticalNesting == 1 ) + { + configASSERT( ulPortInterruptNesting == 0 ); + } +} +/*-----------------------------------------------------------*/ + +/* PRIVILEGED_FUNCTION */ +void vPortExitCritical( void ) +{ + if( ulCriticalNesting > portNO_CRITICAL_NESTING ) + { + /* Decrement the nesting count as the critical section is being + * exited. */ + ulCriticalNesting--; + + /* If the nesting level has reached zero then all interrupt + * priorities must be re-enabled. */ + if( ulCriticalNesting == portNO_CRITICAL_NESTING ) + { + /* Critical nesting has reached zero so all interrupt priorities + * should be unmasked. */ + portENABLE_INTERRUPTS(); + } + } +} +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CRx_MPU/portASM.S b/portable/GCC/ARM_CRx_MPU/portASM.S index 5ebc8b2b0f..b9cb955402 100644 --- a/portable/GCC/ARM_CRx_MPU/portASM.S +++ b/portable/GCC/ARM_CRx_MPU/portASM.S @@ -28,8 +28,6 @@ .arm .syntax unified - /* All code in the portASM.S file is intended to be run from a prvileged - * operating mode, as such mark the entire file as privileged_functions */ .section privileged_functions #define FREERTOS_ASSEMBLY @@ -37,583 +35,464 @@ #include "mpu_syscall_numbers.h" #undef FREERTOS_ASSEMBLY - /* External FreeRTOS-Kernel Variables */ + /* External FreeRTOS-Kernel variables. */ .extern pxCurrentTCB .extern uxSystemCallImplementations .extern ulPortInterruptNesting .extern ulPortYieldRequired - /* External Linker script variables that are needed by the port */ - .extern __privileged_functions_start__ - .extern __privileged_functions_end__ - .extern __privileged_stacks_start__ - .extern __privileged_stacks_end__ - .extern __syscalls_flash_length__ + /* External Llnker script variables. */ .extern __syscalls_flash_start__ .extern __syscalls_flash_end__ - /* External FreeRTOS-Kernel Functions */ - .extern vAssertCalled + /* External FreeRTOS-Kernel functions. */ .extern vTaskSwitchContext .extern vApplicationIRQHandler /* ----------------------------------------------------------------------------------- */ -/* Save the register context of a FreeRTOS Task. */ + +/* Save the context of a FreeRTOS Task. */ .macro portSAVE_CONTEXT DSB ISB - /* Push R0 and the Link Register (LR) for scratch register space */ + /* Push R0 and LR to the stack for current mode. */ PUSH { R0, LR } - /* Load the pointer to the current task's Task Control Block (TCB) */ - LDR LR, =pxCurrentTCB - /* Load the actual TCB into LR */ - LDR LR, [LR] - /* Set LR to pxTopOfStack, the address of where to save the task context */ - LDR LR, [LR] - - /* Load the address of ulCriticalNesting */ - LDR R0, =ulCriticalNesting - /* Load the value of ulCriticalNesting into R0 */ - LDR R0, [R0] - /* Push the value of ulCriticalNesting into the context, auto-increment the - * LR by using the ! operator. */ - STM LR!, { R0 } + + LDR LR, =pxCurrentTCB /* LR = &( pxCurrentTCB ). */ + LDR LR, [LR] /* LR = pxCurrentTCB. */ + LDR LR, [LR] /* LR = pxTopOfStack i.e. the address where to store the task context. */ + + LDR R0, =ulCriticalNesting /* R0 = &( ulCriticalNesting ). */ + LDR R0, [R0] /* R0 = ulCriticalNesting. */ + STM LR!, { R0 } /* Store ulCriticalNesting. ! increments LR after storing. */ #if ( portENABLE_FPU == 1 ) - /* Save the floating point context */ - /* Copy the Floating Point Status and Control Register (FPSRC) */ - FMRX R0, FPSCR - /* Push the value of FPSCR onto the stack */ - STM LR!, { R0 } - /* Push the 32 Floating Point Registers (FPRs) onto the stack */ - VSTM LR!, { D0-D15 } + VMRS R0, FPSCR /* R0 = FPSCR. */ + STM LR!, { R0 } /* Store FPSCR. */ + VSTM LR!, { D0-D15 } /* Store D0-D15. */ #endif /* ( portENABLE_FPU == 1 ) */ - /* Restore the saved register */ - POP { R0 } - /* Save the General Purpose Registers (GPRs). Also save the pre-exception - * Stack Pointer (SP) and LR. The ^ operator causes this instruction to store - * the mode selected in the Saved Program Status Register (SPSR) */ + POP { R0 } /* Restore R0 to pre-exception value. */ + /* STM (user registers) - In a PL1 mode other than System mode, STM (user + * registers) instruction stores multiple User mode registers to + * consecutive memory locations using an address from a base register. The + * processor reads the base register value normally, using the current mode + * to determine the correct Banked version of the register. This instruction + * cannot writeback to the base register. + * + * The following can be derived from the above description: + * - The macro portSAVE_CONTEXT MUST be called from a PL1 mode other than + * the System mode. + * - Base register LR of the current mode will be used which contains the + * location to store the context. + * - It will store R0-R14 of User mode i.e. pre-exception SP(R13) and LR(R14) + * will be stored. */ STM LR, { R0-R14 }^ - /* Not allowed to auto-increment with ! when using banked registers */ - ADD LR, LR, #portREGISTER_LENGTH - /* Pop the pushed LR, which is the pre-exception Program Counter (PC) */ - POP { R0 } - /* Copy the pre-exception Current Program Status Register (CPSR), which, - * is banked as the SPSR and save it as part of the task context */ - MRS R1, SPSR - /* Store the pre-exception CPSR and PC */ - STM LR!, { R0-R1 } + ADD LR, LR, #60 /* R0-R14 - Total 155 register, each 4 byte wide. */ + + POP { R0 } /* Pre-exception PC is in R0. */ + MRS R1, SPSR /* R1 = Pre-exception CPSR. */ + STM LR!, { R0-R1 } /* Store pre-exception PC and CPSR. */ .endm /* ----------------------------------------------------------------------------------- */ -/* Restore the register context of a FreeRTOS Task. */ + +/* Restore the context of a FreeRTOS Task. */ .macro portRESTORE_CONTEXT - /* Load the pointer to the current task's Task Control Block (TCB) */ - LDR LR, =pxCurrentTCB - /* Load the actual TCB into LR */ - LDR LR, [LR] - /* Set R1 to the second member of the TCB struct, xMPUSettings */ - ADD R1, LR, #0x4 - /* Set LR to pxTopOfStack, the address to restore the task context from */ - LDR LR, [LR] - /* Load the first per-task MPU region into R5 */ - MOV R5, #portFIRST_CONFIGURABLE_REGION + /* Load the pointer to the current task's Task Control Block (TCB). */ + LDR LR, =pxCurrentTCB /* LR = &( pxCurrentTCB ). */ + LDR LR, [LR] /* LR = pxCurrentTCB. */ + ADD R1, LR, #0x4 /* R1 now points to the xMPUSettings in TCB. */ + LDR LR, [LR] /* LR = pxTopOfStack i.e. the address where to restore the task context from. */ + /* When creating a loop label in a macro it has to be a numeric label. * for( R5 = portFIRST_CONFIGURABLE_REGION ; R5 <= portNUM_CONFIGURABLE_REGIONS ; R5++ ) */ + MOV R5, #portFIRST_CONFIGURABLE_REGION 123: - /* Load values of struct MPU_REGION_REGISTERS into R2-R4 */ - LDMIA R1!, { R2-R4 } - /* Load the values set in xMPU_REGION_REGISTERS - * R2 Will hold ulRegionSize - * R3 will hold ulRegionAttribute - * R4 will hold ulRegionBaseAddress - * R5 will hold the MPU Region number */ - - /* Select the MPU Region using R5 */ - MCR p15, #0, R5, c6, c2, #0 - /* Set the MPU Region Base Address using ulRegionBaseAddress */ - MCR p15, #0, R4, c6, c1, #0 - /* Set the MPU Region Access Attributes using ulRegionAttribute */ - MCR p15, #0, R3, c6, c1, #4 - /* Set the MPU Region Size, and if the region is enabled using ulRegionSize */ - MCR p15, #0, R2, c6, c1, #2 - /* R5++ */ + LDMIA R1!, { R2-R4 } /* R2 = ulRegionSize, R3 = ulRegionAttribute, R4 = ulRegionBaseAddress. */ + + MCR p15, #0, R5, c6, c2, #0 /* MPU Region Number Register. */ + MCR p15, #0, R4, c6, c1, #0 /* MPU Region Base Address Register. */ + MCR p15, #0, R3, c6, c1, #4 /* MPU Region Access Control Register. */ + MCR p15, #0, R2, c6, c1, #2 /* MPU Region Size and Enable Register. */ + ADD R5, R5, #1 - /* R5 <= R6 */ CMP R5, #portNUM_CONFIGURABLE_REGIONS - /* R5 <= R6, loop again */ BLE 123b - /* R5 > portSTACK_REGION, all MPU regions have been restored */ - /* Load the address of the ulCriticalNesting variable into R1 */ - LDR R1, =ulCriticalNesting - /* Pop the previously saved value of ulCriticalNesting from ulContext */ - LDM LR!, { R2 } - /* Store the value of ulCriticalNesting into address of ulCriticalNesting */ - STR R2, [R1] + LDR R1, =ulCriticalNesting /* R1 = &( ulCriticalNesting ). */ + LDM LR!, { R2 } /* R2 = Stored ulCriticalNesting. */ + STR R2, [R1] /* Restore ulCriticalNesting. */ #if ( portENABLE_FPU == 1 ) - /* Restore Floating Point Context: Restore previous FPSCR from ulContext */ - LDM LR!, { R1 } - /* Move the saved FPSCR value into the FPSCR */ - VMSR FPSCR, R1 - /* Restore the Floating Point Registers */ - VLDM LR!, { D0-D15 } + LDM LR!, { R1 } /* R1 = Stored FPSCR. */ + VMSR FPSCR, R1 /* Restore FPSCR. */ + VLDM LR!, { D0-D15 } /* Restore D0-D15. */ #endif /* portENABLE_FPU*/ - /* Load the value of the CPSR into R0, needed to set the SP and the LR */ - LDR R0, [LR, +#(portREGISTER_LENGTH + 4UL)] - /* Move the CPSR the into our SPSR */ - MSR SPSR_cxsf, R0 - /* Restore the saved Stack Pointer and Link Register into User Mode */ + /* LDM (User registers) - In a PL1 mode other than System mode, LDM (User + * registers) loads multiple User mode registers from consecutive memory + * locations using an address from a base register. The registers loaded + * cannot include the PC. The processor reads the base register value + * normally, using the current mode to determine the correct Banked version + * of the register. This instruction cannot writeback to the base register. + * + * The following can be derived from the above description: + * - The macro portRESTORE_CONTEXT MUST be called from a PL1 mode other than + * the System mode. + * - Base register LR of the current mode will be used which contains the + * location to restore the context from. + * - It will restore R0-R14 of User mode i.e. SP(R13) and LR(R14) of User + * mode will be restored. + */ LDM LR, { R0-R14 }^ - /* Not allowed to auto-increment with ! when using banked registers */ - ADD LR, LR, #portREGISTER_LENGTH - /* Load the PC to return from the exception */ - RFE LR + ADD LR, LR, #60 /* R0-R14 - Total 155 register, each 4 byte wide. */ + + RFE LR /* Restore PC and CPSR from the context. */ .endm /* ----------------------------------------------------------------------------------- */ -/* Load the context of the first task, starting the FreeRTOS-Scheduler */ + +/* + * void vPortStartFirstTask( void ); + */ .align 4 .global vPortStartFirstTask .type vPortStartFirstTask, %function vPortStartFirstTask: - /** This function is called from System Mode to start the FreeRTOS-Kernel. - * This is done by restoring the context of the first task. - * Restoring the context of a task will allow interrupts. - * This allows the FreeRTOS Scheduler Tick to start, and therefore - * starts the FreeRTOS-Kernel. - */ - /* Swap to SVC Mode for context restore */ + /* This function is called from System Mode to start the FreeRTOS-Kernel. + * As described in the portRESTORE_CONTEXT macro, portRESTORE_CONTEXT cannot + * be called from the System mode. We, therefore, switch to the Supervisor + * mode before calling portRESTORE_CONTEXT. */ CPS #SVC_MODE - /* Load the context of first task, starting the FreeRTOS-Scheduler */ portRESTORE_CONTEXT /* ----------------------------------------------------------------------------------- */ -/* Handler for Supervisor Calls (SVCs) when using this FreeRTOS Port - * Upon entering here the LR, or R14, will hold the address of the following - * instruction. This then checks that instruction for the SVC # raised. - * Checks: - * 1. SVC is raised from the system call section (i.e. application is - * not raising SVC directly). - * 2. pxMpuSettings->xSystemCallStackInfo.pulTaskStack must be NULL as - * it is non-NULL only during the execution of a system call (i.e. - * between system call enter and exit). - * 3. System call is not for a kernel API disabled by the configuration - * in FreeRTOSConfig.h. - * 4. We do not need to check that ucSystemCallNumber is within range - * because the assembly SVC handler checks that before calling - * this function. - */ + .align 4 .global FreeRTOS_SVC_Handler .type FreeRTOS_SVC_Handler, %function FreeRTOS_SVC_Handler: - /* Push R11-R12 for scratch space */ PUSH { R11-R12 } /* ------------------------- Caller Flash Location Check ------------------------- */ - /* The address of the caller will be in the Link Register (LR), it will - * be the caller's Program Counter (PC). Check this address to ensure the - * Supervisor call (SVC) was raised from inside the FreRTOS-Kernel. */ - - /* Get the starting address for FreeRTOS System Calls */ - LDR R12, =__syscalls_flash_start__ - /* Subtract the start point from the Program Counter of the caller */ - SUB R11, LR, R12 - /* Now check if it is less than the length of the section */ - LDR R12, =__syscalls_flash_length__ - /* Check if an SVC was raised after the end of FreeRTOS System Calls */ - CMP R11, R12 - /* If the SVC was raised from outside FreeRTOS System Calls exit now */ - BGE SVC_Handler_Exit + LDR R11, =__syscalls_flash_start__ + LDR R12, =__syscalls_flash_end__ + CMP LR, R11 /* If SVC instruction address is less than __syscalls_flash_start__, exit. */ + BLT svcHandlerExit + CMP LR, R12 /* If SVC instruction address is greater than __syscalls_flash_end__, exit. */ + BGT svcHandlerExit /* ---------------------------- Get Caller SVC Number ---------------------------- */ - /* The SPSR will be the CPSR of the calling task, store it in R11 */ - MRS R11, SPSR - /* Thumb Mode is bit 5 of the CPSR, AND for comparison */ - ANDS R11, R11, #0x20 - /* In Thumb Mode, the instruction 0x2 before holds the SVC numebr */ - LDRHNE R11, [LR, #-0x2] - /* Not in Thumb Mode, the instruction 0x4 before holds the SVC numebr */ - LDRHEQ R11, [LR, #-0x4] + MRS R11, SPSR /* LR = CPSR at the time of SVC. */ + TST R11, #0x20 /* Check Thumb bit (5) in CPSR. */ + LDRHNE R11, [LR, #-0x2] /* If Thumb, load halfword. */ + BICNE R11, R11, #0xFF00 /* And extract immidiate field (i.e. SVC number). */ + LDREQ R11, [LR, #-0x4] /* If ARM, load word. */ + BICEQ R11, R11, #0xFF000000 /* And extract immidiate field (i.e. SVC number). */ /* --------------------------------- SVC Routing --------------------------------- */ - /* Determine if the SVC number is below #NUM_SYSTEM_CALLS */ + /* If SVC Number < #NUM_SYSTEM_CALLS, go to svcSystemCallEnter. */ CMP R11, #NUM_SYSTEM_CALLS - /* If it is go to the entry point for FreeRTOS System Calls */ BLT svcSystemCallEnter - /* Check if the caller is leaving a FreeRTOS System Call */ + /* If SVC Number == #portSVC_SYSTEM_CALL_EXIT, go to svcSystemCallExit. */ CMP R11, #portSVC_SYSTEM_CALL_EXIT BEQ svcSystemCallExit - /* Check if the caller is requesting to yield */ + /* If SVC Number == #portSVC_YIELD, go to svcPortYield. */ CMP R11, #portSVC_YIELD BEQ svcPortYield - /* If one of the above jumps wasn't taken, go straight to the exit */ -SVC_Handler_Exit: - /** Restore the saved R11 and R12, then return to the caller */ +svcHandlerExit: POP { R11-R12 } - /* This instruction loads the SPSR into the CPSR, performing the mode swap */ - MOVS PC, LR + MOVS PC, LR /* Copies the SPSR into the CPSR, performing the mode swap. */ -/* Perform a task swap */ svcPortYield: - /* Restore the previously saved R11, R12 */ POP { R11-R12 } - /* Save the context of the current task and select a new task to run. */ portSAVE_CONTEXT - /* Select a new task to swap to */ BL vTaskSwitchContext - /* Restore the context of the task selected to execute. */ portRESTORE_CONTEXT -/* Reset task stack and link register after a FreeRTOS System Call */ svcSystemCallExit: - /* Restore the Task Stack Pointer and Link Register */ - /* Load the address of pxCurrentTCB into R11 */ - LDR R11, =pxCurrentTCB - /* Load pxCurrentTCB into R11 */ - LDR R11, [R11] - /* Set R11 to be the location of xSystemCallStackInfo inside the TCB */ - ADD R11, R11, #portSYSTEM_CALL_INFO_OFFSET - /* Restore the user mode Stack Pointer and Link Register */ - LDMIB R11, { R13-R14 }^ - /* Zero out R12 so we can set ulTaskStackPointer back to NULL */ - AND R12, R12, #0x0 - /* Set pulTaskStackPointer to be 0x0 */ - STR R12, [R11, #0x4] - /* Set pulLinkRegisterAtSystemCallEntry to be 0x0 */ - STR R12, [R11, #0x8] - /* Load the ulTaskFlag so we can determine if we're going to lower privilege */ - LDM R11, { R12 } - /* Check if the task is privileged */ - CMP R12, #portTASK_IS_PRIVILEGED_FLAG - /* If the task is privileged we can leave now */ - BEQ SVC_Handler_Exit - /* Otherwise, we need to set the SPSR back to USER mode */ + LDR R11, =pxCurrentTCB /* R11 = &( pxCurrentTCB ). */ + LDR R11, [R11] /* R11 = pxCurrentTCB. */ + ADD R11, R11, #portSYSTEM_CALL_INFO_OFFSET /* R11 now points to xSystemCallStackInfo in TCB. */ + + /* Restore the user mode SP and LR. */ + LDM R11, { R13-R14 }^ + + AND R12, R12, #0x0 /* R12 = 0. */ + STR R12, [R11] /* xSystemCallStackInfo.pulTaskStackPointer = NULL. */ + STR R12, [R11, #0x4] /* xSystemCallStackInfo.pulLinkRegisterAtSystemCallEntry = NULL. */ + + LDMDB R11, { R12 } /* R12 = ulTaskFlags. */ + + TST R12, #portTASK_IS_PRIVILEGED_FLAG + /* If the task is privileged, we can exit now. */ + BNE svcHandlerExit + /* Otherwise, we need to switch back to User mode. */ MRS R12, SPSR - /* Clear the last 4 bits, which are the MODE bits */ BIC R12, R12, #0x0F - /* Move the new value into the SPSR */ MSR SPSR_cxsf, R12 - /* Jump back */ - B SVC_Handler_Exit -/* Save task's SP and LR, swap to ulSystemCallStack Buffer, raise privilege */ + B svcHandlerExit + svcSystemCallEnter: - /* Load the base address of the uxSystemCallImplementations[] table into R14 */ - LDR R14, =uxSystemCallImplementations - - /** Shift the value of R11, the SVC number, left by two to get the jump offset - * Add this offset to R14, which holds the jump table address. This is the address - * of the SVC that the relevant function is trying to complete. - * Now when the Link Register is loaded as the Program Counter at the end of this - * handler, the caller will immediately execute the requested function */ - LDR R14, [R14, R11, lsl #2] - - /* Load the address of pxCurrentTCB into R11 */ - LDR R11, =pxCurrentTCB - /* Load pxCurrentTCB into R11 */ - LDR R11, [R11] - /* Set R11 to be the location of xSystemCallStackInfo inside the TCB */ - ADD R11, R11, #portSYSTEM_CALL_INFO_OFFSET - /* Get the value in the TCB for ulTaskStackPointer */ - LDMIB R11!, { R12 } - /* Ensure ulTaskStackPointer is null, signifying initial entry */ - TEQ R12, #0x0 - /* Make sure that the function pointer loaded is not NULL */ - CMPEQ R14, #0x0 - - /* Hard code the ascii value of the function name and line number to call - * assert if the ulTaskStackPointer is not null. */ - MOVWEQ R0, #0x706F - MOVTEQ R0, #0x7274 - MOVEQ R1, #342 - BEQ vAssertCalled - - /* Store the task's SP and LR to xSYSTEM_CALL_STACK_INFO */ + LDR R12, =uxSystemCallImplementations /* R12 = uxSystemCallImplementations. */ + /* R12 = uxSystemCallImplementations[ R12 + ( R11 << 2 ) ]. + * R12 now contains the address of the system call impl function. */ + LDR R12, [R12, R11, lsl #2] + + /* If R12 == NULL, exit. */ + CMP R12, #0x0 + BEQ svcHandlerExit + + /* It is okay to clobber LR here because we do not need to return to the + * SVC enter location anymore. LR now contains the address of the system + * call impl function. */ + MOV LR, R12 + + LDR R11, =pxCurrentTCB /* R11 = &( pxCurrentTCB ). */ + LDR R11, [R11] /* R11 = pxCurrentTCB. */ + ADD R11, R11, #portSYSTEM_CALL_INFO_OFFSET /* R11 now points to xSystemCallStackInfo in TCB. */ + + /* Store User mode SP and LR in xSystemCallStackInfo.pulTaskStackPointer and + * xSystemCallStackInfo.pulLinkRegisterAtSystemCallEntry. */ STM R11, { R13-R14 }^ - /* Not allowed to auto-increment with ! when using banked registers */ ADD R11, R11, 0x8 - /* Load pulSystemCallStackPointer and pulSystemCallLinkRegister now */ + + /* Load User mode SP an LR with xSystemCallStackInfo.pulSystemCallStackPointer + * and xSystemCallStackInfo.pulSystemCallExitAddress. */ LDM R11, { R13-R14 }^ - /* Swap the SPSR to SYS_MODE for the System Call. Move SPSR into R12 */ + /* Change to SYS_MODE for the System Call. */ MRS R12, SPSR - /* Set the MODE bits to SYS_MODE */ ORR R12, R12, #SYS_MODE - /* Assign the new value to SPSR */ MSR SPSR_cxsf, R12 - /* Leave through the SVC Exit */ - B SVC_Handler_Exit -/* ----------------------------------------------------------------------------------- */ -/* Disable IRQs and increment the critical nesting count */ -.align 4 -.global vPortEnterCritical -.type vPortEnterCritical, %function -vPortEnterCritical: - /* Disable IRQs */ - CPSID I - /* Save scratch registers */ - PUSH { R0-R1 } - /* Load address of current critical nesting count */ - LDR R0, =ulCriticalNesting - /* Load value of current critical nesting count */ - LDR R1, [R0] - /* Add one to ulCriticalNesting */ - ADD R1, R1, #1 - /* Store the modified ulCriticalNesting back into RAM */ - STR R1, [R0] - /* Restore pushed registers */ - POP { R0-R1 } - /* Return to caller */ - BX LR + B svcHandlerExit /* ----------------------------------------------------------------------------------- */ -/* Disable IRQs */ + +/* + * void vPortDisableInterrupts( void ); + */ .align 4 .global vPortDisableInterrupts .type vPortDisableInterrupts, %function vPortDisableInterrupts: - /* Disable IRQs */ CPSID I - /* Return to caller */ BX LR /* ----------------------------------------------------------------------------------- */ -/* Enable IRQs and decrement the critical nesting count */ -.align 4 -.global vPortExitCritical -.type vPortExitCritical, %function -vPortExitCritical: - /* Store two scratch registers and LR for IRQ Mode re-entry */ - PUSH { R0-R1, LR } - /* Load address of current critical nesting count */ - LDR R0, =ulCriticalNesting - /* Load value of current critical nesting count */ - LDR R1, [R0] - /* Check if the count is 0 */ - CMP R1, #0 - /* If ulCriticalNesting is greater than 0, Subtract 1 from it */ - SUBGT R1, R1, #1 - /* Store the modified ulCriticalNesting back into RAM */ - STRGT R1, [R0] - /* Enable IRQs */ - CPSIE I - /* Restore Pushed registers */ - POP { R0-R1, LR } - /* Return to caller */ - BX LR -/* ----------------------------------------------------------------------------------- */ -/* Enable IRQs */ +/* + * void vPortEnableInterrupts( void ); + */ .align 4 .global vPortEnableInterrupts .type vPortEnableInterrupts, %function vPortEnableInterrupts: - /* Push LR to account for re-entry in IRQ Mode */ - PUSH { LR } - /* Enable IRQs */ CPSIE I - /* Restore previous LR */ - POP { LR } - /* Return to caller */ BX LR /* ----------------------------------------------------------------------------------- */ -/** Set MPU Registers using provided values - * Function: void vMPUSetRegion - * Inputs: uint32_t ulRegionNumber - * Inputs: uint32_t ulBaseAddress - * Inputs: uint32_t ulRegionSize - * Inputs: uint32_t ulRegionPermissions -*/ + +/* + * void vMPUSetRegion( uint32_t ulRegionNumber, + * uint32_t ulBaseAddress, + * uint32_t ulRegionSize, + * uint32_t ulRegionPermissions ); + * + * According to the Procedure Call Standard for the ARM Architecture (AAPCS), + * paramters are passed in the following registers: + * R0 = ulRegionNumber. + * R1 = ulBaseAddress. + * R2 = ulRegionSize. + * R3 = ulRegionPermissions. + */ .align 4 .global vMPUSetRegion .type vMPUSetRegion, %function vMPUSetRegion: - /* Only 15 possible regions, drop all other bits */ - AND R0, R0, #15 - /* Select the MPU Region selected by ulRegionNumber */ - MCR p15, #0, R0, c6, c2, #0 - /* Set the Base Address to be ulBaseAddress */ - MCR p15, #0, R1, c6, c1, #0 - /* Set the Access Attributes to be ulRegionPermissions */ - MCR p15, #0, R3, c6, c1, #4 - /* Set the Size and Enable bits to be ulRegionSize */ - MCR p15, #0, R2, c6, c1, #2 - /* Return to caller */ + AND R0, R0, #0x0F /* R0 = R0 & 0x0F. Max possible region number is 15. */ + + MCR p15, #0, R0, c6, c2, #0 /* MPU Region Number Register. */ + MCR p15, #0, R1, c6, c1, #0 /* MPU Region Base Address Register. */ + MCR p15, #0, R3, c6, c1, #4 /* MPU Region Access Control Register. */ + MCR p15, #0, R2, c6, c1, #2 /* MPU Region Size and Enable Register. */ + BX LR /* ----------------------------------------------------------------------------------- */ -/* Set the Enable bit of the MPU Enable Register to 1. */ + +/* + * void vMPUEnable( void ); + */ .align 4 .global vMPUEnable .type vMPUEnable, %function vMPUEnable: - /* Read the current MPU control register into R0 */ - MRC p15, #0, R0, c1, c0, #0 - /* Set the enable bit to high */ - ORR R0, R0, #0x1 - /* Data sync */ + PUSH { R0 } + + MRC p15, #0, R0, c1, c0, #0 /* R0 = System Control Register (SCTLR). */ + ORR R0, R0, #0x1 /* R0 = R0 | 0x1. Set the M bit in SCTLR. */ DSB - /* Write out previous MPU control register with a high enable bit */ - MCR p15, #0, R0, c1, c0, #0 - /* Instruction sync */ + MCR p15, #0, R0, c1, c0, #0 /* SCTLR = R0. */ ISB - /* Return to caller */ + + POP { R0 } BX LR /* ----------------------------------------------------------------------------------- */ -/* Set the Enable bit of the MPU Enable Register to 0. */ + +/* + * void vMPUDisable( void ); + */ .align 4 .global vMPUDisable .type vMPUDisable, %function vMPUDisable: - /* Read the MPU enable register values into R0 */ - MRC p15, #0, R0, c1, c0, #0 - /* Perform a bitwise AND of R0 and NOT #1, i.e. clear bit 1 */ - BIC R0, R0, #1 - /* Wait for all pending explicit data accesses to complete */ + PUSH { R0 } + + MRC p15, #0, R0, c1, c0, #0 /* R0 = System Control Register (SCTLR). */ + BIC R0, R0, #1 /* R0 = R0 & ~0x1. Clear the M bit in SCTLR. */ + /* Wait for all pending data accesses to complete. */ DSB - /* Write out to the MPU Enable Register */ - MCR p15, #0, R0, c1, c0, #0 - /* Flushes the pipeline and prefetch buffer(s) in the processor. */ - /* Ensures all following instructions are fetched from cache or memory. */ + MCR p15, #0, R0, c1, c0, #0 /* SCTLR = R0. */ + /* Flush the pipeline and prefetch buffer(s) in the processor to ensure that + * all following instructions are fetched from cache or memory. */ ISB - /* Return to caller */ + + POP { R0 } BX LR /* ----------------------------------------------------------------------------------- */ -/* Enable the MPU Background Region */ + +/* + * void vMPUEnableBackgroundRegion( void ); + */ .align 4 .global vMPUEnableBackgroundRegion .type vMPUEnableBackgroundRegion, %function vMPUEnableBackgroundRegion: - /* Save value in R0 */ PUSH { R0 } - /* Read CP15 System Control Register into R0 */ - MRC p15, 0, R0, c1, c0, 0 - /* Set bit 17 so that privileged modes won't trigger unmapped MPU region faults */ - ORR R0, R0, #0x20000 - /* Write the value back out */ - MCR p15, 0, R0, c1, c0, 0 - /* Restore the used register */ + + MRC p15, #0, R0, c1, c0, #0 /* R0 = System Control Register (SCTLR). */ + ORR R0, R0, #0x20000 /* R0 = R0 | 0x20000. Set the BR bit in SCTLR. */ + MCR p15, #0, R0, c1, c0, #0 /* SCTLR = R0. */ + POP { R0 } - /* Return to the caller */ BX LR /* ----------------------------------------------------------------------------------- */ -/* Disable the MPU Background Region */ + +/* + * void vMPUDisableBackgroundRegion( void ); + */ .align 4 .global vMPUDisableBackgroundRegion .type vMPUDisableBackgroundRegion, %function vMPUDisableBackgroundRegion: - /* Save value in R0 */ PUSH { R0 } - /* Read CP15 System Control Register into R0 */ - MRC p15, 0, R0, c1, c0, 0 - /* Clear bit 17 so that privileged modes won't trigger unmapped MPU region faults */ - BIC R0, R0, #0x20000 - /* Write the value back out */ - MCR p15, 0, R0, c1, c0, 0 - /* Restore the used register */ + + MRC p15, 0, R0, c1, c0, 0 /* R0 = System Control Register (SCTLR). */ + BIC R0, R0, #0x20000 /* R0 = R0 & ~0x20000. Clear the BR bit in SCTLR. */ + MCR p15, 0, R0, c1, c0, 0 /* SCTLR = R0. */ + POP { R0 } - /* Return to the caller */ BX LR /* ----------------------------------------------------------------------------------- */ + .align 4 .global FreeRTOS_IRQ_Handler .type FreeRTOS_IRQ_Handler, %function FreeRTOS_IRQ_Handler: - /* Disable IRQs */ - CPSID I - /* Return to the interrupted instruction. */ - SUB LR, LR, #4 - /* Save the return state to the IRQ stack */ - SRSDB SP!, #IRQ_MODE - /* Push used registers. */ - PUSH { R0-R3, R12 } - - /* Load &ulPortInterruptNesting into R0 */ - LDR R0, =ulPortInterruptNesting - /* Load the value of ulPortInterruptNesting into R1 */ - LDR R1, [R0] - /* R2 = ulPortInterruptNesting + 1 */ - ADD R2, R1, #1 - /* Store the value of ulPortInterruptNesting++ back into the variable */ - STR R2, [R0] - - /* Save Calling Registers */ + SUB LR, LR, #4 /* Return to the interrupted instruction. */ + SRSDB SP!, #IRQ_MODE /* Save return state (i.e. SPSR_irq and LR_irq) to the IRQ stack. */ + + /* Change to supervisor mode to allow reentry. It is necessary to ensure + * that a BL instruction within the interrupt handler code does not + * overwrite LR_irq. */ + CPS #SVC_MODE + + PUSH { R0-R3, R12 } /* Push AAPCS callee saved registers. */ + + /* Update interrupt nesting count. */ + LDR R0, =ulPortInterruptNesting /* R0 = &( ulPortInterruptNesting ). */ + LDR R1, [R0] /* R1 = ulPortInterruptNesting. */ + ADD R2, R1, #1 /* R2 = R1 + 1. */ + STR R2, [R0] /* Store the updated nesting count. */ + + /* Call the application provided IRQ handler. */ PUSH { R0-R3, LR } - /* Call the User provided IRQ handler */ BL vApplicationIRQHandler + POP { R0-R3, LR } - /* Disable IRQs incase vApplicationIRQHandler enabled them for re-entry */ - CPSID I - /* Perform a data and instruction buffer flush */ + /* Disable IRQs incase vApplicationIRQHandler enabled them for re-entry. */ + CPSID I DSB ISB - /* Restore the previous registers */ - POP { R0-R3, LR } - /* R0 holds the address of ulPortInterruptNesting, R1 holds original value */ + /* Restore the old interrupt nesting count. R0 holds the address of + * ulPortInterruptNesting and R1 holds original value of + * ulPortInterruptNesting. */ STR R1, [R0] - /* Check if ulPortInterruptNesting is 0 */ + + /* Context swtich is only performed when interrupt nesting count is 0. */ CMP R1, #0 - /* If ulPortInterruptNesting is not zero, unwind the nested interrupt */ BNE exit_without_switch - /* ulPortInterruptNesting is zero, check if ulPortYieldRequired is set */ - LDR R1, =ulPortYieldRequired - /* Load the value of ulPortYieldRequired */ - LDR R0, [R1] - /* Check if the value of ulPortYieldRequired is zero */ + /* Check ulPortInterruptNesting to see if the interrupt requested a context + * switch. */ + LDR R1, =ulPortYieldRequired /* R1 = &( ulPortYieldRequired ). */ + LDR R0, [R1] /* R0 = ulPortYieldRequired. */ + /* If ulPortYieldRequired != 0, goto switch_before_exit. */ CMP R0, #0 - /* If it is non-zero select a new task to run */ BNE switch_before_exit exit_without_switch: - /* No context switch. Restore used registers, LR_irq and SPSR before returning. */ - POP { R0-R3, R12 } - /* Return from exception, load pre-exception PC and CPSR */ + POP { R0-R3, R12 } /* Restore AAPCS callee saved registers. */ + CPS #IRQ_MODE RFE SP! switch_before_exit: - /* A context swtich is to be performed. Clear the context switch pending flag. */ + /* A context swtich is to be performed. Clear ulPortYieldRequired. R1 holds + * the address of ulPortYieldRequired. */ MOV R0, #0 - /* Set ulPortYieldRequired back to zero */ STR R0, [R1] - /* Restore used registers, LR_irq and SPSR before saving the context */ + /* Restore AAPCS callee saved registers, SPSR_irq and LR_irq before saving + * the task context. */ POP { R0-R3, R12 } - /* Load the pushed SPSR from the stack */ + CPS #IRQ_MODE + /* The contents of the IRQ stack at this point is the following: + * +----------+ + * SP+4 | SPSR_irq | + * +----------+ + * SP | LR_irq | + * +----------+ + */ LDMIB SP!, { LR } - /* Move it into the SPSR */ MSR SPSR_cxsf, LR - /* Load the pushed pre-exception Program Counter into LR_irq */ LDMDB SP, { LR } - /* Increment the Stack Pointer an additional 0x4 */ ADD SP, SP, 0x4 - /* Save the current task's context */ portSAVE_CONTEXT /* Call the function that selects the new task to execute. */ BLX vTaskSwitchContext - /* Restore the context of the selected task, which will start executing. */ + /* Restore the context of, and branch to, the task selected to execute + * next. */ portRESTORE_CONTEXT +/* ----------------------------------------------------------------------------------- */ + .end diff --git a/portable/GCC/ARM_CRx_MPU/portmacro.h b/portable/GCC/ARM_CRx_MPU/portmacro.h index 7ef2119046..6d0eea568b 100644 --- a/portable/GCC/ARM_CRx_MPU/portmacro.h +++ b/portable/GCC/ARM_CRx_MPU/portmacro.h @@ -40,45 +40,29 @@ extern "C" { #endif -/* Include stdint for integer types of specific bit widths */ +/* Include stdint for integer types of specific bit widths. */ #include /* ------------------------------ FreeRTOS Config Check ------------------------------ */ -/* Include the FreeRTOS Config file first to get the includes being used */ -#include "FreeRTOSConfig.h" - -#ifndef configENABLE_MPU - #define configENABLE_MPU 1 -#elif( configENABLE_MPU != 1 ) - #error "This port is only usable with configENABLE_MPU set to 1" -#endif /* configENABLE_MPU */ - -#ifndef configENABLE_ACCESS_CONTROL_LIST - #define configENABLE_ACCESS_CONTROL_LIST 1 -#endif /* configENABLE_ACCESS_CONTROL_LIST */ - -#ifndef configPROTECTED_KERNEL_OBJECT_POOL_SIZE - #error "Set configPROTECTED_KERNEL_OBJECT_POOL_SIZE to at least the " \ - "number of FreeRTOS-Kernel Objects to be created" -#endif /* configPROTECTED_KERNEL_OBJECT_POOL_SIZE */ - -/** - * @brief The size in Bytes that the Privileged System Call Stack should be. - * - * @ingroup MPU Privilege - * - * @note A Stack of this length, in bytes, is used by FreeRTOS APIs when called - * by an unprivileged task. - */ #ifndef configSYSTEM_CALL_STACK_SIZE #error "Define configSYSTEM_CALL_STACK_SIZE to a length, in bytes, " \ "to use when an unprivileged task makes a FreeRTOS Kernel call. " #endif /* configSYSTEM_CALL_STACK_SIZE */ +#if( configUSE_MPU_WRAPPERS_V1 == 1 ) + #error This port is usable with MPU wrappers V2 only. +#endif /* configUSE_MPU_WRAPPERS_V1 */ + +#ifndef configSETUP_TICK_INTERRUPT + #error "configSETUP_TICK_INTERRUPT() must be defined in FreeRTOSConfig.h " \ + "to call the function that sets up the tick interrupt." +#endif /* configSETUP_TICK_INTERRUPT */ + /* ----------------------------------------------------------------------------------- */ #if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + /* Check the configuration. */ #if( configMAX_PRIORITIES > 32 ) #error "configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when " \ @@ -88,115 +72,95 @@ extern "C" { #endif /* ( configMAX_PRIORITIES > 32 ) */ /** - * @brief Mark that a task of the current priority is ready for execution. + * @brief Mark that a task of the given priority is ready. * * @ingroup Scheduler * - * @param[in] uxPriority Priority of task that can enter the ready state - * @param[out] uxTopReadyPriority Bitmap of tasks that are in the ready state + * @param[in] uxPriority Priority of the task that is ready. + * @param[in] uxTopReadyPriority Bitmap of the ready tasks priorities. */ #define portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority ) \ ( uxTopReadyPriority ) |= ( 1UL << ( uxPriority ) ) /** - * @brief Mark that a task of the current priority has left the ready state. + * @brief Mark that a task of the given priority is no longer ready. * * @ingroup Scheduler * - * @param[in] uxPriority Priority of task that is leaving the ready state - * @param[out] uxTopReadyPriority Bitmap of tasks that are in the ready state + * @param[in] uxPriority Priority of the task that is no longer ready. + * @param[in] uxTopReadyPriority Bitmap of the ready tasks priorities. */ #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority ) \ ( uxTopReadyPriority ) &= ~( 1UL << ( uxPriority ) ) /** - * @brief Determine what the highest priority ready task is. + * @brief Determine the highest priority ready task's priority. * * @ingroup Scheduler * - * @param[out] uxTopReadyPriority Bitmap of tasks that are in the ready state - * @param[out] uxTopPriority The highest priority ready task's priority value. + * @param[in] uxTopReadyPriority Bitmap of the ready tasks priorities. + * @param[in] uxTopPriority The highest priority ready task's priority. */ #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ) \ - uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxTopReadyPriority ) ) ) + ( uxTopPriority ) = ( 31UL - ulPortCountLeadingZeros( ( uxTopReadyPriority ) ) ) #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ -#ifndef configSETUP_TICK_INTERRUPT - #error "configSETUP_TICK_INTERRUPT() must be defined in FreeRTOSConfig.h " \ - "to call the function that sets up the tick interrupt." -#endif /* configSETUP_TICK_INTERRUPT */ - -#if( configUSE_TICKLESS_IDLE != 0 ) - #error This port does not support tickless idle -#endif /* ( configUSE_TICKLESS_IDLE != 0 ) */ - /* ------------------------------ Port Type Definitions ------------------------------ */ #include "portmacro_asm.h" /** - * @brief Critical section nesting value to mark the end of a critical section. + * @brief Critical section nesting value. * * @ingroup Critical Sections * - * @note - * A critical section is exited when the critical section nesting count reaches - * this value. When exiting a critical section IRQs are re-enabled. + * A task exits critical section and enables IRQs when its nesting count reaches + * this value. */ #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0x0 ) /** - * @brief Bit value used to mark if the CPU is currently executing in Thumb Mode. + * @brief Bit in Current Program Status Register (CPSR) to indicate that CPU is + * in Thumb State. + * * @ingroup Task Context */ #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) /** - * @brief Value used to check if a task's function is a Thumb function. + * @brief Bitmask to check if an address is of Thumb Code. + * * @ingroup Task Context */ #define portTHUMB_MODE_ADDRESS ( 0x01UL ) /** - * @brief Unsigned Data type equal to the data word operating size of the CPU. + * @brief Data type used to represent a stack word. * * @ingroup Port Interface Specifications - * - * @note - * The FreeRTOS-Kernel needs to be able to use an unsigned type that is - * the most efficient, natural type for the targeted architecture. */ typedef uint32_t StackType_t; /** - * @brief Signed Data type equal to the data word operating size of the CPU. + * @brief Signed data type equal to the data word operating size of the CPU. * * @ingroup Port Interface Specifications - * - * @note - * The FreeRTOS-Kernel needs to be able to use a signed type that is - * the most efficient, natural type for the targeted architecture. */ typedef int32_t BaseType_t; /** - * @brief Unsigned Data type equal to the data word operating size of the CPU. + * @brief Unsigned data type equal to the data word operating size of the CPU. * * @ingroup Port Interface Specifications - * - * @note - * The FreeRTOS-Kernel needs to be able to use an unsigned type that is - * the most efficient, natural type for the targeted architecture. */ typedef uint32_t UBaseType_t; /** - * @brief Integer type used for the Tick Counter. + * @brief Data type used for the FreeRTOS Tick Counter. * - * @note - * Use a 32-bit tick type on a 32-bit architecture, so reads of the tick count - * do not need to be guarded with a critical section. + * @note Using 32-bit tick type on a 32-bit architecture ensures that reads of + * the tick count do not need to be guarded with a critical section. */ typedef uint32_t TickType_t; @@ -204,15 +168,13 @@ typedef uint32_t TickType_t; * @brief Marks the direction the stack grows on the targeted CPU. * * @ingroup Port Interface Specifications - * */ #define portSTACK_GROWTH ( -1 ) /** - * @brief Specifies at what number of bytes a stack pointer shall be aligned. + * @brief Specifies stack pointer alignment requirements of the target CPU. * * @ingroup Port Interface Specifications - * */ #define portBYTE_ALIGNMENT 8U @@ -221,9 +183,8 @@ typedef uint32_t TickType_t; * * @ingroup Port Interface Specifications * - * @note - * These are not required for this port but included in case common demo code - * that uses these macros is used. + * @note This is not required for this port but included in case common demo + * code uses it. */ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) \ void vFunction( void * pvParameters ) @@ -233,46 +194,49 @@ typedef uint32_t TickType_t; * * @ingroup Port Interface Specifications * - * @note - * These are not required for this port but included in case common demo code - * that uses these macros is used. + * @note This is not required for this port but included in case common demo + * code uses it. */ -#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) \ + void vFunction( void * pvParameters ) /** - * @brief Wrapper for the no-op ARM Assembly Instruction. + * @brief The no-op ARM assembly instruction. + * * @ingroup Port Interface Specifications */ #define portNOP() __asm volatile( "NOP" ) /** - * @brief Wrapper for the Inline GCC Label. + * @brief The inline GCC label. + * * @ingroup Port Interface Specifications */ #define portINLINE __inline /** - * @brief Wrapper for the ARM Memory Sync Assembly Instruction. + * @brief The memory access synchronization barrier. + * * @ingroup Port Interface Specifications */ #define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) /** - * @brief Defines if the system tick count can be accessed atomically. + * @brief Defines if the tick count can be accessed atomically. * * @ingroup System Clock */ #define portTICK_TYPE_IS_ATOMIC 1 /** - * @brief Define the number of miliseconds between system ticks. + * @brief The number of miliseconds between system ticks. * * @ingroup System Clock */ #define portTICK_PERIOD_MS ( ( TickType_t ) 1000UL / configTICK_RATE_HZ ) /** - * @brief Define the larges possible delay value for a task. + * @brief The largest possible delay value for any FreeRTOS API. * * @ingroup System Clock */ @@ -280,88 +244,58 @@ typedef uint32_t TickType_t; /* ----------------------------- Port Assembly Functions ----------------------------- */ -/** @brief Assembly FreeRTOS Supervisor Call Handler. */ -void FreeRTOS_SVC_Handler( void ); - -/** @brief Assembly FreeRTOS Interrupt Handler */ -void FreeRTOS_IRQ_Handler( void ); - /** - * @brief Make a Supervisor Call to swap the currently running task out. + * @brief FreeRTOS Supervisor Call (SVC) Handler. * * @ingroup Scheduler - * @note The FreeRTOS-Kernel needs a method to swap the current task that is - * running. The FreeRTOS-Port needs to ensure that when this happens any - * hardware specific values related to the current task’s context are properly - * saved. A properly saved context can be restored to allow execution of the - * task as if it was not interrupted. */ -void vPortYield( void ); - -/** @brief Raise a Supervisor Call to swap the currently running task out. */ -#define portYIELD() vPortYield() +void FreeRTOS_SVC_Handler( void ); /** - * @brief Disable IRQs then increment the critical nesting count. - * @ingroup Critical Section + * @brief FreeRTOS Interrupt Handler. + * + * @ingroup Scheduler */ -void vPortEnterCritical( void ); - -/** @brief Enter a Critical Section inside of the FreeRTOS-Kernel */ -#define portENTER_CRITICAL() vPortEnterCritical() +void FreeRTOS_IRQ_Handler( void ); /** - * @brief Enable IRQs and decrement the critical nesting count. - * @ingroup Critical Section + * @brief Yield the CPU. + * + * @ingroup Scheduler */ -void vPortExitCritical( void ); +void vPortYield( void ); -/** - * @brief Exit a Critical Section inside of the FreeRTOS-Kernel. - * @ingroup Critical Section - */ -#define portEXIT_CRITICAL() vPortExitCritical() +#define portYIELD() vPortYield() /** - * @brief Set the IRQ bit of the CPSR high, enabling IRQs. + * @brief Enable interrupts. + * * @ingroup Interrupt Management */ void vPortEnableInterrupts( void ); -/** - * @brief Enable Interrupts by setting the IRQ allowed flag on the CPU - * @ingroup Interrupt Management - */ #define portENABLE_INTERRUPTS() vPortEnableInterrupts() /** - * @brief Set the IRQ bit of the CPSR low, disabling IRQs. + * @brief Disable interrupts. + * * @ingroup Interrupt Management */ void vPortDisableInterrupts( void ); -/** - * @brief Enable Interrupts by lowering the IRQ allowed flag on the CPU. - * @ingroup Interrupt Management - */ #define portDISABLE_INTERRUPTS() vPortDisableInterrupts() /** - * @brief Exit the FreeRTOS-Kernel, restoring the task's settings. + * @brief Exit from a FreeRTO System Call. * * @ingroup Port Privilege - * - * @return void */ void vPortSystemCallExit( void ); /** - * @brief Load the context of the first task. + * @brief Start executing first task. * * @ingroup Scheduler - * - * @note This is an assembly function implemented in portASM.s, it loads the - * context of the first task from pxCurrentTCB. */ void vPortStartFirstTask( void ); @@ -369,8 +303,6 @@ void vPortStartFirstTask( void ); * @brief Enable the onboard MPU. * * @ingroup MPU Control - * - * @return void */ void vMPUEnable( void ); @@ -378,8 +310,6 @@ void vMPUEnable( void ); * @brief Disable the onboard MPU. * * @ingroup MPU Control - * - * @return VOID */ void vMPUDisable( void ); @@ -387,33 +317,28 @@ void vMPUDisable( void ); * @brief Enable the MPU Background Region. * * @ingroup MPU Control - * - * @return void */ void vMPUEnableBackgroundRegion( void ); /** - * @brief Disable the MPU Background Region + * @brief Disable the MPU Background Region. * * @ingroup MPU Control - * - * @return void */ void vMPUDisableBackgroundRegion( void ); + /** - * @brief Assembly routine to set permissions for an MPU Region. + * @brief Set permissions for an MPU Region. * * @ingroup MPU Control * - * @param[in] ulRegionNumber The MPU Region Number to change permissions for - * @param[in] ulBaseAddress The base address of the MPU Region - * @param[in] ulRegionSize The number of bytes to make the MPU Region - * @param[in] ulRegionPermissions The permissions to assign to the MPU Region + * @param[in] ulRegionNumber The MPU Region Number to set permissions for. + * @param[in] ulBaseAddress The base address of the MPU Region. + * @param[in] ulRegionSize The size of the MPU Region in bytes. + * @param[in] ulRegionPermissions The permissions associated with the MPU Region. * - * @note This is an Assembly Function implemented in portASM.S. - * This is meant as a purely internal function that performs a raw write of the - * provided values to the relevant MPU Registers. The inputs to this function - * are checked internally before it is called in the port.c file. + * @note This is an internal function and assumes that the inputs to this + * function are checked before calling this function. */ void vMPUSetRegion( uint32_t ulRegionNumber, uint32_t ulBaseAddress, @@ -423,105 +348,82 @@ void vMPUSetRegion( uint32_t ulRegionNumber, /* ------------------------------- Port.c Declarations ------------------------------- */ /** - * @brief Checks whether or not the processor is privileged. + * @brief Enter critical section. * - * @ingroup Port Privilege - * - * @note - * The Privilege level is determined by checking if bits [4:0] of - * the callers Current Program Status Register are in USER_MODE, 0x10 - * - * @return - * 0 If the CPSR Mode Bits are set to 0x10 - * 1 If the CPSR Mode Bits are set to 0x11-0x11F + * @ingroup Critical Section + */ +void vPortEnterCritical( void ); + +#define portENTER_CRITICAL() vPortEnterCritical() + +/** + * @brief Exit critical section. * + * @ingroup Critical Section */ -BaseType_t xPortIsPrivileged( void ); +void vPortExitCritical( void ); + +#define portEXIT_CRITICAL() vPortExitCritical() /** - * @brief Check if the CPU is currently in a privileged operating mode. + * @brief Checks whether or not the processor is privileged. * * @ingroup Port Privilege * - * @return - * 1 If the processor is privileged - * 0 If the processor is not privileged + * @note The processor privilege level is determined by checking if bits [4:0] + * of the Current Program Status Register (CPSR). * + * @return pdTRUE, if the processer is privileged, pdFALSE otherwise. */ +BaseType_t xPortIsPrivileged( void ); + #define portIS_PRIVILEGED() xPortIsPrivileged() /** - * @brief Check if ulTaskFlags has portTASK_IS_PRIVILEGED_FLAG. + * @brief Checks whether or not a task is privileged. * * @ingroup Port Privilege * - * @note - * As this loads pxCurrentTCB to determine if the task's ulTaskFlags is privileged - * or not, this function can return a different value than xPortIsPrivileged. + * A task's privilege level is associated with the task and is different from + * the processor's privilege level returned by xPortIsPrivileged. For example, + * the processor is privileged when an unprivileged task executes a system call. * - * @return - * 0 If pxCurrentTCB's !( ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) - * 1 If pxCurrentTCB's ( ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) + * @return pdTRUE if the task is privileged, pdFALSE otherwise. */ BaseType_t xPortIsTaskPrivileged( void ); -/** - * @brief Checks whether or not the currently running task is privileged. - * - * @ingroup Port Privilege - * - * @return - * pdTRUE if the calling task is privileged - * pdFALSE if the calling task is not privileged - */ #define portIS_TASK_PRIVILEGED() xPortIsTaskPrivileged() /** - * @brief Default return address for tasks, it is not meant to be called. + * @brief Default return address for tasks. * * @ingroup Task Context - * @note This function is used as the default Link Register address if - * configTASK_RETURN_ADDRESS is not defined in FreeRTOSConfig.h * + * This function is used as the default return address for tasks if + * configTASK_RETURN_ADDRESS is not defined in FreeRTOSConfig.h. */ void prvTaskExitError( void ); -/** - * @brief User provided task return function. - * - * @ingroup Task Context - * - * @note Let the user override the pre-loading of the initial LR with - * the address of prvTaskExitError() in case it messes up unwinding of - * the stack in the debugger. - */ #ifdef configTASK_RETURN_ADDRESS #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #else - #define configTASK_RETURN_ADDRESS prvTaskExitError + #define portTASK_RETURN_ADDRESS prvTaskExitError #endif /* configTASK_RETURN_ADDRESS */ -/** - * @brief Function a task should execute if it exits its assigned function. - * - * @ingroup Task Context - * - * @note If configTASK_RETURN_ADDRESS is not defined this value shall be set to - * prvTaskExitError(). - */ -#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS - /** * @brief Returns the number of leading zeros in a 32 bit variable. * - * @param[in] ulBitmap 32 Bit long number to count zeros of. + * @param[in] ulBitmap 32-Bit number to count leading zeros in. * - * @return The number of leading zeros ulBitmap has. + * @return The number of leading zeros in ulBitmap. */ UBaseType_t ulPortCountLeadingZeros( UBaseType_t ulBitmap ); /** - * @brief Function meant to end the FreeRTOS Scheduler, not implemented on this port. + * @brief End the FreeRTOS scheduler. + * + * Not implemented on this port. + * * @ingroup Scheduler */ void vPortEndScheduler( void ); @@ -532,11 +434,6 @@ void vPortEndScheduler( void ); * @brief Mark that this port utilizes the onboard ARM MPU. * * @ingroup MPU Control - * - * @note The structures and methods of manipulating the MPU are contained - * within the port layer. Fills the xMPUSettings structure with the memory - * region information contained in xRegions. - * */ #define portUSING_MPU_WRAPPERS 1 @@ -546,139 +443,76 @@ void vPortEndScheduler( void ); * @ingroup Task Context * @ingroup MPU Control * - * @note This is done by performing a bitwise OR of this value and the task priority. - * For example, to create a privileged task at priority 2 the uxPriority - * parameter should be set to ( 2 | portPRIVILEGE_BIT ). + * A privileged task is created by performing a bitwise OR of this value and the + * task priority. For example, to create a privileged task at priority 2, the + * uxPriority parameter should be set to ( 2 | portPRIVILEGE_BIT ). */ #define portPRIVILEGE_BIT ( 0x80000000UL ) -/** @brief Size of the System Call Buffer in the TCB. */ - -#define portSYSTEM_CALL_STACK_SIZE configSYSTEM_CALL_STACK_SIZE - -/** @brief Size of an Access Control List (ACL) entry in bits. */ +/** + * @brief Size of an Access Control List (ACL) entry in bits. + */ #define portACL_ENTRY_SIZE_BITS ( 32UL ) /** * @brief Structure to hold the MPU Register Values. + * * @struct xMPU_REGION_REGISTERS * * @ingroup MPU Control * - * NOTE: Do not modify this structure. The ordering of this struct MUST - * line up with the ordering explained in portRESTORE_CONTEXT. + * @note The ordering of this struct MUST be in sync with the ordering in + * portRESTORE_CONTEXT. */ typedef struct MPU_REGION_REGISTERS { - /** - * @brief Member used to hold the MPU register value for the Region Size. - * @struct xMPU_REGION_REGISTERS - * @ingroup MPU Control - */ - uint32_t ulRegionSize; - - /** - * @brief Member used to hold the MPU register value for the Region Attributes. - * @struct xMPU_REGION_REGISTERS - * @ingroup MPU Control - */ - uint32_t ulRegionAttribute; - - /** - * @brief Member used to hold the MPU register value for the Region Base Address. - * @struct xMPU_REGION_REGISTERS - * @ingroup MPU Control - */ - uint32_t ulRegionBaseAddress; + uint32_t ulRegionSize; /* Information for MPU Region Size and Enable Register. */ + uint32_t ulRegionAttribute; /* Information for MPU Region Access Control Register. */ + uint32_t ulRegionBaseAddress; /* Information for MPU Region Base Address Register. */ } xMPU_REGION_REGISTERS; /** * @brief Structure to hold per-task System Call Stack information. + * * @struct xSYSTEM_CALL_STACK_INFO * * @ingroup Port Privilege * - * NOTE: Do not modify this structure. The ordering of this structure is expected - * to be this way in the assembly code of the port. + * @note The ordering of this structure MUST be in sync with the assembly code + * of the port. */ typedef struct SYSTEM_CALL_STACK_INFO { - /** - * @brief Stack Pointer of the task when it made a FreeRTOS System Call. - * @struct xSYSTEM_CALL_STACK_INFO - */ - uint32_t * pulTaskStackPointer; - - /** - * @brief Link Register of the task when it made a FreeRTOS System Call. - * @struct xSYSTEM_CALL_STACK_INFO - */ - uint32_t * pulLinkRegisterAtSystemCallEntry; - - /** - * @brief Pre-Set Stack Pointer to use when making a FreeRTOS System Call. - * @struct xSYSTEM_CALL_STACK_INFO - * @note This will point to the start of ulSystemCallStackBuffer[] - */ - uint32_t * pulSystemCallStackPointer; - - /** - * @brief Pre-Set Link Register to exit a FreeRTOS System Call. - * @struct xSYSTEM_CALL_STACK_INFO - * @note This value is set in pxPortInitialiseStack() to ensure after making - * a FreeRTOS System Call that the last LR jump is to vPortSystemCallExit() - */ - void * pulSystemCallLinkRegister; - - /** - * @brief Buffer to be used when performing a FreeRTOS System Call. - * @struct xSYSTEM_CALL_STACK_INFO - */ - uint32_t ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE ]; + uint32_t * pulTaskStackPointer; /**< Stack Pointer of the task when it made a FreeRTOS System Call. */ + uint32_t * pulLinkRegisterAtSystemCallEntry; /**< Link Register of the task when it made a FreeRTOS System Call. */ + uint32_t * pulSystemCallStackPointer; /**< Stack Pointer to use for executing a FreeRTOS System Call. */ + uint32_t * pulSystemCallExitAddress; /**< System call exit address. */ + uint32_t ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE ]; /**< Buffer to be used as stack when performing a FreeRTOS System Call. */ } xSYSTEM_CALL_STACK_INFO; /** - * @brief Per-Task MPU Settings structure stored in the TCB + * @brief Per-Task MPU settings structure stored in the TCB. * @struct xMPU_SETTINGS * * @ingroup MPU Control * @ingroup Task Context * @ingroup Port Privilege * - * NOTE: Do not modify this structure. The ordering of this structure is expected to be - * this way in the assembly code of the port. + * @note The ordering of this structure MUST be in sync with the assembly code + * of the port. */ typedef struct MPU_SETTINGS { - /** - * @brief Array of Per-Task MPU Register Values. Loaded on Task Context Restore. - * @struct xMPU_SETTINGS - */ xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS_IN_TCB ]; - - /** - * @brief Buffer that holds a Task's Context when being swapped out. - * @struct xMPU_SETTINGS - */ - uint32_t ulContext[ MAX_CONTEXT_SIZE ]; - - /** - * @brief Variable to hold FreeRTOS Privilege Settings. - * @struct xMPU_SETTINGS - */ uint32_t ulTaskFlags; - - /** - * @brief System Call Info structure that is stored in the TCB. - * @struct xMPU_SETTINGS - */ xSYSTEM_CALL_STACK_INFO xSystemCallStackInfo; + uint32_t ulContext[ CONTEXT_SIZE ]; /**< Buffer used to store task context. */ -#if( configENABLE_ACCESS_CONTROL_LIST == 1 ) - uint32_t ulAccessControlList[ ( configPROTECTED_KERNEL_OBJECT_POOL_SIZE - / portACL_ENTRY_SIZE_BITS ) - + 1UL ]; -#endif + #if( configENABLE_ACCESS_CONTROL_LIST == 1 ) + uint32_t ulAccessControlList[ ( configPROTECTED_KERNEL_OBJECT_POOL_SIZE + / portACL_ENTRY_SIZE_BITS ) + + 1UL ]; + #endif } xMPU_SETTINGS; #ifdef __cplusplus diff --git a/portable/GCC/ARM_CRx_MPU/portmacro_asm.h b/portable/GCC/ARM_CRx_MPU/portmacro_asm.h index fa4ba85c1c..16454d1233 100644 --- a/portable/GCC/ARM_CRx_MPU/portmacro_asm.h +++ b/portable/GCC/ARM_CRx_MPU/portmacro_asm.h @@ -37,8 +37,6 @@ extern "C" { #ifndef configTOTAL_MPU_REGIONS #error "Set configTOTAL_MPU_REGIONS to the humber of MPU regions in FreeRTOSConfig.h" -#elif( configTOTAL_MPU_REGIONS == 8 ) - #define portMPU_TOTAL_REGIONS ( 8UL ) #elif( configTOTAL_MPU_REGIONS == 12 ) #define portMPU_TOTAL_REGIONS ( 12UL ) #elif( configTOTAL_MPU_REGIONS == 16 ) @@ -47,112 +45,74 @@ extern "C" { #error "Set configTOTAL_MPU_REGIONS to the number of MPU regions in FreeRTOSConfig.h" #endif /* configTOTAL_MPU_REGIONS */ -/** On the ArmV7-R Architecture the Operating mode of the Processor is set - * using the Current Program Status Register (CPSR) Mode bits, [4:0]. - * The only registers banked between modes are the CPSR, Stack Pointer (R13), - * and the Link Register (R14). FIQ mode also banks the GPRs R8-R12 - * Of note, the only mode not "Privileged" is User Mode +/* + * The application write can disable Floating Point Unit (FPU) support by + * setting configENABLE_FPU to 0. Floating point context stored in TCB + * comprises of 32 floating point registers (D0-D31) and FPSCR register. + * Disabling FPU, therefore, reduces the per-task RAM usage by + * ( 32 + 1 ) * 4 = 132 bytes per task. + * + * BE CAREFUL DISABLING THIS: Certain standard library APIs try to optimize + * themselves by using the floating point registers. If the FPU support is + * disabled, the use of such APIs may result in memory corruption. + */ +#ifndef configENABLE_FPU + #define configENABLE_FPU 1 +#endif /* configENABLE_FPU */ + +#define portENABLE_FPU configENABLE_FPU + +/* On the ArmV7-R Architecture the Operating mode of the Processor is set + * using the Current Program Status Register (CPSR) Mode bits, [4:0]. The only + * unprivileged mode is User Mode. * * Additional information about the Processor Modes can be found here: * https://developer.arm.com/documentation/ddi0406/cb/System-Level-Architecture/The-System-Level-Programmers--Model/ARM-processor-modes-and-ARM-core-registers/ARM-processor-modes?lang=en * - * */ - -/** - * @brief CPSR Mode bit field value for User Mode. - * @ingroup Port Privilege - */ -#define USER_MODE 0x10U - -/** - * @brief CPSR Mode bit field value for Fast Interrupt Handler (FIQ) Mode. - * @ingroup Port Privilege - */ -#define FIQ_MODE 0x11U - -/** - * @brief CPSR Mode bit field value for Interrupt Handler (IRQ) Mode. - * @ingroup Port Privilege - */ -#define IRQ_MODE 0x12U - -/** - * @brief CPSR Mode bit field value for Supervisor (SVC) Mode. - * @ingroup Port Privilege - */ -#define SVC_MODE 0x13U - -/** - * @brief CPSR Mode bit field value for Monitor (MON) Mode. - * @ingroup Port Privilege - */ -#define MON_MODE 0x16U - -/** - * @brief CPSR Mode bit field value for Abort (ABT) Mode. - * @ingroup Port Privilege */ -#define ABT_MODE 0x17U /** - * @brief CPSR Mode bit field value for Hypervisor (HYP) Mode. - * @ingroup Port Privilege - */ -#define HYP_MODE 0x1AU - -/** - * @brief CPSR Mode bit field value for Undefined (UND) Mode. - * @ingroup Port Privilege - */ -#define UND_MODE 0x1BU - -/** - * @brief CPSR Mode bit field value for System (SYS) Mode. - * @ingroup Port Privilege - */ -#define SYS_MODE 0x1FU - -/** - * @brief Used to mark if a task should be created as a privileged task. + * @brief CPSR bits for various processor modes. * - * @ingroup Task Context - * @ingroup MPU Control - * - * @note This is done by performing a bitwise OR of this value and the task priority. - * For example, to create a privileged task at priority 2 the uxPriority - * parameter should be set to ( 2 | portPRIVILEGE_BIT ). + * @ingroup Port Privilege */ -#define portPRIVILEGE_BIT ( 0x80000000UL ) +#define USER_MODE 0x10U +#define FIQ_MODE 0x11U +#define IRQ_MODE 0x12U +#define SVC_MODE 0x13U +#define MON_MODE 0x16U +#define ABT_MODE 0x17U +#define HYP_MODE 0x1AU +#define UND_MODE 0x1BU +#define SYS_MODE 0x1FU /** * @brief Flag used to mark that a FreeRTOS Task is privileged. + * * @ingroup Port Privilege */ #define portTASK_IS_PRIVILEGED_FLAG ( 1UL << 1UL ) /** - * @brief SVC Number to use when requesting a context swap. + * @brief SVC numbers for various scheduler operations. + * * @ingroup Scheduler - * @note This value must not be in use in mpu_syscall_numbers.h + * + * @note These value must not be used in mpu_syscall_numbers.h. */ #define portSVC_YIELD 0x0100U - -/** - * @brief SVC Number to use when exiting a FreeRTOS System Call. - * @ingroup MPU Control - * @note This value must not be in use in mpu_syscall_numbers.h - */ #define portSVC_SYSTEM_CALL_EXIT 0x0104U /** - * @addtogroup MPU Control - * @note The Region Access Control Register is used to set MPU Region Settings. - * Further information about this register can be found in Arm's documentation + * @brief Macros required to manipulate MPU. + * + * Further information about MPU can be found in Arm's documentation * https://developer.arm.com/documentation/ddi0363/g/System-Control/Register-descriptions/c6--MPU-memory-region-programming-registers * */ -/* MPU Sub Region settings */ +/* MPU sub-region disable settings. This information is encoded in the MPU + * Region Size and Enable Register. */ #define portMPU_SUBREGION_0_DISABLE ( 0x1UL << 8UL ) #define portMPU_SUBREGION_1_DISABLE ( 0x1UL << 9UL ) #define portMPU_SUBREGION_2_DISABLE ( 0x1UL << 10UL ) @@ -162,7 +122,7 @@ extern "C" { #define portMPU_SUBREGION_6_DISABLE ( 0x1UL << 14UL ) #define portMPU_SUBREGION_7_DISABLE ( 0x1UL << 15UL ) -/* Default MPU regions */ +/* Default MPU regions. */ #define portFIRST_CONFIGURABLE_REGION ( 0 ) #define portLAST_CONFIGURABLE_REGION ( portMPU_TOTAL_REGIONS - 5UL ) #define portSTACK_REGION ( portMPU_TOTAL_REGIONS - 4UL ) @@ -171,198 +131,100 @@ extern "C" { #define portPRIVILEGED_RAM_REGION ( portMPU_TOTAL_REGIONS - 1UL ) #define portNUM_CONFIGURABLE_REGIONS \ ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1UL ) -/* Plus one to make space for the stack region*/ +/* Plus one to make space for the stack region. */ #define portTOTAL_NUM_REGIONS_IN_TCB ( portNUM_CONFIGURABLE_REGIONS + 1UL ) -/* MPU region sizes */ -#define portMPU_SIZE_32B ( 0x04UL << 1UL ) -#define portMPU_SIZE_64B ( 0x05UL << 1UL ) -#define portMPU_SIZE_128B ( 0x06UL << 1UL ) -#define portMPU_SIZE_256B ( 0x07UL << 1UL ) -#define portMPU_SIZE_512B ( 0x08UL << 1UL ) -#define portMPU_SIZE_1KB ( 0x09UL << 1UL ) -#define portMPU_SIZE_2KB ( 0x0AUL << 1UL ) -#define portMPU_SIZE_4KB ( 0x0BUL << 1UL ) -#define portMPU_SIZE_8KB ( 0x0CUL << 1UL ) -#define portMPU_SIZE_16KB ( 0x0DUL << 1UL ) -#define portMPU_SIZE_32KB ( 0x0EUL << 1UL ) -#define portMPU_SIZE_64KB ( 0x0FUL << 1UL ) -#define portMPU_SIZE_128KB ( 0x10UL << 1UL ) -#define portMPU_SIZE_256KB ( 0x11UL << 1UL ) -#define portMPU_SIZE_512KB ( 0x12UL << 1UL ) -#define portMPU_SIZE_1MB ( 0x13UL << 1UL ) -#define portMPU_SIZE_2MB ( 0x14UL << 1UL ) -#define portMPU_SIZE_4MB ( 0x15UL << 1UL ) -#define portMPU_SIZE_8MB ( 0x16UL << 1UL ) -#define portMPU_SIZE_16MB ( 0x17UL << 1UL ) -#define portMPU_SIZE_32MB ( 0x18UL << 1UL ) -#define portMPU_SIZE_64MB ( 0x19UL << 1UL ) -#define portMPU_SIZE_128MB ( 0x1AUL << 1UL ) -#define portMPU_SIZE_256MB ( 0x1BUL << 1UL ) -#define portMPU_SIZE_512MB ( 0x1CUL << 1UL ) -#define portMPU_SIZE_1GB ( 0x1DUL << 1UL ) -#define portMPU_SIZE_2GB ( 0x1EUL << 1UL ) -#define portMPU_SIZE_4GB ( 0x1FUL << 1UL ) - -/* MPU Device Memory Types */ -#define portMPU_REGION_STRONGLY_ORDERED ( 0x00UL ) -#define portMPU_REGION_DEVICE ( 0x01UL ) -#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x03UL ) -#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 12UL ) -#define portMPU_STRONGLYORDERED_SHAREABLE ( 0x0000UL ) -#define portMPU_DEVICE_SHAREABLE ( 0x0001UL ) -#define portMPU_DEVICE_NONSHAREABLE ( 0x0010UL ) -#define portMPU_NORMAL_OIWTNOWA_NONSHARED ( 0x0002UL ) -#define portMPU_NORMAL_OIWBNOWA_NONSHARED ( 0x0003UL ) -#define portMPU_NORMAL_OIWTNOWA_SHARED ( 0x0006UL ) -#define portMPU_NORMAL_OIWBNOWA_SHARED ( 0x0007UL ) -#define portMPU_NORMAL_OINC_NONSHARED ( 0x0008UL ) -#define portMPU_NORMAL_OIWBWA_NONSHARED ( 0x000BUL ) -#define portMPU_NORMAL_OINC_SHARED ( 0x000CUL ) -#define portMPU_NORMAL_OIWBWA_SHARED ( 0x000FUL ) - -/** - * @brief MPU_CTRL value for: No Access and No Execute - * - * @ingroup MPU Control - * - * @brief No Access in a Privileged Operating Mode - * No Access in User Mode - * Cannot Execute Code from this region - */ -#define portMPU_PRIV_NA_USER_NA_NOEXEC ( 0x1000UL ) - -/** - * @brief MPU_CTRL value for Privileged Read and Exec - * - * @ingroup MPU Control - * - * @note Read Only Access in Privileged Operating Modes. - * No Read/Write Access in User Mode - * Allowed to Execute Code from this region - */ -#define portMPU_PRIV_RO_USER_NA_EXEC ( 0x0500UL ) - -/** - * @brief MPU_CTRL value for Privileged Read, Write, and Exec - * - * @ingroup MPU Control - * - * Read/Write in a Privileged Operating Mode - * No Access in User Mode - * Allowed to Execute Code from this region - */ -#define portMPU_PRIV_RW_USER_NA_EXEC ( 0x0100UL ) - -/** - * @brief MPU_CTRL value for Read Only and Execute - * - * @ingroup MPU Control - * - * @note Read Only in a Privileged Operating Mode - * Read Only in User Mode - * Allowed to Execute Code from this region - * */ -#define portMPU_PRIV_RO_USER_RO_EXEC ( 0x0600UL ) - -/** - * @brief MPU_CTRL value for: Read, Execute, and Privileged Write - * - * @ingroup MPU Control - * - * @note Read/Write in a Privileged Operating Mode - * Read Only in User Mode - * Allowed to Execute Code from this region - */ -#define portMPU_PRIV_RW_USER_RO_EXEC ( 0x0200UL ) - -/** - * @brief MPU_CTRL value for: Read, Write, and Execute - * - * @ingroup MPU Control - * - * @note Read/Write in a Privileged Operating Mode - * Read/write in User Mode - * Allowed to Execute Code from this region - */ -#define portMPU_PRIV_RW_USER_RW_EXEC ( 0x0300UL ) - -/** - * @brief MPU_CTRL value for: Privileged Read, Write Only, no Execute - * - * @ingroup MPU Control - * - * @note Read/Write in a Privileged Operating Mode - * No Access in User Mode - * Cannot Execute Code from this region - */ -#define portMPU_PRIV_RW_USER_NA_NOEXEC ( 0x1100UL ) - -/** - * @brief MPU_CTRL value for: All Read, Privileged Write, no Execute - * - * @ingroup MPU Control - * - * Read/Write in a Privileged Operating Mode - * Read Only in User Mode - * Cannot Execute Code from this region - */ -#define portMPU_PRIV_RW_USER_RO_NOEXEC ( 0x1200UL ) - -/** - * @brief MPU_CTRL value for: Read, Write, no Execute - * - * @ingroup MPU Control - * - * @note Read/Write in a Privileged Operating Mode - * Read/Write in User Mode - * Cannot Execute Code from this region - */ -#define portMPU_PRIV_RW_USER_RW_NOEXEC ( 0x1300UL ) - -/** - * @brief MPU_CTRL value for: Privileged Read Only, No Execute - * - * @ingroup MPU Control - * - * @note Read Only in a Privileged Operating Mode - * No Access in User Mode - * Cannot Execute Code from this region - */ -#define portMPU_PRIV_RO_USER_NA_NOEXEC ( 0x1500UL ) - -/** - * @brief MPU_CTRL value for: Read Only, No Execute - * - * @ingroup MPU Control - * - * @note Read Only in a Privileged Operating Mode - * Read Only in User Mode - * Cannot Execute Code from this region - */ -#define portMPU_PRIV_RO_USER_RO_NOEXEC ( 0x1600UL ) +/* MPU region sizes. This information is encoded in the MPU Region Size and + * Enable Register. */ +#define portMPU_REGION_SIZE_32B ( 0x04UL << 1UL ) +#define portMPU_REGION_SIZE_64B ( 0x05UL << 1UL ) +#define portMPU_REGION_SIZE_128B ( 0x06UL << 1UL ) +#define portMPU_REGION_SIZE_256B ( 0x07UL << 1UL ) +#define portMPU_REGION_SIZE_512B ( 0x08UL << 1UL ) +#define portMPU_REGION_SIZE_1KB ( 0x09UL << 1UL ) +#define portMPU_REGION_SIZE_2KB ( 0x0AUL << 1UL ) +#define portMPU_REGION_SIZE_4KB ( 0x0BUL << 1UL ) +#define portMPU_REGION_SIZE_8KB ( 0x0CUL << 1UL ) +#define portMPU_REGION_SIZE_16KB ( 0x0DUL << 1UL ) +#define portMPU_REGION_SIZE_32KB ( 0x0EUL << 1UL ) +#define portMPU_REGION_SIZE_64KB ( 0x0FUL << 1UL ) +#define portMPU_REGION_SIZE_128KB ( 0x10UL << 1UL ) +#define portMPU_REGION_SIZE_256KB ( 0x11UL << 1UL ) +#define portMPU_REGION_SIZE_512KB ( 0x12UL << 1UL ) +#define portMPU_REGION_SIZE_1MB ( 0x13UL << 1UL ) +#define portMPU_REGION_SIZE_2MB ( 0x14UL << 1UL ) +#define portMPU_REGION_SIZE_4MB ( 0x15UL << 1UL ) +#define portMPU_REGION_SIZE_8MB ( 0x16UL << 1UL ) +#define portMPU_REGION_SIZE_16MB ( 0x17UL << 1UL ) +#define portMPU_REGION_SIZE_32MB ( 0x18UL << 1UL ) +#define portMPU_REGION_SIZE_64MB ( 0x19UL << 1UL ) +#define portMPU_REGION_SIZE_128MB ( 0x1AUL << 1UL ) +#define portMPU_REGION_SIZE_256MB ( 0x1BUL << 1UL ) +#define portMPU_REGION_SIZE_512MB ( 0x1CUL << 1UL ) +#define portMPU_REGION_SIZE_1GB ( 0x1DUL << 1UL ) +#define portMPU_REGION_SIZE_2GB ( 0x1EUL << 1UL ) +#define portMPU_REGION_SIZE_4GB ( 0x1FUL << 1UL ) + +/* MPU memory types. This information is encoded in the TEX, S, C and B bits + * of the MPU Region Access Control Register. */ +#define portMPU_REGION_STRONGLY_ORDERED_SHAREABLE ( 0x00UL ) /* TEX=000, S=NA, C=0, B=0. */ +#define portMPU_REGION_DEVICE_SHAREABLE ( 0x01UL ) /* TEX=000, S=NA, C=0, B=1. */ +#define portMPU_REGION_NORMAL_OIWTNOWA_NONSHARED ( 0x02UL ) /* TEX=000, S=0, C=1, B=0. */ +#define portMPU_REGION_NORMAL_OIWTNOWA_SHARED ( 0x06UL ) /* TEX=000, S=1, C=1, B=0. */ +#define portMPU_REGION_NORMAL_OIWBNOWA_NONSHARED ( 0x03UL ) /* TEX=000, S=0, C=1, B=1. */ +#define portMPU_REGION_NORMAL_OIWBNOWA_SHARED ( 0x07UL ) /* TEX=000, S=1, C=1, B=1. */ +#define portMPU_REGION_NORMAL_OINC_NONSHARED ( 0x08UL ) /* TEX=001, S=0, C=0, B=0. */ +#define portMPU_REGION_NORMAL_OINC_SHARED ( 0x0CUL ) /* TEX=001, S=1, C=0, B=0. */ +#define portMPU_REGION_NORMAL_OIWBWA_NONSHARED ( 0x0BUL ) /* TEX=001, S=0, C=1, B=1. */ +#define portMPU_REGION_NORMAL_OIWBWA_SHARED ( 0x0FUL ) /* TEX=001, S=1, C=1, B=1. */ +#define portMPU_REGION_DEVICE_NONSHAREABLE ( 0x10UL ) /* TEX=010, S=NA, C=0, B=0. */ + +/* MPU access permissions. This information is encoded in the XN and AP bits of + * the MPU Region Access Control Register. */ +#define portMPU_REGION_AP_BITMASK ( 0x07UL << 8UL ) +#define portMPU_REGION_XN_BITMASK ( 0x01UL << 12UL ) + +#define portMPU_REGION_PRIV_NA_USER_NA ( 0x00UL << 8UL ) +#define portMPU_REGION_PRIV_NA_USER_NA_EXEC ( portMPU_REGION_PRIV_NA_USER_NA ) /* Priv: X, Unpriv: X. */ +#define portMPU_REGION_PRIV_NA_USER_NA_NOEXEC ( portMPU_REGION_PRIV_NA_USER_NA | \ + portMPU_REGION_XN_BITMASK ) /* Priv: No Access, Unpriv: No Access. */ + +#define portMPU_REGION_PRIV_RW_USER_NA ( 0x01UL << 8UL ) +#define portMPU_REGION_PRIV_RW_USER_NA_EXEC ( portMPU_REGION_PRIV_RW_USER_NA ) /* Priv: RWX, Unpriv: X. */ +#define portMPU_REGION_PRIV_RW_USER_NA_NOEXEC ( portMPU_REGION_PRIV_RW_USER_NA | \ + portMPU_REGION_XN_BITMASK ) /* Priv: RW, Unpriv: No access. */ + +#define portMPU_REGION_PRIV_RW_USER_RO ( 0x02UL << 8UL ) +#define portMPU_REGION_PRIV_RW_USER_RO_EXEC ( portMPU_REGION_PRIV_RW_USER_RO ) /* Priv: RWX, Unpriv: RX. */ +#define portMPU_REGION_PRIV_RW_USER_RO_NOEXEC ( portMPU_REGION_PRIV_RW_USER_RO | \ + portMPU_REGION_XN_BITMASK ) /* Priv: RW, Unpriv: R. */ + +#define portMPU_REGION_PRIV_RW_USER_RW ( 0x03UL << 8UL ) +#define portMPU_REGION_PRIV_RW_USER_RW_EXEC ( portMPU_REGION_PRIV_RW_USER_RW ) /* Priv: RWX, Unpriv: RWX. */ +#define portMPU_REGION_PRIV_RW_USER_RW_NOEXEC ( portMPU_REGION_PRIV_RW_USER_RW | \ + portMPU_REGION_XN_BITMASK ) /* Priv: RW, Unpriv: RW. */ + +#define portMPU_REGION_PRIV_RO_USER_NA ( 0x05UL << 8UL ) +#define portMPU_REGION_PRIV_RO_USER_NA_EXEC ( portMPU_REGION_PRIV_RO_USER_NA ) /* Priv: RX, Unpriv: X. */ +#define portMPU_REGION_PRIV_RO_USER_NA_NOEXEC ( portMPU_REGION_PRIV_RO_USER_NA | \ + portMPU_REGION_XN_BITMASK ) /* Priv: R, Unpriv: No access. */ + +#define portMPU_REGION_PRIV_RO_USER_RO ( 0x06UL << 8UL ) +#define portMPU_REGION_PRIV_RO_USER_RO_EXEC ( portMPU_REGION_PRIV_RO_USER_RO ) /* Priv: RX, Unpriv: RX. */ +#define portMPU_REGION_PRIV_RO_USER_RO_NOEXEC ( portMPU_REGION_PRIV_RO_USER_RO | \ + portMPU_REGION_XN_BITMASK ) /* Priv: R, Unpriv: R. */ + +/* MPU region management. */ +#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 12UL ) +#define portMPU_REGION_ENABLE ( 0x01UL ) /** - * @brief MPU_CTRL value to enable an MPU Region - * @ingroup MPU Control - */ -#define portMPU_REGION_ENABLE ( 0x01UL ) - -/** This following section is used to create the proper size for the ulContext array. - * This array is where all registers related to a task's context are saved. - * The size of this array will depend on if the system is using an integrated - * Floating Point Unit (FPU) or not. If we are using the FPU we must save the - * Floating Point Status and Control Register (FPSCR), - * and the Floating Point Registers (FPRs). The FPSCR holds the conditional bits - * used for floating point calculations. The FPRs hold the actual floating point bits. - * The remainder of a task's context consists of the General Purpose Registers (GPRs). - * General Purpose Registers are used to manipulate almost all variables. - * The Current Program Status and Control Register, which holds the operating mode - * and bits that correspond to any conditional checks, such as if statements. - * And the Critical Nesting Depth of the task. + * @brief The size (in words) of a task context. * + * An array of this size is allocated in TCB where a task's context is saved + * when it is switched out. * - * For more information about the FPU, FPSCR, and FPRs please reference ARM's website: + * Information about Floating Point Unit (FPU): * https://developer.arm.com/documentation/den0042/a/Floating-Point * * Additional information related to the Cortex R4-F's FPU Implementation: @@ -371,7 +233,7 @@ extern "C" { * Additional information related to the Cortex R5-F's FPU Implementation: * https://developer.arm.com/documentation/ddi0460/d/FPU-Programmers-Model * - * Additional information related to the ArmV7-R CPSR + * Additional information related to the ArmV7-R CPSR: * https://developer.arm.com/documentation/ddi0406/cb/Application-Level-Architecture/Application-Level-Programmers--Model/The-Application-Program-Status-Register--APSR-?lang=en * * Additional information related to the GPRs: @@ -379,74 +241,36 @@ extern "C" { * */ -/** - * @brief The length in ulContext for the General Purpose Registers in bytes. - * @note There are 13 GPRs, R0-R12, the SP, and the LR. Each register is 32 - * bits, so the register context length is 15 registers * 4 bytes = 60 bytes. - */ -#define portREGISTER_LENGTH ( 15U * 4U ) - -/** - * If you KNOW that your system will not utilize the FPU in any capacity - * you can set portENABLE_FPU to 0. This will reduce the per-task RAM usage - * by ( 32 FPRs + 32 bit FPSCR ) * 4 bytes per register = 132 Bytes Per Task. - * It will also increase context swap speed, as these can then be ignored. - * BE CAREFUL DISABLING THIS: Certain APIs will try and optimize themselves - * by using the FPRs. If the FPU context is not saved and this happens it could - * be exceedingly difficult to debug why a strcpy() or other similar function - * seems to randomly fail. - */ -#ifndef configENABLE_FPU - #define configENABLE_FPU 1 -#endif /* configENABLE_FPU */ - -/** - * @brief Mark if the Floating Point Registers (FPRs) will be saved. - * @ingroup Task Context - * @note Using the FPU requires save FPRs into the task's context. As well as - * the Floating Point Status and Control Register (FPSCR). - */ -#define portENABLE_FPU configENABLE_FPU - #if( portENABLE_FPU == 1 ) - /** - * @brief Length of a Task's Register Context when using an FPU. - * @ingroup Task Context - * @note Task Context which is stored in ulContext in order, consists of: - * ulContext[ 0 ]: Critical Nesting Count: ulCriticalNesting - * ulContext[ 1 ]: Floating Point Status and Control Register - * ulContext[ 2 - 33 ]: Floating Point Registers: S0-S31 - * ulContext[ 34 - 46 ]: General Purpose Registers: R0-R12 - * ulContext[ 48 ]: Stack Pointer - * ulContext[ 49 ]: Link Register - * ulContext[ 50 ]: Program Counter - * ulContext[ 51 ]: Current Program Status and Control Register + /* + * +-------------------+-------+----------+--------+----------+----------+----------+------+ + * | ulCriticalNesting | FPSCR | S0-S31 | R0-R12 | SP (R13) | LR (R14) | PC (R15) | CPSR | + * +-------------------+-------+----------+--------+----------+----------+----------+------+ + * + * <------------------><------><---------><--------><---------><--------><----------><-----> + * 1 1 32 13 1 1 1 1 */ - #define MAX_CONTEXT_SIZE 51U + #define CONTEXT_SIZE 51U #else - /** - * @brief Length of a Task's Register Context when not using an FPU. - * @ingroup Task Context - * @note Task Context which is stored in ulContext in order, consists of: - * ulContext[ 0 ]: Critical Nesting Count: ulCriticalNesting - * ulContext[ 1 - 13 ]: General Purpose Registers: R0-R12 - * ulContext[ 14 ]: Stack Pointer - * ulContext[ 15 ]: Link Register - * ulContext[ 16 ]: Program Counter - * ulContext[ 17 ]: Current Program Status and Control Register + /* + * +-------------------+--------+----------+----------+----------+------+ + * | ulCriticalNesting | R0-R12 | SP (R13) | LR (R14) | PC (R15) | CPSR | + * +-------------------+--------+----------+----------+----------+------+ + * + * <------------------><--------><---------><--------><----------><-----> + * 1 13 1 1 1 1 */ - #define MAX_CONTEXT_SIZE 18U -#endif /* MAX_CONTEXT_SIZE */ + #define CONTEXT_SIZE 18U +#endif /* CONTEXT_SIZE */ /** - * @brief Numerical offset from the start of a TCB to xSystemCallStackInfo. - * @note This is used in portASM.S to load xSystemCallStackInfo from the TCB. - * This provides an easy way for the exception handlers to get this structure. - * The numerical value here should be equal to: - * sizeof( xRegion ) + sizeof( ulContext ) + sizeof( ulTaskFlags ) + * @brief Offset of xSystemCallStackInfo from the start of a TCB. */ -#define portSYSTEM_CALL_INFO_OFFSET \ - ( ( ( portTOTAL_NUM_REGIONS_IN_TCB * 3U ) + ( MAX_CONTEXT_SIZE ) + 1U ) * 4U ) +#define portSYSTEM_CALL_INFO_OFFSET \ + ( ( 1U /* pxTopOfStack. */ + \ + ( portTOTAL_NUM_REGIONS_IN_TCB * 3U ) + \ + 1U /* ulTaskFlags. */ \ + ) * 4U ) #ifdef __cplusplus } /* extern C */