mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
FreeRTOS SMP feature is developed in a separate SMP branch. This commit merges the SMP branch to main along with some fixes. User of SMP branch needs to apply the following changes in the port: * Rename configNUM_CORES to configNUMBER_OF_CORES * Define portSET/CLEAR_INTERRUPT_MASK for SMP * Define portENTER/EXIT_CRITICAL_FROM_ISR for SMP. vTaskEnterCriticalFromISR and vTaskExitCriticalFromISR should be used for these port macros * Update portSET/CLEAR_INTERRUPT_MASK_FROM_ISR implementation to mask interrupt only Call xTaskIncrementTick in critical section in port History of the development branch: * Add vTaskYieldWithinAPI for taskYIELD_IF_USING_PREEMPTION * Add configNUM_CORES config for SMP * Add portGET_CORE_ID porting config and default return 0 to compatible with single core demos * Replace xYieldPending with xYieldPendings for multiple cores * Add vTaskYieldWithinAPI function for yield pending if the task is in criticial section. This check are enabled only when portCRITICAL_NESTING_IN_TCB is enabled * taskYIELD_IF_USING_PREEMPTION use vTaskYieldWithinAPI when configUSE_PREEMPTION is set to 1 The following sections will be updated in other commits * taskYIELD_IF_USING_PREEMPTION usage in multiple cores * xYieldPendings usage in multiple cores * Use portYIELD_WITHIN_API for portYIELD_WITHIN_API for single core * Add xTaskRunState and xIsIdle in TCB * Add xTaskRunState and xIsIdle in TCB * Use xTaskAttribute to replace the xIsIdle in SMP TCB * Add pxCurrentTCBs for multiple cores * Keep pxCurrentTCB for single core * Add pxCurrentTCBs for SMP * Add xTaskGetCurrentTaskHandle for SMP * Replace taskSELECT_HIGHEST_PRIORITY_TASK with temporary prvSelectHighestPriorityTask * Add SMP critical section functions * Update vTaskEnterCritical and vTaskExitCritical functions for SMP * Add vTaskEnterCriticalFromISR and vTaskExitCriticalFromISR for SMP * Add SMP prvYieldCore and prvYieldForTask * Add idle tasks for SMP * Add minimal idle task function declaration * Align to use 0x00 for null terminator * Merge vTaskSuspendAll and xTaskResumeAll from SMP branch * Merge vTaskResume and xTaskResumeFromISR from SMP * Merge xTaskIncrementTick from SMP * Update prvYieldForTask usage in kernel APIs * Merge prvAddNewTaskToReadyList from SMP * Merge vTaskSwitchContext from SMP * Add vTaskSwitchContextForCore APIs to switch context for specific core * vTaskSwitchContext will switch context for current core * Merge vTaskDelete from SMP * Add prvYeildCore for single core to reduce multicore macros * Add taskTASK_IS_RUNNING for single core * Add taskTASK_IS_YIELDING * Merge vTaskSuspend from SMP * Set minimal idle task idle attribute * Set minimal idle task idle attribute in prvInitialiseNewTask * Move prvCreateIdleTasks forward and check return value * Add minimal idle hook config check * Fix xTaskResumeAll in SMP * xTaskRusmeAll do nothing when scheduler not running in SMP * check scheduler suspended when scheduler is running * Move suspend scheduler inside critical section * Update comment for uxSchedulerSuspended * Add back xPendingReadyList for single core * Use critical section for SMP * Add in ISR check in prvCheckForRunStateChange function * Add critical section protect for context switch * Add vTaskSwitchContextForCore declaration * Fix missing macro and check for single core * Fix task delete condition * Latest kernel move out the prvDeleteTask and the check condition should be TASK_IS_RUNNING * Use critical section to protect more in SMP for vTaskDelete * The condition task is running is not thread safe in SMP * Once we add the task to termination the task is still running and may add it back to other list. Which cause memory corruption. * Merge SMP prvSelectHighestPriorityTask to main * Merge prvCheckTasksWaitingTermination from SMP branch * Move prvDeleteTCB outside of critical section * Add NULL pointer check in prvCheckTasksWaitingTermination * Update for performance * Remove prvSelectHighestPriorityTask and vTaskSwitchContextForCore for -O0 performance in single core * Update prvSelectHighestPriorityTask * Merge vTaskYieldWithinAPI from SMP Update vTaskYieldWithinAPI from SMP * xTaskDelayUntil * xTaskDelay * ulTaskGenericNotifyTake * xTaskGenericNotifyWait * event_groups.c * queue.c * timers.c Add critical section protection * xTaskGetSchedulerState Update state check macro * vTaskGetInfo * eTaskGetState * Merge vTaskPrioritySet from SMP branch * Void prvYieldForTask return value in vTaskPrioritySet * Yield for SMP when set priority * Move vTaskDelay check uxSchedulerSuspended * Update code logic for performance * Fix yield for task in single core * Merge timer change from SMP branch * Split xTimerGenericCommand into xTimerGenericCommandFromTask and xTimerGenericCommandFromISR to remove the recursion path when called from ISRs. * Add portTIMER_CALLBACK_ATTRIBUTE for timer callback function * Add RP2040 SMP porting support * Seperate task state for SMP and single core * Merge configRUN_MULTIPLE_PRIORITIES from SMP branch * Merge configUSE_TASK_PREEMPTION_DISABLE from SMP * Merge configUSE_CORE_AFFINITY from SMP * Update pxYieldSpinLocks to per-cpu variable in SMP * Remove TODO log * Add suppport for ARM CM55 (#494) * Add supposrt for ARM CM55 * Fix file header * Remove duplicate code * Refactor portmacro.h 1. portmacro.h is re-factored into 2 parts - portmacrocommon.h which is common to all ARMv8-M ports and portmacro.h which is different for different compiler and architecture. This enables us to provide Cortex-M55 ports without code duplication. 2. Update copy_files.py so that it copies Cortex-M55 ports correctly - all files except portmacro.h are used from Cortex-M33 ports. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * add extra check for compiler time (#499) minor change to add extra check for compiler time to prevent bad config Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update feature_request.md (#500) * Update feature_request.md * Remove trailing spaces Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Add callback overrides for stream buffer and message buffers (#437) * Let each stream/message can use its own sbSEND_COMPLETED In FreeRTOS.h, set the default value of configUSE_SB_COMPLETED_CALLBACK to zero, and add additional space for the function pointer when the buffer created statically. In stream_buffer.c, modify the macro of sbSEND_COMPLETED which let the stream buffer to use its own implementation, and then add an pointer to the stream buffer's structure, and modify the implementation of the buffer creating and initializing Co-authored-by: eddie9712 <qw1562435@gmail.com> * Add configUSE_MUTEXES to function declarations in header (#504) This commit adds the configUSE_MUTEXES guard to the function declarations in semphr.h which are only available when configUSE_MUTEXES is set to 1. It was reported here - https://forums.freertos.org/t/mutex-missing-reference-to-configuse-mutexes-on-the-online-documentation/15231 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * RP2040: Remove incorrect assertion (#508) After the xEventGroupWaitBits in vProtLockInternalSpinUnlockWithWait there was an assertion about pxYiledSpinLock being NULL, however when xEventGroupWaitBits returns, IRQs have been re-enabled and so it is no longer safe to assert on the state which is protected by IRQs being disabled. Co-authored-by: graham sanderson <graham.sanderson@raspeberryi.com> * Ensure that xTaskGetCurrentTaskHandle is included (#507) This commits adds a check that INCLUDE_xTaskGetCurrentTaskHandle is set to 1. A compile time error message is produced if it is not set to 1. This is needed because stream_buffer.c uses xTaskGetCurrentTaskHandle. This was reported here - https://forums.freertos.org/t/xstreambufferreceive-include-xtaskgetcur/15283 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * RP2040: Allow FreeRTOS to be added to the parent CMake project post initialization of the Pico SDK (#497) Co-authored-by: graham sanderson <graham.sanderson@raspeberryi.com> * Update to TF-M version TF-Mv1.6.0 (#517) Signed-off-by: Xinyu Zhang <xinyu.zhang@arm.com> Change-Id: I0c15564b342873f9bd7a8240822e770950a0563e * Update submodule pointer of Community Supported Ports (#486) Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Paul Bartell <pbartell@amazon.com> Co-authored-by: Joseph Julicher <jjulicher@mac.com> * Add Cortex M7 r0p1 Errata 837070 workaround to CM4_MPU ports (#513) * Clarify Cortex M7 r0p1 errata number in r0p1 specific port. * Add ARM Cortex M7 r0p0 / r0p1 Errata 837070 workaround to CM4 MPU ports. Optionally, enable the errata workaround by defining configTARGET_ARM_CM7_r0p0 or configTARGET_ARM_CM7_r0p1 in FreeRTOSConfig.h. * Add r0p1 errata support to IAR port as well Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Change macro name to configENABLE_ERRATA_837070_WORKAROUND Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * RP2040: Use indirect reference for pxCurrentTCB (#525) * Posix: Removed unused signal set from port (#528) Co-authored-by: Jakob Hasse <0xjakob@users.noreply.github.com> * Add SBOM Generation in auto_release.yml (#524) * add portDONT_DISCARD to pxCurrentTCB (#479) This fixes link failures with LTO: /tmp/ccJbaKaD.ltrans0.ltrans.o: in function `pxCurrentTCBConst2': /root/project/FreeRTOS/portable/GCC/ARM_CM4F/port.c:249: undefined reference to `pxCurrentTCB' /usr/lib/gcc/arm-none-eabi/11.2.0/../../../../arm-none-eabi/bin/ld: /tmp/ccJbaKaD.ltrans0.ltrans.o: in function `pxCurrentTCBConst': /root/project/FreeRTOS/portable/GCC/ARM_CM4F/port.c:443: undefined reference to `pxCurrentTCB' * Implement MicroBlazeV9 stack protection (#523) * Implement stack protection for MicroBlaze (without MPU wrappers) * Update codecov action to v3.1.0 * Add vPortRemoveInterruptHandler API (#533) * Add xPortRemoveInterruptHandler API This API is added to the MicroBlazeV9 port. It enables the application writer to remove an interrupt handler. This was originally contributed in this PR - https://github.com/FreeRTOS/FreeRTOS-Kernel/pull/523 * Change API signature to return void This makes the API similar to vPortDisableInterrupt. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gavin Lambert <uecasm@users.noreply.github.com> * Fix NULL pointer dereference in vPortGetHeapStats When the heap is exhausted (no free block), start and end markers are the only blocks present in the free block list: +---------------+ +-----------> NULL | | | | V | + ----- + + ----- + | | | | | | | | | | | | + ----- + + ----- + xStart pxEnd The code block which traverses the list of free blocks to calculate heap stats used a do..while loop that moved past the end marker when the heap had no free block resulting in a NULL pointer dereference. This commit changes the do..while loop to while loop thereby ensuring that we never move past the end marker. This was reported here - https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/534 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Change type of message buffer handle (#537) * Block SIG_RESUME in the main thread of the Posix port so that sigwait works as expected (#532) Co-authored-by: alfred gedeon <28123637+alfred2g@users.noreply.github.com> * Update History.txt (#535) * Update History.txt Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add .syntax unified to GCC assembly functions (#538) This fixes the compilation issue with XC32 compiler. It was reported here - https://forums.freertos.org/t/xc32-v4-00-error-with-building-freertos-portasm-c/14357/4 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Paul Bartell <pbartell@amazon.com> * Generalize Thread Local Storage (TLS) support (#540) * Generalize Thread Local Storage (TLS) support FreeRTOS's Thread Local Storage (TLS) support used variables and functions from newlib, thereby making the TLS support specific to newlib. This commit generalizes the TLS support so that it can be used with other c-runtime libraries also. The default behavior for newlib support is still kept same for backward compatibility. The application writer would need to set configUSE_C_RUNTIME_TLS_SUPPORT to 1 in their FreeRTOSConfig.h and define the following macros to support TLS for a c-runtime library: 1. configTLS_BLOCK_TYPE - Type used to define the TLS block in TCB. 2. configINIT_TLS_BLOCK( xTLSBlock ) - Allocate and initialize memory block for the task's TLS Block. 3. configSET_TLS_BLOCK( xTLSBlock ) - Switch C-Runtime's TLS Block to point to xTLSBlock. 4. configDEINIT_TLS_BLOCK( xTLSBlock ) - Free up the memory allocated for the task's TLS Block. The following is an example to support TLS for picolibc: #define configUSE_C_RUNTIME_TLS_SUPPORT 1 #define configTLS_BLOCK_TYPE void* #define configINIT_TLS_BLOCK( xTLSBlock ) _init_tls( xTLSBlock ) #define configSET_TLS_BLOCK( xTLSBlock ) _set_tls( xTLSBlock ) #define configDEINIT_TLS_BLOCK( xTLSBlock ) Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Change default value of INCLUDE_xTaskGetCurrentTaskHandle (#542) * Include string.h at the top of portable/GCC/ARM_CA9/port.c to prevent memset() generating a warning. (#430) Co-authored-by: none <unknown> * Move some of the complex pre-processor guards on prvWriteNameToBuffer() to compile time checks in FreeRTOS.h. Co-authored-by: Paul Bartell <pbartell@amazon.com> * Fix formatting of FreeRTOS.h * correct grammar in include/FreeRTOS.h Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Fix warnings in posix port (#544) Fixes warnings about unused parameters and variables when built with `-Wall -Wextra`. * Add support for MISRA rule 20.7 (#546) Misra rule 20.7 requires parenthesis to all parameter names in macro definitions. The issue was reported here : https://forums.freertos.org/t/misra-20-7-compatibility/15385 * Add FreeRTOS config directory to include dirs (#548) This allows the application write to set FREERTOS_CONFIG_FILE_DIRECTORY to whichever directory the FreeRTOSConfig.h file exists in. This was reported here - https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/545 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * [Fix] Type for pointers operations (#550) * fix type for pointers operations in some places: size_t -> portPOINTER_SIZE_TYPE * fix pointer arithmetics * fix xAddress type * RISC-V: Add support for RV32E extension in GCC port (#543) Co-authored-by: Joseph Julicher <jjulicher@mac.com> * Added checks for index in ThreadLocalStorage APIs (#552) Added checks for ( xIndex >= 0 ) in ThreadLocalStorage APIs * Update of three badly terminated macro definitions (#555) * Update of three badly terminated macro definitions - vTaskDelayUntil() to conform to usual pattern do { ... } while(0) - vTaskNotifyGiveFromISR() and - vTaskGenericNotifyGiveFromISR() to remove extra terminating semicolons - This PR addresses issues #553 and #554 * Adjust formatting of task.h Co-authored-by: Paul Bartell <pbartell@amazon.com> * M85 support (#556) * Extend support to Arm Cortex-M85 Signed-off-by: Gabor Toth <gabor.toth@arm.com> Change-Id: I679ba8e193638126b683b651513f08df445f9fe6 * Add generated Cortex-M85 support files Signed-off-by: Gabor Toth <gabor.toth@arm.com> Change-Id: Ib329d88623c2936ffe3e9a24f5d6e07655e4e5c8 * Extend Trusted Firmware M port Extend Trusted Firmware M port to Cortex-M23, Cortex-M55 and Cortex-M85. Signed-off-by: Gabor Toth <gabor.toth@arm.com> Change-Id: If8f1081acfd04e547b3227579e70e355a6adffe3 * Re-run copy_files.py script Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Gabor Toth <gabor.toth@arm.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * portable-RP2040: Fix typo in README.md (#559) Replace "import" with "include" in cmake code sample. * Update CMakeLists.txt for Cortex-M55 and Cortex-M85 ports (#560) * Annotate ports CMakeLists.txt with port details * CMake: Add Cortex-M55 and Cortex-M85 ports * Use highest numbered MPU regions for kernel ARMv7-M allows overlapping MPU regions. When 2 MPU regions overlap, the MPU configuration of the higher numbered MPU region is applied. For example, if a memory area is covered by 2 MPU regions 0 and 1, the memory permissions for MPU region 1 are applied. We use 5 MPU regions for kernel code and kernel data protections and leave the remaining for the application writer. We were using lowest numbered MPU regions (0-4) for kernel protections and leaving the remaining for the application writer. The application writer could configure those higher numbered MPU regions to override kernel protections. This commit changes the code to use highest numbered MPU regions for kernel protections and leave the remaining for the application writer. This ensures that the application writer cannot override kernel protections. We thank the SecLab team at Northeastern University for reporting this issue. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Make RAM regions non-executable This commit makes the privileged RAM and stack regions non-executable. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Remove local stack variable form MPU wrappers It was possible for a third party that had already independently gained the ability to execute injected code to achieve further privilege escalation by branching directly inside a FreeRTOS MPU API wrapper function with a manually crafted stack frame. This commit removes the local stack variable `xRunningPrivileged` so that a manually crafted stack frame cannot be used for privilege escalation by branching directly inside a FreeRTOS MPU API wrapper. We thank Certibit Consulting, LLC, Huazhong University of Science and Technology and the SecLab team at Northeastern University for reporting this issue. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Restrict unpriv task to invoke code with privilege It was possible for an unprivileged task to invoke any function with privilege by passing it as a parameter to MPU_xTaskCreate, MPU_xTaskCreateStatic, MPU_xTimerCreate, MPU_xTimerCreateStatic, or MPU_xTimerPendFunctionCall. This commit ensures that MPU_xTaskCreate and MPU_xTaskCreateStatic can only create unprivileged tasks. It also removes the following APIs: 1. MPU_xTimerCreate 2. MPU_xTimerCreateStatic 3. MPU_xTimerPendFunctionCall We thank Huazhong University of Science and Technology for reporting this issue. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Update History.txt Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Update History.txt as per the PR feedback Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Update RISC-V IAR port to support vector mode. (#458) * Update RISC-V IAR port to support vector mode. * uncrustify Co-authored-by: David Chalco <david@chalco.io> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: alfred gedeon <28123637+alfred2g@users.noreply.github.com> * Added better pointer declaration readability (#567) * Add better pointer declaration readability I revised the declaration of single-line pointers by splitting it into multiple lines. Now, every pointer is declared (and initialized accordingly) on its own line. This refactoring should enhance readability and decrease the probability of error when a new pointer is added/removed or a current one has its initialization value modified. Signed-off-by: Cristian Cristea <cristiancristea00@gmail.com> * Remove unnecessary whitespace characters and lines It removes whitespace characters at the end of lines (empty or othwerwise) and clear lines at the end of the file (only one remains). It is an automatic operation done by git. Signed-off-by: Cristian Cristea <cristiancristea00@gmail.com> Signed-off-by: Cristian Cristea <cristiancristea00@gmail.com> * Update doc comments in task.h (#570) Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Tickless idle fixes/improvement (#59) * Fix tickless idle when stopping systick on zero... ...and don't stop SysTick at all in the eAbortSleep case. Prior to this commit, if vPortSuppressTicksAndSleep() happens to stop the SysTick on zero, then after tickless idle ends, xTickCount advances one full tick more than the time that actually elapsed as measured by the SysTick. See "bug 1" in this forum post: https://forums.freertos.org/t/ultasknotifytake-timeout-accuracy/9629/40 SysTick ------- The SysTick is the hardware timer that provides the OS tick interrupt in the official ports for Cortex M. SysTick starts counting down from the value stored in its reload register. When SysTick reaches zero, it requests an interrupt. On the next SysTick clock cycle, it loads the counter again from the reload register. To get periodic interrupts every N SysTick clock cycles, the reload register must be N - 1. Bug Example ----------- - Idle task calls vPortSuppressTicksAndSleep(xExpectedIdleTime = 2). [Doesn't have to be "2" -- could be any number.] - vPortSuppressTicksAndSleep() stops SysTick, and the current-count register happens to stop on zero. - SysTick ISR executes, setting xPendedTicks = 1 - vPortSuppressTicksAndSleep() masks interrupts and calls eTaskConfirmSleepModeStatus() which confirms the sleep operation. *** - vPortSuppressTicksAndSleep() configures SysTick for 1 full tick (xExpectedIdleTime - 1) plus the current-count register (which is 0) - One tick period elapses in sleep. - SysTick wakes CPU, ISR executes and increments xPendedTicks to 2. - vPortSuppressTicksAndSleep() calls vTaskStepTick(1), then returns. - Idle task resumes scheduler, which increments xTickCount twice (for xPendedTicks = 2) In the end, two ticks elapsed as measured by SysTick, but the code increments xTickCount three times. The root cause is that the code assumes the SysTick current-count register always contains the number of SysTick counts remaining in the current tick period. However, when the current-count register is zero, there are ulTimerCountsForOneTick counts remaining, not zero. This error is not the kind of time slippage normally associated with tickless idle. *** Note that a recent commit https://github.com/FreeRTOS/FreeRTOS-Kernel/commit/e1b98f0 results in eAbortSleep in this case, due to xPendedTicks != 0. That commit does mostly resolve this bug without specifically mentioning it, and without this commit. But that resolution allows the code in port.c not to directly address the special case of stopping SysTick on zero in any code or comments. That commit also generates additional instances of eAbortSleep, and a second purpose of this commit is to optimize how vPortSuppressTicksAndSleep() behaves for eAbortSleep, as noted below. This commit also includes an optimization to avoid stopping the SysTick when eTaskConfirmSleepModeStatus() returns eAbortSleep. This optimization belongs with this fix because the method of handling the SysTick being stopped on zero changes with this optimization. * Fix imminent tick rescheduled after tickless idle Prior to this commit, if something other than systick wakes the CPU from tickless idle, vPortSuppressTicksAndSleep() might cause xTickCount to increment once too many times. See "bug 2" in this forum post: https://forums.freertos.org/t/ultasknotifytake-timeout-accuracy/9629/40 SysTick ------- The SysTick is the hardware timer that provides the OS tick interrupt in the official ports for Cortex M. SysTick starts counting down from the value stored in its reload register. When SysTick reaches zero, it requests an interrupt. On the next SysTick clock cycle, it loads the counter again from the reload register. To get periodic interrupts every N SysTick clock cycles, the reload register must be N - 1. Bug Example ----------- - CPU is sleeping in vPortSuppressTicksAndSleep() - Something other than the SysTick wakes the CPU. - vPortSuppressTicksAndSleep() calculates the number of SysTick counts until the next tick. The bug occurs only if this number is small. - vPortSuppressTicksAndSleep() puts this small number into the SysTick reload register, and starts SysTick. - vPortSuppressTicksAndSleep() calls vTaskStepTick() - While vTaskStepTick() executes, the SysTick expires. The ISR pends because interrupts are masked, and SysTick starts a 2nd period still based on the small number of counts in its reload register. This 2nd period is undesirable and is likely to cause the error noted below. - vPortSuppressTicksAndSleep() puts the normal tick duration into the SysTick's reload register. - vPortSuppressTicksAndSleep() unmasks interrupts before the SysTick starts a new period based on the new value in the reload register. [This is a race condition that can go either way, but for the bug to occur, the race must play out this way.] - The pending SysTick ISR executes and increments xPendedTicks. - The SysTick expires again, finishing the second very small period, and starts a new period this time based on the full tick duration. - The SysTick ISR increments xPendedTicks (or xTickCount) even though only a tiny fraction of a tick period has elapsed since the previous tick. The bug occurs when *two* consecutive small periods of the SysTick are both counted as ticks. The root cause is a race caused by the small SysTick period. If vPortSuppressTicksAndSleep() unmasks interrupts *after* the small period expires but *before* the SysTick starts a period based on the full tick period, then two small periods are counted as ticks when only one should be counted. The end result is xTickCount advancing nearly one full tick more than time actually elapsed as measured by the SysTick. This is not the kind of time slippage normally associated with tickless idle. After this commit the code starts the SysTick and then immediately modifies the reload register to ensure the very short cycle (if any) is conducted only once. This strategy requires special consideration for the build option that configures SysTick to use a divided clock. To avoid waiting around for the SysTick to load value from the reload register, the new code temporarily configures the SysTick to use the undivided clock. The resulting timing error is typical for tickless idle. The error (commonly known as drift or slippage in kernel time) caused by this strategy is equivalent to one or two counts in ulStoppedTimerCompensation. This commit also updates comments and #define symbols related to the SysTick clock option. The SysTick can optionally be clocked by a divided version of the CPU clock (commonly divide-by-8). The new code in this commit adjusts these comments and symbols to make them clearer and more useful in configurations that use the divided clock. The fix made in this commit requires the use of these symbols, as noted in the code comments. * Fix tickless idle with alternate systick clocking Prior to this commit, in configurations using the alternate SysTick clocking, vPortSuppressTicksAndSleep() might cause xTickCount to jump ahead as much as the entire expected idle time or fall behind as much as one full tick compared to time as measured by the SysTick. SysTick ------- The SysTick is the hardware timer that provides the OS tick interrupt in the official ports for Cortex M. SysTick starts counting down from the value stored in its reload register. When SysTick reaches zero, it requests an interrupt. On the next SysTick clock cycle, it loads the counter again from the reload register. The SysTick has a configuration option to be clocked by an alternate clock besides the core clock. This alternate clock is MCU dependent. Scenarios Fixed --------------- The new code in this commit handles the following scenarios that were not handled correctly prior to this commit. 1. Before the sleep, vPortSuppressTicksAndSleep() stops the SysTick on zero, long after SysTick reached zero. Prior to this commit, this scenario caused xTickCount to jump ahead one full tick for the same reason documented here:0c7b04bd3a
2. After the sleep, vPortSuppressTicksAndSleep() stops the SysTick before it loads the counter from the reload register. Prior to this commit, this scenario caused xTickCount to jump ahead by the entire expected idle time (xExpectedIdleTime) because the current-count register is zero before it loads from the reload register. 3. Prior to return, vPortSuppressTicksAndSleep() attempts to start a short SysTick period when the current SysTick clock cycle has a lot of time remaining. Prior to this commit, this scenario could cause xTickCount to fall behind by as much as nearly one full tick because the short SysTick cycle never started. Note that #3 is partially fixed by967acc9b20
even though that commit addresses a different issue. So this commit completes the partial fix. * Improve comments and name of preprocessor symbol Add a note in the code comments that SysTick requests an interrupt when decrementing from 1 to 0, so that's why stopping SysTick on zero is a special case. Readers might unknowingly assume that SysTick requests an interrupt when wrapping from 0 back to the load-register value. Reconsider new "_SETTING" suffix since "_CONFIG" suffix seems more descriptive. The code relies on *both* of these preprocessor symbols: portNVIC_SYSTICK_CLK_BIT portNVIC_SYSTICK_CLK_BIT_CONFIG **new** A meaningful suffix is really helpful to distinguish the two symbols. * Revert introduction of 2nd name for NVIC register When I added portNVIC_ICSR_REG I didn't realize there was already a portNVIC_INT_CTRL_REG, which identifies the same register. Not good to have both. Note that portNVIC_INT_CTRL_REG is defined in portmacro.h and is already used in this file (port.c). * Replicate to other Cortex M ports Also set a new fiddle factor based on tests with a CM4F. I used gcc, optimizing at -O1. Users can fine-tune as needed. Also add configSYSTICK_CLOCK_HZ to the CM0 ports to be just like the other Cortex M ports. This change allowed uniformity in the default tickless implementations across all Cortex M ports. And CM0 is likely to benefit from configSYSTICK_CLOCK_HZ, especially considering new CM0 devices with very fast CPU clock speeds. * Revert changes to IAR-CM0-portmacro.h portNVIC_INT_CTRL_REG was already defined in port.c. No need to define it in portmacro.h. * Handle edge cases with slow SysTick clock Co-authored-by: Cobus van Eeden <35851496+cobusve@users.noreply.github.com> Co-authored-by: abhidixi11 <44424462+abhidixi11@users.noreply.github.com> Co-authored-by: Joseph Julicher <jjulicher@mac.com> Co-authored-by: alfred gedeon <28123637+alfred2g@users.noreply.github.com> * Merge SMP commit45dd83a8e
*45dd83a8e
| 2022-06-09 | Fix RP2040 assertion due to yield spin lock info being wrongly shared between multiple cores (#501) * Merge SMPb87dfa3e9
*b87dfa3e9
| 2022-06-04 | RP2040: Allow FreeRTOS to be added to the parent CMake project post initialization of the Pico SDK * Merge SMP13f034eb7
*13f034eb7
| 2022-06-24 | RP2040: Fix compiler warning and comment (#509) * Fix compiler warning and spelling * Fix Add new task for single core when scheduler not running * Fix priority set when task is not in ready list for single core * Fix vTaskResume when task is not running * Fix uncrustify formating warning * Add portCHECK_IF_IN_ISR for SMP * Format vTaskSwitchContext * Fix vTaskSwitchContextForCore bug due to uncrustify * First review - did not build yet Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Corresponding changes in FreeRTOS.h and task.h Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Fix the single core compilation * vTaskSwtichContextForCore rename vTaskSwitchContext * vTaskYieldWithinAPI for single core * pxCurrentTCBs for single core in xTaskIncrementTick * Fix compilation warning * Update xTaskGetCurrentTaskHandleCPU API * Use BaseType_t instead of UBaseType_t * Make the list traverse loop more readable Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Remove unnecessary loop in xTaskIncrementTick for single core * Update uxSchedulerSuspended with ISR lock in prvCheckForRunStateChange * Updated ESP32 port-layer to ESP-IDF `v4.4.2` (#572) * Xtensa_ESP32: Added esp-idf v4.4.2 specific changes * Xtensa_ESP32: Updated SPDX license identifiers * Add warning message to ensure min stack size (#575) Co-authored-by: alfred gedeon <28123637+alfred2g@users.noreply.github.com> * Removed the 'configASSERT( xInheritanceOccurred == pdFALSE )' assertion from xQueueSemaphoreTake as the reasoning behind it is wrong; it can trigger on wrongly on highly-contested semaphores on multicore systems. See https://forums.freertos.org/t/15967 (#576) Co-authored-by: Niklas Gürtler <niklas.guertler@tacterion.com> * Update the NIOSII port to enable longer jumps (#578) Update the NIOSII port so it works on systems with more RAM as per https://forums.freertos.org/t/nios-ii-r-nios2-call26-noat-linker-error/16028 * Update Cortex-M55 and Cortex-M85 ports (#579) These were missed when PR #59 was merged. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Fix context switch when time slicing is off (#568) * Fix context switch when time slicing is off When time slicing is off, context switch should only happen when a task with priority higher than the currently executing one is unblocked. Earlier the code was invoking a context switch even when a task with priority equal the currently executing task was unblocked. This commit fixes the code to only do a context switch when a higher priority task is unblocked. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Merge commit "Add support for retrieving a task's uxCoreAffinityMask with the vTaskGetInfo() API" * Merge commit8128208bde
* Use taskENTER/EXIT_CRITICAL_FROM_ISR (#38) * Enter critical section from is implemented differently for single core and smp. Use taskENTER/EXIT_CRITICAL_FROM_ISR in source. * Improve single core unit test coverage (#42) * prvCreateIldeTask use configNUM_CORES * First time yield in idle task in SMP only * prvCheckTasksWaitingTermination check pxTCB NULL pointer for SMP only. Single core won't have to check the pxTCB * Yield for task when core affinity changed (#41) * Yield for task when the task is linked to new allowed cores Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Remove builtin clz in prvSelectHighestPriorityTask (#37) * Remove builtin clz in prvSelectHighestPriorityTask * Move critical nesting count to port (#47) * Move the critical nesting management to port layer Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Move critical nesting in TCB macro to tasks.c * Add RP2040 support maintain critical nesting count in TCB * Fix formatting * RP2040 maintain critical nesting count in port * Fix constant type Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Rename config num cores (#48) * Rename configNUM_CORES to configNUMBER_OF_CORES * Fix the task selection when task yields (#54) * Move xTaskIncrementTick critical section to port (#55) * Port should use taskENTER/EXIT_CRITICAL_FROM_ISR * Not preempt equal priority task in the following functions (#56) Not to preempt equal priority task in the following functions * vTaskResume * vTaskResumeFromISR * vTaskPrioritySet * vTaskCoreAffinitySet * Remove implicit test (#49) * Remove taskTASK_IS_RUNNING implicit test * Remove portCHECK_IF_IN_ISR implicit test * Fix taskVALID_CORE_ID implicit test * Remove configASSERT implicit test * Fix preempt equal priority task in xTaskIncrementTick (#58) * Not preempt equal priority when a task is removed from delay list. Process time sharing is handle in the logic below. * Remove the xPreemptEqualPriority parameter of prvYieldForTask * Remove prvSelectHighestPriorityTask call in vTaskSuspend (#59) * Every core starts with an idle task in SMP implementation and taskTASK_IS_RUNNING only return ture when the task is idle task before scheduler started. So prvSelectHighestPriorityTask won't be called in vTaskSuspend before scheduler started. * Update prvSelectHighestPriorityTask to ensure that this function is called only when scheduler started. * Adding portIDLE_TASK_TEST_MOCK in idle task function (#66) * Adding configIDLE_TASK_HOOK in idle task function * Add INFINITE_LOOP macro to test idle task function (#67) * Remove configIDLE_TASK_HOOK * Add INFINIT_LOOP. Unit test can redefine this macro to mock the function. * portYield is not called when exit critical section from ISR (#60) * Reference SMP branch * Fix list index is moved in prvSearchForNameWithinSingleList (#61) * index pointer should not be moved in SMP * Yield for priority inherit and disinherit (#64) * Yield the core runs the task with prority changed when priority inheritance and disinheritance. * fix performance counting for SMP (#65) * performance counting: ulTaskSwitchedInTime and ulTotalRunTime must be (#618) arrays, index is core number --------- Co-authored-by: Hardy Griech <ntbox@gmx.net> * Remomve unreachable assert in prvCheckForRunStateChange (#68) * Previous assert already ensure this assert won't be triggered * Remove unreachable code in preYieldForTask (#69) * xLowestPriorityCore index can't be greater than configNUMBER_OF_CORES * Add first version of XCOREAI port (#63) * xTaskIncrementTick need to be called in critical section * Rename configNUM_CORES to configNUMBER_OF_CORES * Define portENTER/EXIT_CRITICAL_FROM_ISR for SMP * portSET/CLEAR_INTERRUPT_MASK_FROM_ISR is not used in SMP * Fix configDEINIT_TLS_BLOCK (#73) configDEINIT_TLS_BLOCK() should deinit the TLS block of the task to being deleted instead of the currently running task. * Sync with main branch (#71) * Fix array-bounds compiler warning on gcc11+ in list.h (#580) listGET_OWNER_OF_NEXT_ENTRY computes `( pxConstList )->pxIndex->pxNext` after verifying that `( pxConstList )->pxIndex` points to `xListEnd`, which due to being a MiniListItem_t, can be shorter than a ListItem_t. Thus, `( pxConstList )->pxIndex` is a `ListItem_t *` that extends past the end of the `List_t` whose `xListEnd` it points to. This is fixed by accessing `pxNext` through a `MiniListItem_t` instead. * move the prototype for vApplicationIdleHook to task.h. (#600) Co-authored-by: pluess <pluess@faulhorn.mw.iap.unibe.ch> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update equal priority task preemption (#603) * vTaskResume and vTaskPrioritySet don't preempt equal priority task * Update vTaskResumeAll not to preempt task with equal priority * Fix in xTaskResumeFromISR * Update FreeRTOS/FreeRTOS build checks (#613) This is needed to be compatible with the refactoring done in this PR - https://github.com/FreeRTOS/FreeRTOS/pull/889 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add ulTaskGetRunTimeCounter and ulTaskGetRunTimePercent (#611) Allow ulTaskGetIdleRunTimeCounter and ulTaskGetIdleRunTimePercent to be used whenever configGENERATE_RUN_TIME_STATS is enabled, as this is the only requirement for these functions to work. * Fix some CMake documentation typos (#616) The quick start instructions for CMake mention the "master" git branch which has been replaced by "main" in the current repo. The main CMakeLists.txt documents how to integrate a custom port. Fix a typo in the suggested CMake code. * Added support of 64bit events. (#597) * Added support of 64bit even Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Added missing brackets Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Made proper name for tick macro. Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Improved macro evaluation Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Fixed missed port files + documentation Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Changes made on PR Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Fix macro definition. Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Formatted code with uncrustify Signed-off-by: Cervenka Dusan <cervenka@acrios.com> --------- Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Introduce portMEMORY_BARRIER for Microblaze port. (#621) The introduction of `portMEMORY_BARRIER` will ensure the places in the kernel use a barrier will work. For example, `xTaskResumeAll` has a memory barrier to ensure its correctness when compiled with optimization enabled. Without the barrier `xTaskResumeAll` can fail (e.g. start reading and writing to address 0 and/or infinite looping) when `xPendingReadyList` contains more than one task to restore. In `xTaskResumeAll` the compiler chooses to cache the `pxTCB` the first time through the loop for use in every subsequent loop. This is incorrect as the removal of `pxTCB->xEventListItem` will actually change the value of `pxTCB` if it was read again at the top of the loop. The barrier forces the compiler to read `pxTCB` again at the top of the loop. The compiler is operating correctly. The removal `pxTCB->xEventListItem` executes on a `List_t *` and `ListItem_t *`. This means that the compiler can assume that any `MiniListItem_t` values are unchanged by the loop (i.e. "strict-aliasing"). This allows the compiler to cache `pxTCB` as it is obtained via a `MiniListItem_t`. This is incorrect in this case because it is possible for a `ListItem_t *` to actually alias a `MiniListItem_t`. This is technically a "violation of aliasing rules" so we use the the barrier to disable the strict-aliasing optimization in this loop. * Do not call exit() on MSVC Port when calling vPortEndScheduler (#624) * make port exitable * correctly set xPortRunning to False * add suggestions from Review Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * add suggestions from Review Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update PR template to include checkbox for Unit Test related changes (#627) * Fix build failure introduced in PR #597 (#629) The PR #597 introduced a new config option configTICK_TYPE_WIDTH_IN_BITS which can be defined to one of the following: * TICK_TYPE_WIDTH_16_BITS - Tick type is 16 bit wide. * TICK_TYPE_WIDTH_32_BITS - Tick type is 32 bit wide. * TICK_TYPE_WIDTH_64_BITS - Tick type is 64 bit wide. Earlier we supported 16 and 32 bit width for tick type which was controlled using the config option configUSE_16_BIT_TICKS. The PR tried to maintain backward compatibility by honoring configUSE_16_BIT_TICKS. The backward compatibility did not work as expected though, as the macro configTICK_TYPE_WIDTH_IN_BITS was used before it was defined. This PR addresses it by ensuring that the macro configTICK_TYPE_WIDTH_IN_BITS is defined before it is used. Testing 1. configUSE_16_BIT_TICKS is defined to 0. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 109e: 4b50 ldr r3, [pc, #320] ; (11e0 <xTaskIncrementTick+0x150>) 10a0: f8d3 4134 ldr.w r4, [r3, #308] ; 0x134 10a4: 3401 adds r4, #1 10a6: f8c3 4134 str.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 32 bit. 2. configUSE_16_BIT_TICKS is defined to 1. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 10e2: 4b53 ldr r3, [pc, #332] ; (1230 <xTaskIncrementTick+0x15c>) 10e4: f8b3 4134 ldrh.w r4, [r3, #308] ; 0x134 10e8: b2a4 uxth r4, r4 10ea: 3401 adds r4, #1 10ec: b2a4 uxth r4, r4 10ee: f8a3 4134 strh.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 16 bit. 3. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_16_BITS. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 10e2: 4b53 ldr r3, [pc, #332] ; (1230 <xTaskIncrementTick+0x15c>) 10e4: f8b3 4134 ldrh.w r4, [r3, #308] ; 0x134 10e8: b2a4 uxth r4, r4 10ea: 3401 adds r4, #1 10ec: b2a4 uxth r4, r4 10ee: f8a3 4134 strh.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 16 bit. 4. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_32_BITS. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 109e: 4b50 ldr r3, [pc, #320] ; (11e0 <xTaskIncrementTick+0x150>) 10a0: f8d3 4134 ldr.w r4, [r3, #308] ; 0x134 10a4: 3401 adds r4, #1 10a6: f8c3 4134 str.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 32 bit. 5. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_64_BITS. ``` #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. ``` The testing was done for GCC/ARM_CM3 port which does not support 64 bit tick type. 6. Neither configUSE_16_BIT_TICKS nor configTICK_TYPE_WIDTH_IN_BITS defined. ``` #error Missing definition: One of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. ``` 7. Both configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS defined. ``` #error Only one of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. ``` Related issue - https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/628 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Feature/fixing clang gnu compiler warnings (#620) * Adding in ability to support a library for freertos_config and a custom freertos_kernel_port (#558) * Using single name definition for libraries everywhere. (#558) * Supporting backwards compatibility with FREERTOS_CONFIG_FILE_DIRECTORY (#571) * Removing compiler warnings for GNU and Clang. (#571) * Added in documentation on how to consume from a main project. Added default PORT selection for native POSIX and MINGW platforms. * Only adding freertos_config if it exists. Removing auto generation of it from a FREERTOS_CONFIG_FILE_DIRECTORY. * Fixing clang and gnu compiler warnings. * Adding in project information and how to compile for GNU/clang * Fixing compiler issue with unused variable - no need to declare variable. * Adding in compile warnings for linux builds that kernel is okay with using. * Fixing more extra-semi-stmt clang warnings. * Moving definition of hooks into header files if features are enabled. * Fixing formatting with uncrustify. * Fixing merge conflicts with main merge. * Fixing compiler errors due to merge issues and formatting. * Fixing Line feeds. * Adding 'portNORETURN' into portmacros.h. Other Updates based on PR request * Further clean-up of clang and clang-tidy issues. * Removing compiler specific pragmas from common c files. * Fixing missing lexicon entry and uncrustify formatting changes. * Resolving merge issue multiple defnitions of proto for prvIdleTask * Fixing formatting issues that are not covered by uncrustify. Use clang-tidy instead if you want this level of control. * More uncrustify formatting issues. * Fixing extra bracket in #if statement. --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * POSIX port fixes (#626) * Fix types in POSIX port Use TaskFunction_t and StackType_t as other ports do. * Fix portTICK_RATE_MICROSECONDS in POSIX port --------- Co-authored-by: Jacques GUILLOU <jacques.guillou.job@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Cortex-M35P: Add Cortex-M35P port (#631) * Cortex-M35P: Add Cortex-M35P port The Cortex-M35P support added to kernel. The port hasn't been validated yet with TF-M. Hence TF-M support is not included in this port. Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> * Add portNORETURN to the newly added portmacro.h Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> * Introduced Github Status Badge for Unit Tests (#634) * Introduced Github Status Badge for Unit Tests * Github status badge to point to latest run * Github status badge UT points to latest results * Fixed URL for Github Status badge --------- Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> * Remove C99 requirement from CMake file (#633) * Remove C99 requirement from CMake file The kernel source is C89 compliant and does not need C99. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Explicitly set C89 requirement for kernel Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add Thread Local Storage (TLS) support using Picolibc functions (#343) * Pass top of stack to configINIT_TLS_BLOCK Picolibc wants to allocate the per-task TLS block within the stack segment, so it will need to modify the top of stack value. Pass the pxTopOfStack variable to make this explicit. Signed-off-by: Keith Packard <keithpac@amazon.com> * Move newlib-specific definitions to separate file This reduces the clutter in FreeRTOS.h caused by having newlib-specific macros present there. Signed-off-by: Keith Packard <keithpac@amazon.com> * Make TLS code depend only on configUSE_C_RUNTIME_TLS_SUPPORT Remove reference to configUSE_NEWLIB_REENTRANT as that only works when using newlib. configUSE_C_RUNTIME_TLS_SUPPORT is always set when configUSE_NEWLIB_REENTRANT is set, so using both was redundant in that case. Signed-off-by: Keith Packard <keithpac@amazon.com> * portable-ARC: Adapt ARC support to use generalized TLS support With generalized thread local storage (TLS) support present in the core, the two ARC ports need to have the changes to the TCB mirrored to them. Signed-off-by: Keith Packard <keithpac@amazon.com> * Add Thread Local Storage (TLS) support using Picolibc functions This patch provides definitions of the general TLS support macros in terms of the Picolibc TLS support functions. Picolibc is normally configured to use TLS internally for all variables that are intended to be task-local, so these changes are necessary for picolibc to work correctly with FreeRTOS. The picolibc helper functions rely on elements within the linker script to arrange the TLS data in memory and define some symbols. Applications wanting to use this mechanism will need changes in their linker script when migrating to picolibc. Signed-off-by: Keith Packard <keithpac@amazon.com> --------- Signed-off-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Interrupt priority assert improvements for CM3/4/7 (#602) * Interrupt priority assert improvements for CM3/4/7 In the ARM_CM3, ARM_CM4, and ARM_CM7 ports, change the assertion that `configMAX_SYSCALL_INTERRUPT_PRIORITY` is nonzero to account for the number of priority bits implemented by the hardware. Change these ports to also use the lowest priority for PendSV and SysTick, ignoring `configKERNEL_INTERRUPT_PRIORITY`. * Remove not needed configKERNEL_INTERRUPT_PRIORITY define Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Introduced code coverage status badge (#635) * Introduced code coverage status badge * Trying to fix the URL checker issue * Fix URL check Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * added portPOINTER_SIZE_TYPE and SIZE_MAX definition to PIC24/dsPIC port (#636) * added portPOINTER_SIZE_TYPE definition to PIC24/dsPIC port * Added SIZE_MAX definition to PIC24/dsPIC33 * Fix TLS and stack alignment when using picolibc (#637) Both the TLS block and stack must be correctly aligned when using picolibc. The architecture stack alignment is represented by the portBYTE_ALIGNMENT_MASK and the TLS block alignment is provided by the Picolibc _tls_align() inline function for Picolibc version 1.8 and above. For older versions of Picolibc, we'll assume that the TLS block requires the same alignment as the stack. For downward growing stacks, this requires aligning the start of the TLS block to the maximum of the stack alignment and the TLS alignment. With this, both the TLS block and stack will now be correctly aligned. For upward growing stacks, the two areas must be aligned independently; the TLS block is aligned from the start of the stack, then the tls space is allocated, and then the stack is aligned above that. It's probably useful to know here that the linker ensures that variables within the TLS block are assigned offsets that match their alignment requirements. If the TLS block itself is correctly aligned, then everything within will also be. I have only tested the downward growing stack branch of this patch. Signed-off-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Enable building the GCC Cortex-R5 port without an FPU (#586) * Ensure configUSE_TASK_FPU_SUPPORT option is set correctly If one does enable the FPU of the Cortex-R5 processor, then the GCC compiler will define the macro __ARM_FP. This can be used to ensure, that the configUSE_TASK_FPU_SUPPORT is set accordingly. * Enable the implementation of vPortTaskUsesFPU only if configUSE_TASK_FPU_SUPPORT is set to 1 * Remove error case in pxPortInitialiseStack The case of configUSE_TASK_FPU_SUPPORT is 0 is now handled * Enable access to FPU registers only if FPU is enabled * Make minor formating changes * Format ARM Cortex-R5 port * Address review comments from @ChristosZosi * Minor code review suggestions Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Fix freertos_kernel cmake property, Posix Port (#640) * Fix freertos_kernel cmake property, Posix Port * Moves the `set_property()` call below the target definition in top level CMakeLists file * Corrects billion value from `ULL` suffix (not C90 compliant) to `UL` suffix with cast to uint64_t * Add blank line to CMakeLists.txt * Add missing FreeRTOS+ defines * Run kernel demos and unit tests for PR changes (#645) * Run kernel demos and unit tests for PR changes Kernel demos check builds multiple demos from FreeRTOS/FreeRTOS and unit tests check runs unit tests in FreeRTOS/FreeRTOS. Both of these checks currently use main branch of FreeRTOS-Kernel. This commits updates these checks to use the changes in the PR. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Do not specify PR SHA explicitly as that is default Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Remove explicit PR SHA from kernel checks Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add functions to get the buffers of statically created objects (#641) Added various ...GetStaticBuffer() functions to get the buffers of statically created objects. --------- Co-authored-by: Paul Bartell <pbartell@amazon.com> Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Cortex-M Assert when NVIC implements 8 PRIO bits (#639) * Cortex-M Assert when NVIC implements 8 PRIO bits * Fix CM3 ports * Fix ARM_CM3_MPU * Fix ARM CM3 * Fix ARM_CM4_MPU * Fix ARM_CM4 * Fix GCC ARM_CM7 * Fix IAR ARM ports * Uncrustify changes * Fix MikroC_ARM_CM4F port * Fix MikroC_ARM_CM4F port-(2) * Fix RVDS ARM ports * Revert changes for Tasking/ARM_CM4F port * Revert changes for Tasking/ARM_CM4F port-(2) * Update port.c Fix GCC/ARM_CM4F port * Update port.c * update GCC\ARM_CM4F port * update port.c * Assert to check configMAX_SYSCALL_INTERRUPT_PRIORITY is set to higher priority * Fix merge error: remove duplicate code * Fix typos --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-17-174.ec2.internal> * Remove C90 requirement from CMakeLists (#649) This is needed as it is breaking projects - https://forums.freertos.org/t/freertos-gcc-cmake/16984 We will re-evaluate and accordingly add this later. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Only add alignment padding when needed (#650) Heap 4 and Heap 5 add some padding to ensure that the allocated blocks are always aligned to portBYTE_ALIGNMENT bytes. The code until now was adding padding always even if the resulting block was already aligned. This commits updates the code to only add padding if the resulting block is not aligned. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * add a missing comma (#651) * fix conversion warning (#658) FreeRTOS-Kernel/portable/GCC/ARM_CM4F/port.c:399:41: error: conversion from 'uint32_t' {aka 'long unsigned int'} to 'uint8_t' {aka 'unsigned char'} may change value [-Werror=conversion] Signed-off-by: Vo Trung Chi <chi.votrung@vn.bosch.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Cervenka Dusan <cervenka@acrios.com> Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Keith Packard <keithpac@amazon.com> Signed-off-by: Vo Trung Chi <chi.votrung@vn.bosch.com> Co-authored-by: Archit Gupta <71798289+archigup@users.noreply.github.com> Co-authored-by: tcpluess <tpluess@ieee.org> Co-authored-by: pluess <pluess@faulhorn.mw.iap.unibe.ch> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Chris Copeland <chris@chrisnc.net> Co-authored-by: David J. Fiddes <35607151+davefiddes@users.noreply.github.com> Co-authored-by: Dusan Cervenka <cervenka@acrios.com> Co-authored-by: bbain <16752579+bbain@users.noreply.github.com> Co-authored-by: Ju1He1 <93189163+Ju1He1@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: phelter <paulheltera@gmail.com> Co-authored-by: jacky309 <jacques.guillou@gmail.com> Co-authored-by: Jacques GUILLOU <jacques.guillou.job@gmail.com> Co-authored-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com> Co-authored-by: Keith Packard <keithp@keithp.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Joseph Julicher <jjulicher@mac.com> Co-authored-by: Paul Bartell <pbartell@amazon.com> Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com> Co-authored-by: Kody Stribrny <89810515+kstribrnAmzn@users.noreply.github.com> Co-authored-by: Holden <holden-zenithaerotech.com> Co-authored-by: Darian <32921628+Dazza0@users.noreply.github.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-17-174.ec2.internal> Co-authored-by: Nicolas <nicolas.brunner@heig-vd.ch> Co-authored-by: Vo Trung Chi <chi.votrung@vn.bosch.com> * Smp dev merge main 20230410 (#74) * Fix array-bounds compiler warning on gcc11+ in list.h (#580) listGET_OWNER_OF_NEXT_ENTRY computes `( pxConstList )->pxIndex->pxNext` after verifying that `( pxConstList )->pxIndex` points to `xListEnd`, which due to being a MiniListItem_t, can be shorter than a ListItem_t. Thus, `( pxConstList )->pxIndex` is a `ListItem_t *` that extends past the end of the `List_t` whose `xListEnd` it points to. This is fixed by accessing `pxNext` through a `MiniListItem_t` instead. * move the prototype for vApplicationIdleHook to task.h. (#600) Co-authored-by: pluess <pluess@faulhorn.mw.iap.unibe.ch> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update equal priority task preemption (#603) * vTaskResume and vTaskPrioritySet don't preempt equal priority task * Update vTaskResumeAll not to preempt task with equal priority * Fix in xTaskResumeFromISR * Update FreeRTOS/FreeRTOS build checks (#613) This is needed to be compatible with the refactoring done in this PR - https://github.com/FreeRTOS/FreeRTOS/pull/889 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add ulTaskGetRunTimeCounter and ulTaskGetRunTimePercent (#611) Allow ulTaskGetIdleRunTimeCounter and ulTaskGetIdleRunTimePercent to be used whenever configGENERATE_RUN_TIME_STATS is enabled, as this is the only requirement for these functions to work. * Fix some CMake documentation typos (#616) The quick start instructions for CMake mention the "master" git branch which has been replaced by "main" in the current repo. The main CMakeLists.txt documents how to integrate a custom port. Fix a typo in the suggested CMake code. * Added support of 64bit events. (#597) * Added support of 64bit even Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Added missing brackets Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Made proper name for tick macro. Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Improved macro evaluation Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Fixed missed port files + documentation Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Changes made on PR Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Fix macro definition. Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Formatted code with uncrustify Signed-off-by: Cervenka Dusan <cervenka@acrios.com> --------- Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Introduce portMEMORY_BARRIER for Microblaze port. (#621) The introduction of `portMEMORY_BARRIER` will ensure the places in the kernel use a barrier will work. For example, `xTaskResumeAll` has a memory barrier to ensure its correctness when compiled with optimization enabled. Without the barrier `xTaskResumeAll` can fail (e.g. start reading and writing to address 0 and/or infinite looping) when `xPendingReadyList` contains more than one task to restore. In `xTaskResumeAll` the compiler chooses to cache the `pxTCB` the first time through the loop for use in every subsequent loop. This is incorrect as the removal of `pxTCB->xEventListItem` will actually change the value of `pxTCB` if it was read again at the top of the loop. The barrier forces the compiler to read `pxTCB` again at the top of the loop. The compiler is operating correctly. The removal `pxTCB->xEventListItem` executes on a `List_t *` and `ListItem_t *`. This means that the compiler can assume that any `MiniListItem_t` values are unchanged by the loop (i.e. "strict-aliasing"). This allows the compiler to cache `pxTCB` as it is obtained via a `MiniListItem_t`. This is incorrect in this case because it is possible for a `ListItem_t *` to actually alias a `MiniListItem_t`. This is technically a "violation of aliasing rules" so we use the the barrier to disable the strict-aliasing optimization in this loop. * Do not call exit() on MSVC Port when calling vPortEndScheduler (#624) * make port exitable * correctly set xPortRunning to False * add suggestions from Review Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * add suggestions from Review Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update PR template to include checkbox for Unit Test related changes (#627) * Fix build failure introduced in PR #597 (#629) The PR #597 introduced a new config option configTICK_TYPE_WIDTH_IN_BITS which can be defined to one of the following: * TICK_TYPE_WIDTH_16_BITS - Tick type is 16 bit wide. * TICK_TYPE_WIDTH_32_BITS - Tick type is 32 bit wide. * TICK_TYPE_WIDTH_64_BITS - Tick type is 64 bit wide. Earlier we supported 16 and 32 bit width for tick type which was controlled using the config option configUSE_16_BIT_TICKS. The PR tried to maintain backward compatibility by honoring configUSE_16_BIT_TICKS. The backward compatibility did not work as expected though, as the macro configTICK_TYPE_WIDTH_IN_BITS was used before it was defined. This PR addresses it by ensuring that the macro configTICK_TYPE_WIDTH_IN_BITS is defined before it is used. Testing 1. configUSE_16_BIT_TICKS is defined to 0. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 109e: 4b50 ldr r3, [pc, #320] ; (11e0 <xTaskIncrementTick+0x150>) 10a0: f8d3 4134 ldr.w r4, [r3, #308] ; 0x134 10a4: 3401 adds r4, #1 10a6: f8c3 4134 str.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 32 bit. 2. configUSE_16_BIT_TICKS is defined to 1. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 10e2: 4b53 ldr r3, [pc, #332] ; (1230 <xTaskIncrementTick+0x15c>) 10e4: f8b3 4134 ldrh.w r4, [r3, #308] ; 0x134 10e8: b2a4 uxth r4, r4 10ea: 3401 adds r4, #1 10ec: b2a4 uxth r4, r4 10ee: f8a3 4134 strh.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 16 bit. 3. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_16_BITS. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 10e2: 4b53 ldr r3, [pc, #332] ; (1230 <xTaskIncrementTick+0x15c>) 10e4: f8b3 4134 ldrh.w r4, [r3, #308] ; 0x134 10e8: b2a4 uxth r4, r4 10ea: 3401 adds r4, #1 10ec: b2a4 uxth r4, r4 10ee: f8a3 4134 strh.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 16 bit. 4. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_32_BITS. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 109e: 4b50 ldr r3, [pc, #320] ; (11e0 <xTaskIncrementTick+0x150>) 10a0: f8d3 4134 ldr.w r4, [r3, #308] ; 0x134 10a4: 3401 adds r4, #1 10a6: f8c3 4134 str.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 32 bit. 5. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_64_BITS. ``` #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. ``` The testing was done for GCC/ARM_CM3 port which does not support 64 bit tick type. 6. Neither configUSE_16_BIT_TICKS nor configTICK_TYPE_WIDTH_IN_BITS defined. ``` #error Missing definition: One of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. ``` 7. Both configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS defined. ``` #error Only one of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. ``` Related issue - https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/628 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Feature/fixing clang gnu compiler warnings (#620) * Adding in ability to support a library for freertos_config and a custom freertos_kernel_port (#558) * Using single name definition for libraries everywhere. (#558) * Supporting backwards compatibility with FREERTOS_CONFIG_FILE_DIRECTORY (#571) * Removing compiler warnings for GNU and Clang. (#571) * Added in documentation on how to consume from a main project. Added default PORT selection for native POSIX and MINGW platforms. * Only adding freertos_config if it exists. Removing auto generation of it from a FREERTOS_CONFIG_FILE_DIRECTORY. * Fixing clang and gnu compiler warnings. * Adding in project information and how to compile for GNU/clang * Fixing compiler issue with unused variable - no need to declare variable. * Adding in compile warnings for linux builds that kernel is okay with using. * Fixing more extra-semi-stmt clang warnings. * Moving definition of hooks into header files if features are enabled. * Fixing formatting with uncrustify. * Fixing merge conflicts with main merge. * Fixing compiler errors due to merge issues and formatting. * Fixing Line feeds. * Adding 'portNORETURN' into portmacros.h. Other Updates based on PR request * Further clean-up of clang and clang-tidy issues. * Removing compiler specific pragmas from common c files. * Fixing missing lexicon entry and uncrustify formatting changes. * Resolving merge issue multiple defnitions of proto for prvIdleTask * Fixing formatting issues that are not covered by uncrustify. Use clang-tidy instead if you want this level of control. * More uncrustify formatting issues. * Fixing extra bracket in #if statement. --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * POSIX port fixes (#626) * Fix types in POSIX port Use TaskFunction_t and StackType_t as other ports do. * Fix portTICK_RATE_MICROSECONDS in POSIX port --------- Co-authored-by: Jacques GUILLOU <jacques.guillou.job@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Cortex-M35P: Add Cortex-M35P port (#631) * Cortex-M35P: Add Cortex-M35P port The Cortex-M35P support added to kernel. The port hasn't been validated yet with TF-M. Hence TF-M support is not included in this port. Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> * Add portNORETURN to the newly added portmacro.h Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> * Introduced Github Status Badge for Unit Tests (#634) * Introduced Github Status Badge for Unit Tests * Github status badge to point to latest run * Github status badge UT points to latest results * Fixed URL for Github Status badge --------- Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> * Remove C99 requirement from CMake file (#633) * Remove C99 requirement from CMake file The kernel source is C89 compliant and does not need C99. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Explicitly set C89 requirement for kernel Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add Thread Local Storage (TLS) support using Picolibc functions (#343) * Pass top of stack to configINIT_TLS_BLOCK Picolibc wants to allocate the per-task TLS block within the stack segment, so it will need to modify the top of stack value. Pass the pxTopOfStack variable to make this explicit. Signed-off-by: Keith Packard <keithpac@amazon.com> * Move newlib-specific definitions to separate file This reduces the clutter in FreeRTOS.h caused by having newlib-specific macros present there. Signed-off-by: Keith Packard <keithpac@amazon.com> * Make TLS code depend only on configUSE_C_RUNTIME_TLS_SUPPORT Remove reference to configUSE_NEWLIB_REENTRANT as that only works when using newlib. configUSE_C_RUNTIME_TLS_SUPPORT is always set when configUSE_NEWLIB_REENTRANT is set, so using both was redundant in that case. Signed-off-by: Keith Packard <keithpac@amazon.com> * portable-ARC: Adapt ARC support to use generalized TLS support With generalized thread local storage (TLS) support present in the core, the two ARC ports need to have the changes to the TCB mirrored to them. Signed-off-by: Keith Packard <keithpac@amazon.com> * Add Thread Local Storage (TLS) support using Picolibc functions This patch provides definitions of the general TLS support macros in terms of the Picolibc TLS support functions. Picolibc is normally configured to use TLS internally for all variables that are intended to be task-local, so these changes are necessary for picolibc to work correctly with FreeRTOS. The picolibc helper functions rely on elements within the linker script to arrange the TLS data in memory and define some symbols. Applications wanting to use this mechanism will need changes in their linker script when migrating to picolibc. Signed-off-by: Keith Packard <keithpac@amazon.com> --------- Signed-off-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Interrupt priority assert improvements for CM3/4/7 (#602) * Interrupt priority assert improvements for CM3/4/7 In the ARM_CM3, ARM_CM4, and ARM_CM7 ports, change the assertion that `configMAX_SYSCALL_INTERRUPT_PRIORITY` is nonzero to account for the number of priority bits implemented by the hardware. Change these ports to also use the lowest priority for PendSV and SysTick, ignoring `configKERNEL_INTERRUPT_PRIORITY`. * Remove not needed configKERNEL_INTERRUPT_PRIORITY define Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Introduced code coverage status badge (#635) * Introduced code coverage status badge * Trying to fix the URL checker issue * Fix URL check Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * added portPOINTER_SIZE_TYPE and SIZE_MAX definition to PIC24/dsPIC port (#636) * added portPOINTER_SIZE_TYPE definition to PIC24/dsPIC port * Added SIZE_MAX definition to PIC24/dsPIC33 * Fix TLS and stack alignment when using picolibc (#637) Both the TLS block and stack must be correctly aligned when using picolibc. The architecture stack alignment is represented by the portBYTE_ALIGNMENT_MASK and the TLS block alignment is provided by the Picolibc _tls_align() inline function for Picolibc version 1.8 and above. For older versions of Picolibc, we'll assume that the TLS block requires the same alignment as the stack. For downward growing stacks, this requires aligning the start of the TLS block to the maximum of the stack alignment and the TLS alignment. With this, both the TLS block and stack will now be correctly aligned. For upward growing stacks, the two areas must be aligned independently; the TLS block is aligned from the start of the stack, then the tls space is allocated, and then the stack is aligned above that. It's probably useful to know here that the linker ensures that variables within the TLS block are assigned offsets that match their alignment requirements. If the TLS block itself is correctly aligned, then everything within will also be. I have only tested the downward growing stack branch of this patch. Signed-off-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Enable building the GCC Cortex-R5 port without an FPU (#586) * Ensure configUSE_TASK_FPU_SUPPORT option is set correctly If one does enable the FPU of the Cortex-R5 processor, then the GCC compiler will define the macro __ARM_FP. This can be used to ensure, that the configUSE_TASK_FPU_SUPPORT is set accordingly. * Enable the implementation of vPortTaskUsesFPU only if configUSE_TASK_FPU_SUPPORT is set to 1 * Remove error case in pxPortInitialiseStack The case of configUSE_TASK_FPU_SUPPORT is 0 is now handled * Enable access to FPU registers only if FPU is enabled * Make minor formating changes * Format ARM Cortex-R5 port * Address review comments from @ChristosZosi * Minor code review suggestions Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Fix freertos_kernel cmake property, Posix Port (#640) * Fix freertos_kernel cmake property, Posix Port * Moves the `set_property()` call below the target definition in top level CMakeLists file * Corrects billion value from `ULL` suffix (not C90 compliant) to `UL` suffix with cast to uint64_t * Add blank line to CMakeLists.txt * Add missing FreeRTOS+ defines * Run kernel demos and unit tests for PR changes (#645) * Run kernel demos and unit tests for PR changes Kernel demos check builds multiple demos from FreeRTOS/FreeRTOS and unit tests check runs unit tests in FreeRTOS/FreeRTOS. Both of these checks currently use main branch of FreeRTOS-Kernel. This commits updates these checks to use the changes in the PR. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Do not specify PR SHA explicitly as that is default Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Remove explicit PR SHA from kernel checks Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add functions to get the buffers of statically created objects (#641) Added various ...GetStaticBuffer() functions to get the buffers of statically created objects. --------- Co-authored-by: Paul Bartell <pbartell@amazon.com> Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Cortex-M Assert when NVIC implements 8 PRIO bits (#639) * Cortex-M Assert when NVIC implements 8 PRIO bits * Fix CM3 ports * Fix ARM_CM3_MPU * Fix ARM CM3 * Fix ARM_CM4_MPU * Fix ARM_CM4 * Fix GCC ARM_CM7 * Fix IAR ARM ports * Uncrustify changes * Fix MikroC_ARM_CM4F port * Fix MikroC_ARM_CM4F port-(2) * Fix RVDS ARM ports * Revert changes for Tasking/ARM_CM4F port * Revert changes for Tasking/ARM_CM4F port-(2) * Update port.c Fix GCC/ARM_CM4F port * Update port.c * update GCC\ARM_CM4F port * update port.c * Assert to check configMAX_SYSCALL_INTERRUPT_PRIORITY is set to higher priority * Fix merge error: remove duplicate code * Fix typos --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-17-174.ec2.internal> * Remove C90 requirement from CMakeLists (#649) This is needed as it is breaking projects - https://forums.freertos.org/t/freertos-gcc-cmake/16984 We will re-evaluate and accordingly add this later. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Only add alignment padding when needed (#650) Heap 4 and Heap 5 add some padding to ensure that the allocated blocks are always aligned to portBYTE_ALIGNMENT bytes. The code until now was adding padding always even if the resulting block was already aligned. This commits updates the code to only add padding if the resulting block is not aligned. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * add a missing comma (#651) * fix conversion warning (#658) FreeRTOS-Kernel/portable/GCC/ARM_CM4F/port.c:399:41: error: conversion from 'uint32_t' {aka 'long unsigned int'} to 'uint8_t' {aka 'unsigned char'} may change value [-Werror=conversion] Signed-off-by: Vo Trung Chi <chi.votrung@vn.bosch.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Cervenka Dusan <cervenka@acrios.com> Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Keith Packard <keithpac@amazon.com> Signed-off-by: Vo Trung Chi <chi.votrung@vn.bosch.com> Co-authored-by: Archit Gupta <71798289+archigup@users.noreply.github.com> Co-authored-by: tcpluess <tpluess@ieee.org> Co-authored-by: pluess <pluess@faulhorn.mw.iap.unibe.ch> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Chris Copeland <chris@chrisnc.net> Co-authored-by: David J. Fiddes <35607151+davefiddes@users.noreply.github.com> Co-authored-by: Dusan Cervenka <cervenka@acrios.com> Co-authored-by: bbain <16752579+bbain@users.noreply.github.com> Co-authored-by: Ju1He1 <93189163+Ju1He1@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: phelter <paulheltera@gmail.com> Co-authored-by: jacky309 <jacques.guillou@gmail.com> Co-authored-by: Jacques GUILLOU <jacques.guillou.job@gmail.com> Co-authored-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com> Co-authored-by: Keith Packard <keithp@keithp.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Joseph Julicher <jjulicher@mac.com> Co-authored-by: Paul Bartell <pbartell@amazon.com> Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com> Co-authored-by: Kody Stribrny <89810515+kstribrnAmzn@users.noreply.github.com> Co-authored-by: Holden <holden-zenithaerotech.com> Co-authored-by: Darian <32921628+Dazza0@users.noreply.github.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-17-174.ec2.internal> Co-authored-by: Nicolas <nicolas.brunner@heig-vd.ch> Co-authored-by: Vo Trung Chi <chi.votrung@vn.bosch.com> * Not yield for running task in prvYieldForTask (#72) * Raise priority of a running task should not alter other cores * Remove unreachable code in prvSelectHighestPriorityTask (#70) * Remove unreachable code in prvSelectHighestPriorityTask * Remove unreachable assert condition * Update comment * Move static idle task memory to global scope (#75) * Update XMOS AICORE conflict (#77) * Define portBASE_TYPE in XMOS AICORE porting * Update enter critical from ISR API * Fix run time stats for SMP (#76) * Update get idle tasks stats * Fix get task stats * Fix missing configNUM_CORES * Update the uxSchedulerSuspended after prvCheckForRunStateChange (#62) * Update the uxSchedulerSuspended after the prvCheckForRunStateChange to prevent race condition in fromISR APIs * Fix SMP dev branch CI errors (#79) * Fix uncrustify * Update lexicon * Remove tailing space * Ignore XMOS AICORE header check * Fix ulTotalRunTime and ulTaskSwitchedInTime (#80) * SMP has multiple ulTotalRunTime and ulTaskSwitchedInTime * Smp dev compelete merge main 20230424 (#78) * Fix array-bounds compiler warning on gcc11+ in list.h (#580) listGET_OWNER_OF_NEXT_ENTRY computes `( pxConstList )->pxIndex->pxNext` after verifying that `( pxConstList )->pxIndex` points to `xListEnd`, which due to being a MiniListItem_t, can be shorter than a ListItem_t. Thus, `( pxConstList )->pxIndex` is a `ListItem_t *` that extends past the end of the `List_t` whose `xListEnd` it points to. This is fixed by accessing `pxNext` through a `MiniListItem_t` instead. * move the prototype for vApplicationIdleHook to task.h. (#600) Co-authored-by: pluess <pluess@faulhorn.mw.iap.unibe.ch> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update equal priority task preemption (#603) * vTaskResume and vTaskPrioritySet don't preempt equal priority task * Update vTaskResumeAll not to preempt task with equal priority * Fix in xTaskResumeFromISR * Update FreeRTOS/FreeRTOS build checks (#613) This is needed to be compatible with the refactoring done in this PR - https://github.com/FreeRTOS/FreeRTOS/pull/889 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add ulTaskGetRunTimeCounter and ulTaskGetRunTimePercent (#611) Allow ulTaskGetIdleRunTimeCounter and ulTaskGetIdleRunTimePercent to be used whenever configGENERATE_RUN_TIME_STATS is enabled, as this is the only requirement for these functions to work. * Fix some CMake documentation typos (#616) The quick start instructions for CMake mention the "master" git branch which has been replaced by "main" in the current repo. The main CMakeLists.txt documents how to integrate a custom port. Fix a typo in the suggested CMake code. * Added support of 64bit events. (#597) * Added support of 64bit even Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Added missing brackets Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Made proper name for tick macro. Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Improved macro evaluation Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Fixed missed port files + documentation Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Changes made on PR Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Fix macro definition. Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Formatted code with uncrustify Signed-off-by: Cervenka Dusan <cervenka@acrios.com> --------- Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Introduce portMEMORY_BARRIER for Microblaze port. (#621) The introduction of `portMEMORY_BARRIER` will ensure the places in the kernel use a barrier will work. For example, `xTaskResumeAll` has a memory barrier to ensure its correctness when compiled with optimization enabled. Without the barrier `xTaskResumeAll` can fail (e.g. start reading and writing to address 0 and/or infinite looping) when `xPendingReadyList` contains more than one task to restore. In `xTaskResumeAll` the compiler chooses to cache the `pxTCB` the first time through the loop for use in every subsequent loop. This is incorrect as the removal of `pxTCB->xEventListItem` will actually change the value of `pxTCB` if it was read again at the top of the loop. The barrier forces the compiler to read `pxTCB` again at the top of the loop. The compiler is operating correctly. The removal `pxTCB->xEventListItem` executes on a `List_t *` and `ListItem_t *`. This means that the compiler can assume that any `MiniListItem_t` values are unchanged by the loop (i.e. "strict-aliasing"). This allows the compiler to cache `pxTCB` as it is obtained via a `MiniListItem_t`. This is incorrect in this case because it is possible for a `ListItem_t *` to actually alias a `MiniListItem_t`. This is technically a "violation of aliasing rules" so we use the the barrier to disable the strict-aliasing optimization in this loop. * Do not call exit() on MSVC Port when calling vPortEndScheduler (#624) * make port exitable * correctly set xPortRunning to False * add suggestions from Review Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * add suggestions from Review Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update PR template to include checkbox for Unit Test related changes (#627) * Fix build failure introduced in PR #597 (#629) The PR #597 introduced a new config option configTICK_TYPE_WIDTH_IN_BITS which can be defined to one of the following: * TICK_TYPE_WIDTH_16_BITS - Tick type is 16 bit wide. * TICK_TYPE_WIDTH_32_BITS - Tick type is 32 bit wide. * TICK_TYPE_WIDTH_64_BITS - Tick type is 64 bit wide. Earlier we supported 16 and 32 bit width for tick type which was controlled using the config option configUSE_16_BIT_TICKS. The PR tried to maintain backward compatibility by honoring configUSE_16_BIT_TICKS. The backward compatibility did not work as expected though, as the macro configTICK_TYPE_WIDTH_IN_BITS was used before it was defined. This PR addresses it by ensuring that the macro configTICK_TYPE_WIDTH_IN_BITS is defined before it is used. Testing 1. configUSE_16_BIT_TICKS is defined to 0. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 109e: 4b50 ldr r3, [pc, #320] ; (11e0 <xTaskIncrementTick+0x150>) 10a0: f8d3 4134 ldr.w r4, [r3, #308] ; 0x134 10a4: 3401 adds r4, #1 10a6: f8c3 4134 str.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 32 bit. 2. configUSE_16_BIT_TICKS is defined to 1. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 10e2: 4b53 ldr r3, [pc, #332] ; (1230 <xTaskIncrementTick+0x15c>) 10e4: f8b3 4134 ldrh.w r4, [r3, #308] ; 0x134 10e8: b2a4 uxth r4, r4 10ea: 3401 adds r4, #1 10ec: b2a4 uxth r4, r4 10ee: f8a3 4134 strh.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 16 bit. 3. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_16_BITS. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 10e2: 4b53 ldr r3, [pc, #332] ; (1230 <xTaskIncrementTick+0x15c>) 10e4: f8b3 4134 ldrh.w r4, [r3, #308] ; 0x134 10e8: b2a4 uxth r4, r4 10ea: 3401 adds r4, #1 10ec: b2a4 uxth r4, r4 10ee: f8a3 4134 strh.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 16 bit. 4. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_32_BITS. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 109e: 4b50 ldr r3, [pc, #320] ; (11e0 <xTaskIncrementTick+0x150>) 10a0: f8d3 4134 ldr.w r4, [r3, #308] ; 0x134 10a4: 3401 adds r4, #1 10a6: f8c3 4134 str.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 32 bit. 5. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_64_BITS. ``` #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. ``` The testing was done for GCC/ARM_CM3 port which does not support 64 bit tick type. 6. Neither configUSE_16_BIT_TICKS nor configTICK_TYPE_WIDTH_IN_BITS defined. ``` #error Missing definition: One of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. ``` 7. Both configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS defined. ``` #error Only one of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. ``` Related issue - https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/628 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Feature/fixing clang gnu compiler warnings (#620) * Adding in ability to support a library for freertos_config and a custom freertos_kernel_port (#558) * Using single name definition for libraries everywhere. (#558) * Supporting backwards compatibility with FREERTOS_CONFIG_FILE_DIRECTORY (#571) * Removing compiler warnings for GNU and Clang. (#571) * Added in documentation on how to consume from a main project. Added default PORT selection for native POSIX and MINGW platforms. * Only adding freertos_config if it exists. Removing auto generation of it from a FREERTOS_CONFIG_FILE_DIRECTORY. * Fixing clang and gnu compiler warnings. * Adding in project information and how to compile for GNU/clang * Fixing compiler issue with unused variable - no need to declare variable. * Adding in compile warnings for linux builds that kernel is okay with using. * Fixing more extra-semi-stmt clang warnings. * Moving definition of hooks into header files if features are enabled. * Fixing formatting with uncrustify. * Fixing merge conflicts with main merge. * Fixing compiler errors due to merge issues and formatting. * Fixing Line feeds. * Adding 'portNORETURN' into portmacros.h. Other Updates based on PR request * Further clean-up of clang and clang-tidy issues. * Removing compiler specific pragmas from common c files. * Fixing missing lexicon entry and uncrustify formatting changes. * Resolving merge issue multiple defnitions of proto for prvIdleTask * Fixing formatting issues that are not covered by uncrustify. Use clang-tidy instead if you want this level of control. * More uncrustify formatting issues. * Fixing extra bracket in #if statement. --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * POSIX port fixes (#626) * Fix types in POSIX port Use TaskFunction_t and StackType_t as other ports do. * Fix portTICK_RATE_MICROSECONDS in POSIX port --------- Co-authored-by: Jacques GUILLOU <jacques.guillou.job@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Cortex-M35P: Add Cortex-M35P port (#631) * Cortex-M35P: Add Cortex-M35P port The Cortex-M35P support added to kernel. The port hasn't been validated yet with TF-M. Hence TF-M support is not included in this port. Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> * Add portNORETURN to the newly added portmacro.h Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> * Introduced Github Status Badge for Unit Tests (#634) * Introduced Github Status Badge for Unit Tests * Github status badge to point to latest run * Github status badge UT points to latest results * Fixed URL for Github Status badge --------- Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> * Remove C99 requirement from CMake file (#633) * Remove C99 requirement from CMake file The kernel source is C89 compliant and does not need C99. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Explicitly set C89 requirement for kernel Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add Thread Local Storage (TLS) support using Picolibc functions (#343) * Pass top of stack to configINIT_TLS_BLOCK Picolibc wants to allocate the per-task TLS block within the stack segment, so it will need to modify the top of stack value. Pass the pxTopOfStack variable to make this explicit. Signed-off-by: Keith Packard <keithpac@amazon.com> * Move newlib-specific definitions to separate file This reduces the clutter in FreeRTOS.h caused by having newlib-specific macros present there. Signed-off-by: Keith Packard <keithpac@amazon.com> * Make TLS code depend only on configUSE_C_RUNTIME_TLS_SUPPORT Remove reference to configUSE_NEWLIB_REENTRANT as that only works when using newlib. configUSE_C_RUNTIME_TLS_SUPPORT is always set when configUSE_NEWLIB_REENTRANT is set, so using both was redundant in that case. Signed-off-by: Keith Packard <keithpac@amazon.com> * portable-ARC: Adapt ARC support to use generalized TLS support With generalized thread local storage (TLS) support present in the core, the two ARC ports need to have the changes to the TCB mirrored to them. Signed-off-by: Keith Packard <keithpac@amazon.com> * Add Thread Local Storage (TLS) support using Picolibc functions This patch provides definitions of the general TLS support macros in terms of the Picolibc TLS support functions. Picolibc is normally configured to use TLS internally for all variables that are intended to be task-local, so these changes are necessary for picolibc to work correctly with FreeRTOS. The picolibc helper functions rely on elements within the linker script to arrange the TLS data in memory and define some symbols. Applications wanting to use this mechanism will need changes in their linker script when migrating to picolibc. Signed-off-by: Keith Packard <keithpac@amazon.com> --------- Signed-off-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Interrupt priority assert improvements for CM3/4/7 (#602) * Interrupt priority assert improvements for CM3/4/7 In the ARM_CM3, ARM_CM4, and ARM_CM7 ports, change the assertion that `configMAX_SYSCALL_INTERRUPT_PRIORITY` is nonzero to account for the number of priority bits implemented by the hardware. Change these ports to also use the lowest priority for PendSV and SysTick, ignoring `configKERNEL_INTERRUPT_PRIORITY`. * Remove not needed configKERNEL_INTERRUPT_PRIORITY define Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Introduced code coverage status badge (#635) * Introduced code coverage status badge * Trying to fix the URL checker issue * Fix URL check Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * added portPOINTER_SIZE_TYPE and SIZE_MAX definition to PIC24/dsPIC port (#636) * added portPOINTER_SIZE_TYPE definition to PIC24/dsPIC port * Added SIZE_MAX definition to PIC24/dsPIC33 * Fix TLS and stack alignment when using picolibc (#637) Both the TLS block and stack must be correctly aligned when using picolibc. The architecture stack alignment is represented by the portBYTE_ALIGNMENT_MASK and the TLS block alignment is provided by the Picolibc _tls_align() inline function for Picolibc version 1.8 and above. For older versions of Picolibc, we'll assume that the TLS block requires the same alignment as the stack. For downward growing stacks, this requires aligning the start of the TLS block to the maximum of the stack alignment and the TLS alignment. With this, both the TLS block and stack will now be correctly aligned. For upward growing stacks, the two areas must be aligned independently; the TLS block is aligned from the start of the stack, then the tls space is allocated, and then the stack is aligned above that. It's probably useful to know here that the linker ensures that variables within the TLS block are assigned offsets that match their alignment requirements. If the TLS block itself is correctly aligned, then everything within will also be. I have only tested the downward growing stack branch of this patch. Signed-off-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Enable building the GCC Cortex-R5 port without an FPU (#586) * Ensure configUSE_TASK_FPU_SUPPORT option is set correctly If one does enable the FPU of the Cortex-R5 processor, then the GCC compiler will define the macro __ARM_FP. This can be used to ensure, that the configUSE_TASK_FPU_SUPPORT is set accordingly. * Enable the implementation of vPortTaskUsesFPU only if configUSE_TASK_FPU_SUPPORT is set to 1 * Remove error case in pxPortInitialiseStack The case of configUSE_TASK_FPU_SUPPORT is 0 is now handled * Enable access to FPU registers only if FPU is enabled * Make minor formating changes * Format ARM Cortex-R5 port * Address review comments from @ChristosZosi * Minor code review suggestions Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Fix freertos_kernel cmake property, Posix Port (#640) * Fix freertos_kernel cmake property, Posix Port * Moves the `set_property()` call below the target definition in top level CMakeLists file * Corrects billion value from `ULL` suffix (not C90 compliant) to `UL` suffix with cast to uint64_t * Add blank line to CMakeLists.txt * Add missing FreeRTOS+ defines * Run kernel demos and unit tests for PR changes (#645) * Run kernel demos and unit tests for PR changes Kernel demos check builds multiple demos from FreeRTOS/FreeRTOS and unit tests check runs unit tests in FreeRTOS/FreeRTOS. Both of these checks currently use main branch of FreeRTOS-Kernel. This commits updates these checks to use the changes in the PR. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Do not specify PR SHA explicitly as that is default Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Remove explicit PR SHA from kernel checks Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add functions to get the buffers of statically created objects (#641) Added various ...GetStaticBuffer() functions to get the buffers of statically created objects. --------- Co-authored-by: Paul Bartell <pbartell@amazon.com> Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Cortex-M Assert when NVIC implements 8 PRIO bits (#639) * Cortex-M Assert when NVIC implements 8 PRIO bits * Fix CM3 ports * Fix ARM_CM3_MPU * Fix ARM CM3 * Fix ARM_CM4_MPU * Fix ARM_CM4 * Fix GCC ARM_CM7 * Fix IAR ARM ports * Uncrustify changes * Fix MikroC_ARM_CM4F port * Fix MikroC_ARM_CM4F port-(2) * Fix RVDS ARM ports * Revert changes for Tasking/ARM_CM4F port * Revert changes for Tasking/ARM_CM4F port-(2) * Update port.c Fix GCC/ARM_CM4F port * Update port.c * update GCC\ARM_CM4F port * update port.c * Assert to check configMAX_SYSCALL_INTERRUPT_PRIORITY is set to higher priority * Fix merge error: remove duplicate code * Fix typos --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-17-174.ec2.internal> * Remove C90 requirement from CMakeLists (#649) This is needed as it is breaking projects - https://forums.freertos.org/t/freertos-gcc-cmake/16984 We will re-evaluate and accordingly add this later. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Only add alignment padding when needed (#650) Heap 4 and Heap 5 add some padding to ensure that the allocated blocks are always aligned to portBYTE_ALIGNMENT bytes. The code until now was adding padding always even if the resulting block was already aligned. This commits updates the code to only add padding if the resulting block is not aligned. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * add a missing comma (#651) * fix conversion warning (#658) FreeRTOS-Kernel/portable/GCC/ARM_CM4F/port.c:399:41: error: conversion from 'uint32_t' {aka 'long unsigned int'} to 'uint8_t' {aka 'unsigned char'} may change value [-Werror=conversion] Signed-off-by: Vo Trung Chi <chi.votrung@vn.bosch.com> * ARMv7M: Adjust implemented priority bit assertions (#665) Adjust assertions related to the CMSIS __NVIC_PRIO_BITS and FreeRTOS configPRIO_BITS configuration macros such that these macros specify the minimum number of implemented priority bits supported by a config build rather than the exact number of implemented priority bits. Related to Qemu issue #1122 * Format portmacro.h in arm CM0 ports * portable/ARM_CM0: Add xPortIsInsideInterrupt Add missing xPortIsInsideInterrupt function to Cortex-M0 port. --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Cervenka Dusan <cervenka@acrios.com> Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Keith Packard <keithpac@amazon.com> Signed-off-by: Vo Trung Chi <chi.votrung@vn.bosch.com> Co-authored-by: Archit Gupta <71798289+archigup@users.noreply.github.com> Co-authored-by: tcpluess <tpluess@ieee.org> Co-authored-by: pluess <pluess@faulhorn.mw.iap.unibe.ch> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Chris Copeland <chris@chrisnc.net> Co-authored-by: David J. Fiddes <35607151+davefiddes@users.noreply.github.com> Co-authored-by: Dusan Cervenka <cervenka@acrios.com> Co-authored-by: bbain <16752579+bbain@users.noreply.github.com> Co-authored-by: Ju1He1 <93189163+Ju1He1@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: phelter <paulheltera@gmail.com> Co-authored-by: jacky309 <jacques.guillou@gmail.com> Co-authored-by: Jacques GUILLOU <jacques.guillou.job@gmail.com> Co-authored-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com> Co-authored-by: Keith Packard <keithp@keithp.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Joseph Julicher <jjulicher@mac.com> Co-authored-by: Paul Bartell <pbartell@amazon.com> Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com> Co-authored-by: Kody Stribrny <89810515+kstribrnAmzn@users.noreply.github.com> Co-authored-by: Holden <holden-zenithaerotech.com> Co-authored-by: Darian <32921628+Dazza0@users.noreply.github.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-17-174.ec2.internal> Co-authored-by: Nicolas <nicolas.brunner@heig-vd.ch> Co-authored-by: Vo Trung Chi <chi.votrung@vn.bosch.com> * Update coverity violation for SMP (#81) * Update coverity violation for SMP ( code surrounded by configNUMBER_OF_CORES > 1 ). * Single core and common code are still scanned by lint tool. * Smp dev merge main 0527 (#82) * Fix array-bounds compiler warning on gcc11+ in list.h (#580) listGET_OWNER_OF_NEXT_ENTRY computes `( pxConstList )->pxIndex->pxNext` after verifying that `( pxConstList )->pxIndex` points to `xListEnd`, which due to being a MiniListItem_t, can be shorter than a ListItem_t. Thus, `( pxConstList )->pxIndex` is a `ListItem_t *` that extends past the end of the `List_t` whose `xListEnd` it points to. This is fixed by accessing `pxNext` through a `MiniListItem_t` instead. * move the prototype for vApplicationIdleHook to task.h. (#600) Co-authored-by: pluess <pluess@faulhorn.mw.iap.unibe.ch> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update equal priority task preemption (#603) * vTaskResume and vTaskPrioritySet don't preempt equal priority task * Update vTaskResumeAll not to preempt task with equal priority * Fix in xTaskResumeFromISR * Update FreeRTOS/FreeRTOS build checks (#613) This is needed to be compatible with the refactoring done in this PR - https://github.com/FreeRTOS/FreeRTOS/pull/889 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add ulTaskGetRunTimeCounter and ulTaskGetRunTimePercent (#611) Allow ulTaskGetIdleRunTimeCounter and ulTaskGetIdleRunTimePercent to be used whenever configGENERATE_RUN_TIME_STATS is enabled, as this is the only requirement for these functions to work. * Fix some CMake documentation typos (#616) The quick start instructions for CMake mention the "master" git branch which has been replaced by "main" in the current repo. The main CMakeLists.txt documents how to integrate a custom port. Fix a typo in the suggested CMake code. * Added support of 64bit events. (#597) * Added support of 64bit even Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Added missing brackets Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Made proper name for tick macro. Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Improved macro evaluation Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Fixed missed port files + documentation Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Changes made on PR Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Fix macro definition. Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Formatted code with uncrustify Signed-off-by: Cervenka Dusan <cervenka@acrios.com> --------- Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Introduce portMEMORY_BARRIER for Microblaze port. (#621) The introduction of `portMEMORY_BARRIER` will ensure the places in the kernel use a barrier will work. For example, `xTaskResumeAll` has a memory barrier to ensure its correctness when compiled with optimization enabled. Without the barrier `xTaskResumeAll` can fail (e.g. start reading and writing to address 0 and/or infinite looping) when `xPendingReadyList` contains more than one task to restore. In `xTaskResumeAll` the compiler chooses to cache the `pxTCB` the first time through the loop for use in every subsequent loop. This is incorrect as the removal of `pxTCB->xEventListItem` will actually change the value of `pxTCB` if it was read again at the top of the loop. The barrier forces the compiler to read `pxTCB` again at the top of the loop. The compiler is operating correctly. The removal `pxTCB->xEventListItem` executes on a `List_t *` and `ListItem_t *`. This means that the compiler can assume that any `MiniListItem_t` values are unchanged by the loop (i.e. "strict-aliasing"). This allows the compiler to cache `pxTCB` as it is obtained via a `MiniListItem_t`. This is incorrect in this case because it is possible for a `ListItem_t *` to actually alias a `MiniListItem_t`. This is technically a "violation of aliasing rules" so we use the the barrier to disable the strict-aliasing optimization in this loop. * Do not call exit() on MSVC Port when calling vPortEndScheduler (#624) * make port exitable * correctly set xPortRunning to False * add suggestions from Review Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * add suggestions from Review Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update PR template to include checkbox for Unit Test related changes (#627) * Fix build failure introduced in PR #597 (#629) The PR #597 introduced a new config option configTICK_TYPE_WIDTH_IN_BITS which can be defined to one of the following: * TICK_TYPE_WIDTH_16_BITS - Tick type is 16 bit wide. * TICK_TYPE_WIDTH_32_BITS - Tick type is 32 bit wide. * TICK_TYPE_WIDTH_64_BITS - Tick type is 64 bit wide. Earlier we supported 16 and 32 bit width for tick type which was controlled using the config option configUSE_16_BIT_TICKS. The PR tried to maintain backward compatibility by honoring configUSE_16_BIT_TICKS. The backward compatibility did not work as expected though, as the macro configTICK_TYPE_WIDTH_IN_BITS was used before it was defined. This PR addresses it by ensuring that the macro configTICK_TYPE_WIDTH_IN_BITS is defined before it is used. Testing 1. configUSE_16_BIT_TICKS is defined to 0. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 109e: 4b50 ldr r3, [pc, #320] ; (11e0 <xTaskIncrementTick+0x150>) 10a0: f8d3 4134 ldr.w r4, [r3, #308] ; 0x134 10a4: 3401 adds r4, #1 10a6: f8c3 4134 str.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 32 bit. 2. configUSE_16_BIT_TICKS is defined to 1. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 10e2: 4b53 ldr r3, [pc, #332] ; (1230 <xTaskIncrementTick+0x15c>) 10e4: f8b3 4134 ldrh.w r4, [r3, #308] ; 0x134 10e8: b2a4 uxth r4, r4 10ea: 3401 adds r4, #1 10ec: b2a4 uxth r4, r4 10ee: f8a3 4134 strh.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 16 bit. 3. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_16_BITS. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 10e2: 4b53 ldr r3, [pc, #332] ; (1230 <xTaskIncrementTick+0x15c>) 10e4: f8b3 4134 ldrh.w r4, [r3, #308] ; 0x134 10e8: b2a4 uxth r4, r4 10ea: 3401 adds r4, #1 10ec: b2a4 uxth r4, r4 10ee: f8a3 4134 strh.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 16 bit. 4. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_32_BITS. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 109e: 4b50 ldr r3, [pc, #320] ; (11e0 <xTaskIncrementTick+0x150>) 10a0: f8d3 4134 ldr.w r4, [r3, #308] ; 0x134 10a4: 3401 adds r4, #1 10a6: f8c3 4134 str.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 32 bit. 5. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_64_BITS. ``` #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. ``` The testing was done for GCC/ARM_CM3 port which does not support 64 bit tick type. 6. Neither configUSE_16_BIT_TICKS nor configTICK_TYPE_WIDTH_IN_BITS defined. ``` #error Missing definition: One of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. ``` 7. Both configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS defined. ``` #error Only one of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. ``` Related issue - https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/628 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Feature/fixing clang gnu compiler warnings (#620) * Adding in ability to support a library for freertos_config and a custom freertos_kernel_port (#558) * Using single name definition for libraries everywhere. (#558) * Supporting backwards compatibility with FREERTOS_CONFIG_FILE_DIRECTORY (#571) * Removing compiler warnings for GNU and Clang. (#571) * Added in documentation on how to consume from a main project. Added default PORT selection for native POSIX and MINGW platforms. * Only adding freertos_config if it exists. Removing auto generation of it from a FREERTOS_CONFIG_FILE_DIRECTORY. * Fixing clang and gnu compiler warnings. * Adding in project information and how to compile for GNU/clang * Fixing compiler issue with unused variable - no need to declare variable. * Adding in compile warnings for linux builds that kernel is okay with using. * Fixing more extra-semi-stmt clang warnings. * Moving definition of hooks into header files if features are enabled. * Fixing formatting with uncrustify. * Fixing merge conflicts with main merge. * Fixing compiler errors due to merge issues and formatting. * Fixing Line feeds. * Adding 'portNORETURN' into portmacros.h. Other Updates based on PR request * Further clean-up of clang and clang-tidy issues. * Removing compiler specific pragmas from common c files. * Fixing missing lexicon entry and uncrustify formatting changes. * Resolving merge issue multiple defnitions of proto for prvIdleTask * Fixing formatting issues that are not covered by uncrustify. Use clang-tidy instead if you want this level of control. * More uncrustify formatting issues. * Fixing extra bracket in #if statement. --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * POSIX port fixes (#626) * Fix types in POSIX port Use TaskFunction_t and StackType_t as other ports do. * Fix portTICK_RATE_MICROSECONDS in POSIX port --------- Co-authored-by: Jacques GUILLOU <jacques.guillou.job@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Cortex-M35P: Add Cortex-M35P port (#631) * Cortex-M35P: Add Cortex-M35P port The Cortex-M35P support added to kernel. The port hasn't been validated yet with TF-M. Hence TF-M support is not included in this port. Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> * Add portNORETURN to the newly added portmacro.h Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> * Introduced Github Status Badge for Unit Tests (#634) * Introduced Github Status Badge for Unit Tests * Github status badge to point to latest run * Github status badge UT points to latest results * Fixed URL for Github Status badge --------- Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> * Remove C99 requirement from CMake file (#633) * Remove C99 requirement from CMake file The kernel source is C89 compliant and does not need C99. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Explicitly set C89 requirement for kernel Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add Thread Local Storage (TLS) support using Picolibc functions (#343) * Pass top of stack to configINIT_TLS_BLOCK Picolibc wants to allocate the per-task TLS block within the stack segment, so it will need to modify the top of stack value. Pass the pxTopOfStack variable to make this explicit. Signed-off-by: Keith Packard <keithpac@amazon.com> * Move newlib-specific definitions to separate file This reduces the clutter in FreeRTOS.h caused by having newlib-specific macros present there. Signed-off-by: Keith Packard <keithpac@amazon.com> * Make TLS code depend only on configUSE_C_RUNTIME_TLS_SUPPORT Remove reference to configUSE_NEWLIB_REENTRANT as that only works when using newlib. configUSE_C_RUNTIME_TLS_SUPPORT is always set when configUSE_NEWLIB_REENTRANT is set, so using both was redundant in that case. Signed-off-by: Keith Packard <keithpac@amazon.com> * portable-ARC: Adapt ARC support to use generalized TLS support With generalized thread local storage (TLS) support present in the core, the two ARC ports need to have the changes to the TCB mirrored to them. Signed-off-by: Keith Packard <keithpac@amazon.com> * Add Thread Local Storage (TLS) support using Picolibc functions This patch provides definitions of the general TLS support macros in terms of the Picolibc TLS support functions. Picolibc is normally configured to use TLS internally for all variables that are intended to be task-local, so these changes are necessary for picolibc to work correctly with FreeRTOS. The picolibc helper functions rely on elements within the linker script to arrange the TLS data in memory and define some symbols. Applications wanting to use this mechanism will need changes in their linker script when migrating to picolibc. Signed-off-by: Keith Packard <keithpac@amazon.com> --------- Signed-off-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Interrupt priority assert improvements for CM3/4/7 (#602) * Interrupt priority assert improvements for CM3/4/7 In the ARM_CM3, ARM_CM4, and ARM_CM7 ports, change the assertion that `configMAX_SYSCALL_INTERRUPT_PRIORITY` is nonzero to account for the number of priority bits implemented by the hardware. Change these ports to also use the lowest priority for PendSV and SysTick, ignoring `configKERNEL_INTERRUPT_PRIORITY`. * Remove not needed configKERNEL_INTERRUPT_PRIORITY define Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Introduced code coverage status badge (#635) * Introduced code coverage status badge * Trying to fix the URL checker issue * Fix URL check Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * added portPOINTER_SIZE_TYPE and SIZE_MAX definition to PIC24/dsPIC port (#636) * added portPOINTER_SIZE_TYPE definition to PIC24/dsPIC port * Added SIZE_MAX definition to PIC24/dsPIC33 * Fix TLS and stack alignment when using picolibc (#637) Both the TLS block and stack must be correctly aligned when using picolibc. The architecture stack alignment is represented by the portBYTE_ALIGNMENT_MASK and the TLS block alignment is provided by the Picolibc _tls_align() inline function for Picolibc version 1.8 and above. For older versions of Picolibc, we'll assume that the TLS block requires the same alignment as the stack. For downward growing stacks, this requires aligning the start of the TLS block to the maximum of the stack alignment and the TLS alignment. With this, both the TLS block and stack will now be correctly aligned. For upward growing stacks, the two areas must be aligned independently; the TLS block is aligned from the start of the stack, then the tls space is allocated, and then the stack is aligned above that. It's probably useful to know here that the linker ensures that variables within the TLS block are assigned offsets that match their alignment requirements. If the TLS block itself is correctly aligned, then everything within will also be. I have only tested the downward growing stack branch of this patch. Signed-off-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Enable building the GCC Cortex-R5 port without an FPU (#586) * Ensure configUSE_TASK_FPU_SUPPORT option is set correctly If one does enable the FPU of the Cortex-R5 processor, then the GCC compiler will define the macro __ARM_FP. This can be used to ensure, that the configUSE_TASK_FPU_SUPPORT is set accordingly. * Enable the implementation of vPortTaskUsesFPU only if configUSE_TASK_FPU_SUPPORT is set to 1 * Remove error case in pxPortInitialiseStack The case of configUSE_TASK_FPU_SUPPORT is 0 is now handled * Enable access to FPU registers only if FPU is enabled * Make minor formating changes * Format ARM Cortex-R5 port * Address review comments from @ChristosZosi * Minor code review suggestions Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Fix freertos_kernel cmake property, Posix Port (#640) * Fix freertos_kernel cmake property, Posix Port * Moves the `set_property()` call below the target definition in top level CMakeLists file * Corrects billion value from `ULL` suffix (not C90 compliant) to `UL` suffix with cast to uint64_t * Add blank line to CMakeLists.txt * Add missing FreeRTOS+ defines * Run kernel demos and unit tests for PR changes (#645) * Run kernel demos and unit tests for PR changes Kernel demos check builds multiple demos from FreeRTOS/FreeRTOS and unit tests check runs unit tests in FreeRTOS/FreeRTOS. Both of these checks currently use main branch of FreeRTOS-Kernel. This commits updates these checks to use the changes in the PR. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Do not specify PR SHA explicitly as that is default Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Remove explicit PR SHA from kernel checks Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add functions to get the buffers of statically created objects (#641) Added various ...GetStaticBuffer() functions to get the buffers of statically created objects. --------- Co-authored-by: Paul Bartell <pbartell@amazon.com> Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Cortex-M Assert when NVIC implements 8 PRIO bits (#639) * Cortex-M Assert when NVIC implements 8 PRIO bits * Fix CM3 ports * Fix ARM_CM3_MPU * Fix ARM CM3 * Fix ARM_CM4_MPU * Fix ARM_CM4 * Fix GCC ARM_CM7 * Fix IAR ARM ports * Uncrustify changes * Fix MikroC_ARM_CM4F port * Fix MikroC_ARM_CM4F port-(2) * Fix RVDS ARM ports * Revert changes for Tasking/ARM_CM4F port * Revert changes for Tasking/ARM_CM4F port-(2) * Update port.c Fix GCC/ARM_CM4F port * Update port.c * update GCC\ARM_CM4F port * update port.c * Assert to check configMAX_SYSCALL_INTERRUPT_PRIORITY is set to higher priority * Fix merge error: remove duplicate code * Fix typos --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-17-174.ec2.internal> * Remove C90 requirement from CMakeLists (#649) This is needed as it is breaking projects - https://forums.freertos.org/t/freertos-gcc-cmake/16984 We will re-evaluate and accordingly add this later. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Only add alignment padding when needed (#650) Heap 4 and Heap 5 add some padding to ensure that the allocated blocks are always aligned to portBYTE_ALIGNMENT bytes. The code until now was adding padding always even if the resulting block was already aligned. This commits updates the code to only add padding if the resulting block is not aligned. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * add a missing comma (#651) * fix conversion warning (#658) FreeRTOS-Kernel/portable/GCC/ARM_CM4F/port.c:399:41: error: conversion from 'uint32_t' {aka 'long unsigned int'} to 'uint8_t' {aka 'unsigned char'} may change value [-Werror=conversion] Signed-off-by: Vo Trung Chi <chi.votrung@vn.bosch.com> * ARMv7M: Adjust implemented priority bit assertions (#665) Adjust assertions related to the CMSIS __NVIC_PRIO_BITS and FreeRTOS configPRIO_BITS configuration macros such that these macros specify the minimum number of implemented priority bits supported by a config build rather than the exact number of implemented priority bits. Related to Qemu issue #1122 * Format portmacro.h in arm CM0 ports * portable/ARM_CM0: Add xPortIsInsideInterrupt Add missing xPortIsInsideInterrupt function to Cortex-M0 port. * tree-wide: Unify formatting of __cplusplus ifdefs * Paranthesize expression-like macro (#668) * Updated tasks.c checks for scheduler suspension (#670) This commit updates the checks for the variable uxSchedulerSuspended in tasks.c module to use a uniform format. Signed-off-by: Sudeep Mohanty <sudp.mohanty@gmail.com> * Fix cast alignment warning (#669) * Fix cast alignment warning Without this change, the code produces the following warning when compiled with `-Wcast-align` flag: ``` cast increases required alignment of target type ``` Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Align StackSize and StackAddress for macOS (#674) * Armv8-M (except Cortex-M23) interrupt priority checking (#673) * Armv8-M: Formatting changes Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> * Armv8-M: Add support for interrupt priority check FreeRTOS provides `FromISR` system calls which can be called directly from interrupt service routines. It is crucial that the priority of these ISRs is set to same or lower value (numerically higher) than that of `configMAX_SYSCALL_INTERRUPT_PRIORITY`. For more information refer to https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. Add a check to trigger an assert when an ISR with priority higher (numerically lower) than `configMAX_SYSCALL_INTERRUPT_PRIORITY` calls `FromISR` system calls if `configASSERT` macro is defined. In addition, add a config option `configQEMU_DISABLE_INTERRUPT_PRIO_BITS_CHECK` to disable interrupt priority check while running on QEMU. Based on the discussion https://gitlab.com/qemu-project/qemu/-/issues/1122, The interrupt priority bits in QEMU do not match the real hardware. Therefore the assert that checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. The config option `configQEMU_DISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the `FreeRTOSConfig.h` for QEMU targets. Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> * Use SHPR2 for calculating interrupt priority bits This removes the dependency on the secure software to mark the interrupt as non-secure. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Use the extended movx instruction instead of mov (#676) The following is from the MSP430X instruction set - ``` MOVX.W Move source word to destination word. The source operand is copied to the destination. The source operand is not affected. Both operands may be located in the full address space. ``` The movx instruction allows both the operands to be located in the full address space and therefore, works with large data model as well. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Cervenka Dusan <cervenka@acrios.com> Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Keith Packard <keithpac@amazon.com> Signed-off-by: Vo Trung Chi <chi.votrung@vn.bosch.com> Signed-off-by: Sudeep Mohanty <sudp.mohanty@gmail.com> Co-authored-by: Archit Gupta <71798289+archigup@users.noreply.github.com> Co-authored-by: tcpluess <tpluess@ieee.org> Co-authored-by: pluess <pluess@faulhorn.mw.iap.unibe.ch> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Chris Copeland <chris@chrisnc.net> Co-authored-by: David J. Fiddes <35607151+davefiddes@users.noreply.github.com> Co-authored-by: Dusan Cervenka <cervenka@acrios.com> Co-authored-by: bbain <16752579+bbain@users.noreply.github.com> Co-authored-by: Ju1He1 <93189163+Ju1He1@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: phelter <paulheltera@gmail.com> Co-authored-by: jacky309 <jacques.guillou@gmail.com> Co-authored-by: Jacques GUILLOU <jacques.guillou.job@gmail.com> Co-authored-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com> Co-authored-by: Keith Packard <keithp@keithp.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Joseph Julicher <jjulicher@mac.com> Co-authored-by: Paul Bartell <pbartell@amazon.com> Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com> Co-authored-by: Kody Stribrny <89810515+kstribrnAmzn@users.noreply.github.com> Co-authored-by: Holden <holden-zenithaerotech.com> Co-authored-by: Darian <32921628+Dazza0@users.noreply.github.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-17-174.ec2.internal> Co-authored-by: Nicolas <nicolas.brunner@heig-vd.ch> Co-authored-by: Vo Trung Chi <chi.votrung@vn.bosch.com> Co-authored-by: Sudeep Mohanty <91244425+sudeep-mohanty@users.noreply.github.com> Co-authored-by: Monika Singh <108652024+moninom1@users.noreply.github.com> * Merge main to SMP branch (#86) * Fix array-bounds compiler warning on gcc11+ in list.h (#580) listGET_OWNER_OF_NEXT_ENTRY computes `( pxConstList )->pxIndex->pxNext` after verifying that `( pxConstList )->pxIndex` points to `xListEnd`, which due to being a MiniListItem_t, can be shorter than a ListItem_t. Thus, `( pxConstList )->pxIndex` is a `ListItem_t *` that extends past the end of the `List_t` whose `xListEnd` it points to. This is fixed by accessing `pxNext` through a `MiniListItem_t` instead. * move the prototype for vApplicationIdleHook to task.h. (#600) Co-authored-by: pluess <pluess@faulhorn.mw.iap.unibe.ch> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update equal priority task preemption (#603) * vTaskResume and vTaskPrioritySet don't preempt equal priority task * Update vTaskResumeAll not to preempt task with equal priority * Fix in xTaskResumeFromISR * Update FreeRTOS/FreeRTOS build checks (#613) This is needed to be compatible with the refactoring done in this PR - https://github.com/FreeRTOS/FreeRTOS/pull/889 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add ulTaskGetRunTimeCounter and ulTaskGetRunTimePercent (#611) Allow ulTaskGetIdleRunTimeCounter and ulTaskGetIdleRunTimePercent to be used whenever configGENERATE_RUN_TIME_STATS is enabled, as this is the only requirement for these functions to work. * Fix some CMake documentation typos (#616) The quick start instructions for CMake mention the "master" git branch which has been replaced by "main" in the current repo. The main CMakeLists.txt documents how to integrate a custom port. Fix a typo in the suggested CMake code. * Added support of 64bit events. (#597) * Added support of 64bit even Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Added missing brackets Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Made proper name for tick macro. Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Improved macro evaluation Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Fixed missed port files + documentation Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Changes made on PR Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Fix macro definition. Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Formatted code with uncrustify Signed-off-by: Cervenka Dusan <cervenka@acrios.com> --------- Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Introduce portMEMORY_BARRIER for Microblaze port. (#621) The introduction of `portMEMORY_BARRIER` will ensure the places in the kernel use a barrier will work. For example, `xTaskResumeAll` has a memory barrier to ensure its correctness when compiled with optimization enabled. Without the barrier `xTaskResumeAll` can fail (e.g. start reading and writing to address 0 and/or infinite looping) when `xPendingReadyList` contains more than one task to restore. In `xTaskResumeAll` the compiler chooses to cache the `pxTCB` the first time through the loop for use in every subsequent loop. This is incorrect as the removal of `pxTCB->xEventListItem` will actually change the value of `pxTCB` if it was read again at the top of the loop. The barrier forces the compiler to read `pxTCB` again at the top of the loop. The compiler is operating correctly. The removal `pxTCB->xEventListItem` executes on a `List_t *` and `ListItem_t *`. This means that the compiler can assume that any `MiniListItem_t` values are unchanged by the loop (i.e. "strict-aliasing"). This allows the compiler to cache `pxTCB` as it is obtained via a `MiniListItem_t`. This is incorrect in this case because it is possible for a `ListItem_t *` to actually alias a `MiniListItem_t`. This is technically a "violation of aliasing rules" so we use the the barrier to disable the strict-aliasing optimization in this loop. * Do not call exit() on MSVC Port when calling vPortEndScheduler (#624) * make port exitable * correctly set xPortRunning to False * add suggestions from Review Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * add suggestions from Review Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update PR template to include checkbox for Unit Test related changes (#627) * Fix build failure introduced in PR #597 (#629) The PR #597 introduced a new config option configTICK_TYPE_WIDTH_IN_BITS which can be defined to one of the following: * TICK_TYPE_WIDTH_16_BITS - Tick type is 16 bit wide. * TICK_TYPE_WIDTH_32_BITS - Tick type is 32 bit wide. * TICK_TYPE_WIDTH_64_BITS - Tick type is 64 bit wide. Earlier we supported 16 and 32 bit width for tick type which was controlled using the config option configUSE_16_BIT_TICKS. The PR tried to maintain backward compatibility by honoring configUSE_16_BIT_TICKS. The backward compatibility did not work as expected though, as the macro configTICK_TYPE_WIDTH_IN_BITS was used before it was defined. This PR addresses it by ensuring that the macro configTICK_TYPE_WIDTH_IN_BITS is defined before it is used. Testing 1. configUSE_16_BIT_TICKS is defined to 0. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 109e: 4b50 ldr r3, [pc, #320] ; (11e0 <xTaskIncrementTick+0x150>) 10a0: f8d3 4134 ldr.w r4, [r3, #308] ; 0x134 10a4: 3401 adds r4, #1 10a6: f8c3 4134 str.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 32 bit. 2. configUSE_16_BIT_TICKS is defined to 1. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 10e2: 4b53 ldr r3, [pc, #332] ; (1230 <xTaskIncrementTick+0x15c>) 10e4: f8b3 4134 ldrh.w r4, [r3, #308] ; 0x134 10e8: b2a4 uxth r4, r4 10ea: 3401 adds r4, #1 10ec: b2a4 uxth r4, r4 10ee: f8a3 4134 strh.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 16 bit. 3. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_16_BITS. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 10e2: 4b53 ldr r3, [pc, #332] ; (1230 <xTaskIncrementTick+0x15c>) 10e4: f8b3 4134 ldrh.w r4, [r3, #308] ; 0x134 10e8: b2a4 uxth r4, r4 10ea: 3401 adds r4, #1 10ec: b2a4 uxth r4, r4 10ee: f8a3 4134 strh.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 16 bit. 4. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_32_BITS. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 109e: 4b50 ldr r3, [pc, #320] ; (11e0 <xTaskIncrementTick+0x150>) 10a0: f8d3 4134 ldr.w r4, [r3, #308] ; 0x134 10a4: 3401 adds r4, #1 10a6: f8c3 4134 str.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 32 bit. 5. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_64_BITS. ``` #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. ``` The testing was done for GCC/ARM_CM3 port which does not support 64 bit tick type. 6. Neither configUSE_16_BIT_TICKS nor configTICK_TYPE_WIDTH_IN_BITS defined. ``` #error Missing definition: One of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. ``` 7. Both configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS defined. ``` #error Only one of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. ``` Related issue - https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/628 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Feature/fixing clang gnu compiler warnings (#620) * Adding in ability to support a library for freertos_config and a custom freertos_kernel_port (#558) * Using single name definition for libraries everywhere. (#558) * Supporting backwards compatibility with FREERTOS_CONFIG_FILE_DIRECTORY (#571) * Removing compiler warnings for GNU and Clang. (#571) * Added in documentation on how to consume from a main project. Added default PORT selection for native POSIX and MINGW platforms. * Only adding freertos_config if it exists. Removing auto generation of it from a FREERTOS_CONFIG_FILE_DIRECTORY. * Fixing clang and gnu compiler warnings. * Adding in project information and how to compile for GNU/clang * Fixing compiler issue with unused variable - no need to declare variable. * Adding in compile warnings for linux builds that kernel is okay with using. * Fixing more extra-semi-stmt clang warnings. * Moving definition of hooks into header files if features are enabled. * Fixing formatting with uncrustify. * Fixing merge conflicts with main merge. * Fixing compiler errors due to merge issues and formatting. * Fixing Line feeds. * Adding 'portNORETURN' into portmacros.h. Other Updates based on PR request * Further clean-up of clang and clang-tidy issues. * Removing compiler specific pragmas from common c files. * Fixing missing lexicon entry and uncrustify formatting changes. * Resolving merge issue multiple defnitions of proto for prvIdleTask * Fixing formatting issues that are not covered by uncrustify. Use clang-tidy instead if you want this level of control. * More uncrustify formatting issues. * Fixing extra bracket in #if statement. --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * POSIX port fixes (#626) * Fix types in POSIX port Use TaskFunction_t and StackType_t as other ports do. * Fix portTICK_RATE_MICROSECONDS in POSIX port --------- Co-authored-by: Jacques GUILLOU <jacques.guillou.job@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Cortex-M35P: Add Cortex-M35P port (#631) * Cortex-M35P: Add Cortex-M35P port The Cortex-M35P support added to kernel. The port hasn't been validated yet with TF-M. Hence TF-M support is not included in this port. Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> * Add portNORETURN to the newly added portmacro.h Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> * Introduced Github Status Badge for Unit Tests (#634) * Introduced Github Status Badge for Unit Tests * Github status badge to point to latest run * Github status badge UT points to latest results * Fixed URL for Github Status badge --------- Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> * Remove C99 requirement from CMake file (#633) * Remove C99 requirement from CMake file The kernel source is C89 compliant and does not need C99. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Explicitly set C89 requirement for kernel Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add Thread Local Storage (TLS) support using Picolibc functions (#343) * Pass top of stack to configINIT_TLS_BLOCK Picolibc wants to allocate the per-task TLS block within the stack segment, so it will need to modify the top of stack value. Pass the pxTopOfStack variable to make this explicit. Signed-off-by: Keith Packard <keithpac@amazon.com> * Move newlib-specific definitions to separate file This reduces the clutter in FreeRTOS.h caused by having newlib-specific macros present there. Signed-off-by: Keith Packard <keithpac@amazon.com> * Make TLS code depend only on configUSE_C_RUNTIME_TLS_SUPPORT Remove reference to configUSE_NEWLIB_REENTRANT as that only works when using newlib. configUSE_C_RUNTIME_TLS_SUPPORT is always set when configUSE_NEWLIB_REENTRANT is set, so using both was redundant in that case. Signed-off-by: Keith Packard <keithpac@amazon.com> * portable-ARC: Adapt ARC support to use generalized TLS support With generalized thread local storage (TLS) support present in the core, the two ARC ports need to have the changes to the TCB mirrored to them. Signed-off-by: Keith Packard <keithpac@amazon.com> * Add Thread Local Storage (TLS) support using Picolibc functions This patch provides definitions of the general TLS support macros in terms of the Picolibc TLS support functions. Picolibc is normally configured to use TLS internally for all variables that are intended to be task-local, so these changes are necessary for picolibc to work correctly with FreeRTOS. The picolibc helper functions rely on elements within the linker script to arrange the TLS data in memory and define some symbols. Applications wanting to use this mechanism will need changes in their linker script when migrating to picolibc. Signed-off-by: Keith Packard <keithpac@amazon.com> --------- Signed-off-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Interrupt priority assert improvements for CM3/4/7 (#602) * Interrupt priority assert improvements for CM3/4/7 In the ARM_CM3, ARM_CM4, and ARM_CM7 ports, change the assertion that `configMAX_SYSCALL_INTERRUPT_PRIORITY` is nonzero to account for the number of priority bits implemented by the hardware. Change these ports to also use the lowest priority for PendSV and SysTick, ignoring `configKERNEL_INTERRUPT_PRIORITY`. * Remove not needed configKERNEL_INTERRUPT_PRIORITY define Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Introduced code coverage status badge (#635) * Introduced code coverage status badge * Trying to fix the URL checker issue * Fix URL check Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * added portPOINTER_SIZE_TYPE and SIZE_MAX definition to PIC24/dsPIC port (#636) * added portPOINTER_SIZE_TYPE definition to PIC24/dsPIC port * Added SIZE_MAX definition to PIC24/dsPIC33 * Fix TLS and stack alignment when using picolibc (#637) Both the TLS block and stack must be correctly aligned when using picolibc. The architecture stack alignment is represented by the portBYTE_ALIGNMENT_MASK and the TLS block alignment is provided by the Picolibc _tls_align() inline function for Picolibc version 1.8 and above. For older versions of Picolibc, we'll assume that the TLS block requires the same alignment as the stack. For downward growing stacks, this requires aligning the start of the TLS block to the maximum of the stack alignment and the TLS alignment. With this, both the TLS block and stack will now be correctly aligned. For upward growing stacks, the two areas must be aligned independently; the TLS block is aligned from the start of the stack, then the tls space is allocated, and then the stack is aligned above that. It's probably useful to know here that the linker ensures that variables within the TLS block are assigned offsets that match their alignment requirements. If the TLS block itself is correctly aligned, then everything within will also be. I have only tested the downward growing stack branch of this patch. Signed-off-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Enable building the GCC Cortex-R5 port without an FPU (#586) * Ensure configUSE_TASK_FPU_SUPPORT option is set correctly If one does enable the FPU of the Cortex-R5 processor, then the GCC compiler will define the macro __ARM_FP. This can be used to ensure, that the configUSE_TASK_FPU_SUPPORT is set accordingly. * Enable the implementation of vPortTaskUsesFPU only if configUSE_TASK_FPU_SUPPORT is set to 1 * Remove error case in pxPortInitialiseStack The case of configUSE_TASK_FPU_SUPPORT is 0 is now handled * Enable access to FPU registers only if FPU is enabled * Make minor formating changes * Format ARM Cortex-R5 port * Address review comments from @ChristosZosi * Minor code review suggestions Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Fix freertos_kernel cmake property, Posix Port (#640) * Fix freertos_kernel cmake property, Posix Port * Moves the `set_property()` call below the target definition in top level CMakeLists file * Corrects billion value from `ULL` suffix (not C90 compliant) to `UL` suffix with cast to uint64_t * Add blank line to CMakeLists.txt * Add missing FreeRTOS+ defines * Run kernel demos and unit tests for PR changes (#645) * Run kernel demos and unit tests for PR changes Kernel demos check builds multiple demos from FreeRTOS/FreeRTOS and unit tests check runs unit tests in FreeRTOS/FreeRTOS. Both of these checks currently use main branch of FreeRTOS-Kernel. This commits updates these checks to use the changes in the PR. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Do not specify PR SHA explicitly as that is default Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Remove explicit PR SHA from kernel checks Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add functions to get the buffers of statically created objects (#641) Added various ...GetStaticBuffer() functions to get the buffers of statically created objects. --------- Co-authored-by: Paul Bartell <pbartell@amazon.com> Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Cortex-M Assert when NVIC implements 8 PRIO bits (#639) * Cortex-M Assert when NVIC implements 8 PRIO bits * Fix CM3 ports * Fix ARM_CM3_MPU * Fix ARM CM3 * Fix ARM_CM4_MPU * Fix ARM_CM4 * Fix GCC ARM_CM7 * Fix IAR ARM ports * Uncrustify changes * Fix MikroC_ARM_CM4F port * Fix MikroC_ARM_CM4F port-(2) * Fix RVDS ARM ports * Revert changes for Tasking/ARM_CM4F port * Revert changes for Tasking/ARM_CM4F port-(2) * Update port.c Fix GCC/ARM_CM4F port * Update port.c * update GCC\ARM_CM4F port * update port.c * Assert to check configMAX_SYSCALL_INTERRUPT_PRIORITY is set to higher priority * Fix merge error: remove duplicate code * Fix typos --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-17-174.ec2.internal> * Remove C90 requirement from CMakeLists (#649) This is needed as it is breaking projects - https://forums.freertos.org/t/freertos-gcc-cmake/16984 We will re-evaluate and accordingly add this later. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Only add alignment padding when needed (#650) Heap 4 and Heap 5 add some padding to ensure that the allocated blocks are always aligned to portBYTE_ALIGNMENT bytes. The code until now was adding padding always even if the resulting block was already aligned. This commits updates the code to only add padding if the resulting block is not aligned. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * add a missing comma (#651) * fix conversion warning (#658) FreeRTOS-Kernel/portable/GCC/ARM_CM4F/port.c:399:41: error: conversion from 'uint32_t' {aka 'long unsigned int'} to 'uint8_t' {aka 'unsigned char'} may change value [-Werror=conversion] Signed-off-by: Vo Trung Chi <chi.votrung@vn.bosch.com> * ARMv7M: Adjust implemented priority bit assertions (#665) Adjust assertions related to the CMSIS __NVIC_PRIO_BITS and FreeRTOS configPRIO_BITS configuration macros such that these macros specify the minimum number of implemented priority bits supported by a config build rather than the exact number of implemented priority bits. Related to Qemu issue #1122 * Format portmacro.h in arm CM0 ports * portable/ARM_CM0: Add xPortIsInsideInterrupt Add missing xPortIsInsideInterrupt function to Cortex-M0 port. * tree-wide: Unify formatting of __cplusplus ifdefs * Paranthesize expression-like macro (#668) * Updated tasks.c checks for scheduler suspension (#670) This commit updates the checks for the variable uxSchedulerSuspended in tasks.c module to use a uniform format. Signed-off-by: Sudeep Mohanty <sudp.mohanty@gmail.com> * Fix cast alignment warning (#669) * Fix cast alignment warning Without this change, the code produces the following warning when compiled with `-Wcast-align` flag: ``` cast increases required alignment of target type ``` Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Align StackSize and StackAddress for macOS (#674) * Armv8-M (except Cortex-M23) interrupt priority checking (#673) * Armv8-M: Formatting changes Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> * Armv8-M: Add support for interrupt priority check FreeRTOS provides `FromISR` system calls which can be called directly from interrupt service routines. It is crucial that the priority of these ISRs is set to same or lower value (numerically higher) than that of `configMAX_SYSCALL_INTERRUPT_PRIORITY`. For more information refer to https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. Add a check to trigger an assert when an ISR with priority higher (numerically lower) than `configMAX_SYSCALL_INTERRUPT_PRIORITY` calls `FromISR` system calls if `configASSERT` macro is defined. In addition, add a config option `configQEMU_DISABLE_INTERRUPT_PRIO_BITS_CHECK` to disable interrupt priority check while running on QEMU. Based on the discussion https://gitlab.com/qemu-project/qemu/-/issues/1122, The interrupt priority bits in QEMU do not match the real hardware. Therefore the assert that checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. The config option `configQEMU_DISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the `FreeRTOSConfig.h` for QEMU targets. Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> * Use SHPR2 for calculating interrupt priority bits This removes the dependency on the secure software to mark the interrupt as non-secure. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Use the extended movx instruction instead of mov (#676) The following is from the MSP430X instruction set - ``` MOVX.W Move source word to destination word. The source operand is copied to the destination. The source operand is not affected. Both operands may be located in the full address space. ``` The movx instruction allows both the operands to be located in the full address space and therefore, works with large data model as well. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Fix eTaskGetState for pending ready tasks (#679) This commit fixes eTaskGetState so that eReady is returned for pending ready tasks. Co-authored-by: Darian Leung <darian@espressif.com> * Generates SBOM after source files are updated with release tag (#680) * update source file with release version info before SBOM generation * delete tag branch during cleanup * Add back croutines by reverting PR#590 (#685) * Add croutines to the code base * Add croutine changes to cmake, lexicon and readme * Add croutine file to portable cmake file * Add back more references from PR 591 * Remove __NVIC_PRIO_BITS and configPRIO_BITS check in port (#683) * Remove __NVIC_PRIO_BITS and configPRIO_BITS check in CM3, CM4 and ARMv8. * Add hardware not implemented bits check. These bits should be zero. --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Use UBaseType_t as interrupt mask (#689) * Use UBaseType_t as interrupt mask * Update GCC posix port to use UBaseType_t as interrupt mask * Fix clang warning in croutine and stream buffer (#686) * Fix document warning in croutine * Fix cast-qual warning in stream buffer * Use portTASK_FUNCTION_PROTO to replace portNORETURN (#688) * Use portTASK_FUNCTION_PROTO to replace portNORETURN * Fix typo in check comment of configMAX_SYSCALL_INTERRUPT_PRIORITY (#690) * Add constant type for portMAX_DELAY in port (#691) Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update static stream buffer size check (#693) * Use volatile size instead of sizeof directly to prevent always true/false warning * Fix typos in comments for the AT91SAM7S port (#695) Co-authored-by: RichardBarry <3073890+RichardBarry@users.noreply.github.com> * Fix #697: Missing portPOINTER_SIZE_TYPE definition for ATmega port (#698) * Remove empty expression statement compiler warning (#692) * Add do while( 0 ) loop for empty expression statement compiler warning * Update uxTaskGetSystemState for tasks in pending ready list (#702) * Update uxTaskGetSystemState to sync with eTaskGetState * Update in vTaskGetInfo for tasks in pending ready list should be in ready state. * Fix circular dependency in CMake project (#700) * Fix circular dependency in cmake project Fix for https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/687 In order for custom ports to also break the cycle, they must link against freertos_kernel_include instead of freertos_kernel. * Simplify include path * Memory Protection Unit (MPU) Enhancements (#705) Memory Protection Unit (MPU) Enhancements This commit introduces a new MPU wrapper that places additional restrictions on unprivileged tasks. The following is the list of changes introduced with the new MPU wrapper: 1. Opaque and indirectly verifiable integers for kernel object handles: All the kernel object handles (for example, queue handles) are now opaque integers. Previously object handles were raw pointers. 2. Saving the task context in Task Control Block (TCB): When a task is swapped out by the scheduler, the task's context is now saved in its TCB. Previously the task's context was saved on its stack. 3. Execute system calls on a separate privileged only stack: FreeRTOS system calls, which execute with elevated privilege, now use a separate privileged only stack. Previously system calls used the calling task's stack. The application writer can control the size of the system call stack using new configSYSTEM_CALL_STACK_SIZE config macro. 4. Memory bounds checks: FreeRTOS system calls which accept a pointer and de-reference it, now verify that the calling task has required permissions to access the memory location referenced by the pointer. 5. System call restrictions: The following system calls are no longer available to unprivileged tasks: - vQueueDelete - xQueueCreateMutex - xQueueCreateMutexStatic - xQueueCreateCountingSemaphore - xQueueCreateCountingSemaphoreStatic - xQueueGenericCreate - xQueueGenericCreateStatic - xQueueCreateSet - xQueueRemoveFromSet - xQueueGenericReset - xTaskCreate - xTaskCreateStatic - vTaskDelete - vTaskPrioritySet - vTaskSuspendAll - xTaskResumeAll - xTaskGetHandle - xTaskCallApplicationTaskHook - vTaskList - vTaskGetRunTimeStats - xTaskCatchUpTicks - xEventGroupCreate - xEventGroupCreateStatic - vEventGroupDelete - xStreamBufferGenericCreate - xStreamBufferGenericCreateStatic - vStreamBufferDelete - xStreamBufferReset Also, an unprivileged task can no longer use vTaskSuspend to suspend any task other than itself. We thank the following people for their inputs in these enhancements: - David Reiss of Meta Platforms, Inc. - Lan Luo, Xinhui Shao, Yumeng Wei, Zixia Liu, Huaiyu Yan and Zhen Ling of School of Computer Science and Engineering, Southeast University, China. - Xinwen Fu of Department of Computer Science, University of Massachusetts Lowell, USA. - Yuequi Chen, Zicheng Wang, Minghao Lin of University of Colorado Boulder, USA. * Update History for Version 10.6.0 (#706) Signed-off-by: kar-rahul-aws <karahulx@amazon.com> * Fixed compile options polluting project (#694) * Fixed compile options polluting project Moved add_library higher * Apply suggestions from code review Co-authored-by: Paul Bartell <paul.bartell@gmail.com> * fixed cmakelists keeping in mind the suggestions --------- Co-authored-by: Paul Bartell <paul.bartell@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Fix the comments in the CM3 and CM4 MPU Ports about the MPU Region numbers being loaded (#707) Co-authored-by: Soren Ptak <skptak@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update xSemaphoreGetStaticBuffer prototype in comment (#704) Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Correct the misspelled name (#708) Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Cervenka Dusan <cervenka@acrios.com> Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Keith Packard <keithpac@amazon.com> Signed-off-by: Vo Trung Chi <chi.votrung@vn.bosch.com> Signed-off-by: Sudeep Mohanty <sudp.mohanty@gmail.com> Signed-off-by: kar-rahul-aws <karahulx@amazon.com> Co-authored-by: Archit Gupta <71798289+archigup@users.noreply.github.com> Co-authored-by: tcpluess <tpluess@ieee.org> Co-authored-by: pluess <pluess@faulhorn.mw.iap.unibe.ch> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Chris Copeland <chris@chrisnc.net> Co-authored-by: David J. Fiddes <35607151+davefiddes@users.noreply.github.com> Co-authored-by: Dusan Cervenka <cervenka@acrios.com> Co-authored-by: bbain <16752579+bbain@users.noreply.github.com> Co-authored-by: Ju1He1 <93189163+Ju1He1@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: phelter <paulheltera@gmail.com> Co-authored-by: jacky309 <jacques.guillou@gmail.com> Co-authored-by: Jacques GUILLOU <jacques.guillou.job@gmail.com> Co-authored-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com> Co-authored-by: Keith Packard <keithp@keithp.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Joseph Julicher <jjulicher@mac.com> Co-authored-by: Paul Bartell <pbartell@amazon.com> Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com> Co-authored-by: Kody Stribrny <89810515+kstribrnAmzn@users.noreply.github.com> Co-authored-by: Holden <holden-zenithaerotech.com> Co-authored-by: Darian <32921628+Dazza0@users.noreply.github.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-17-174.ec2.internal> Co-authored-by: Nicolas <nicolas.brunner@heig-vd.ch> Co-authored-by: Vo Trung Chi <chi.votrung@vn.bosch.com> Co-authored-by: Sudeep Mohanty <91244425+sudeep-mohanty@users.noreply.github.com> Co-authored-by: Monika Singh <108652024+moninom1@users.noreply.github.com> Co-authored-by: Darian Leung <darian@espressif.com> Co-authored-by: Tony Josi <tonyjosi@amazon.com> Co-authored-by: Evgeny Ermakov <22344340+unspecd@users.noreply.github.com> Co-authored-by: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Co-authored-by: Joris Putcuyps <joris.putcuyps@gmail.com> Co-authored-by: Patrick Cook <114708437+cookpate@users.noreply.github.com> Co-authored-by: Mr. Jake <norbertzpilicy@gmail.com> Co-authored-by: Paul Bartell <paul.bartell@gmail.com> Co-authored-by: Soren Ptak <Skptak@outlook.com> Co-authored-by: Soren Ptak <skptak@amazon.com> * Merge main to SMP branch 0721 (#90) * Fix array-bounds compiler warning on gcc11+ in list.h (#580) listGET_OWNER_OF_NEXT_ENTRY computes `( pxConstList )->pxIndex->pxNext` after verifying that `( pxConstList )->pxIndex` points to `xListEnd`, which due to being a MiniListItem_t, can be shorter than a ListItem_t. Thus, `( pxConstList )->pxIndex` is a `ListItem_t *` that extends past the end of the `List_t` whose `xListEnd` it points to. This is fixed by accessing `pxNext` through a `MiniListItem_t` instead. * move the prototype for vApplicationIdleHook to task.h. (#600) Co-authored-by: pluess <pluess@faulhorn.mw.iap.unibe.ch> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update equal priority task preemption (#603) * vTaskResume and vTaskPrioritySet don't preempt equal priority task * Update vTaskResumeAll not to preempt task with equal priority * Fix in xTaskResumeFromISR * Update FreeRTOS/FreeRTOS build checks (#613) This is needed to be compatible with the refactoring done in this PR - https://github.com/FreeRTOS/FreeRTOS/pull/889 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add ulTaskGetRunTimeCounter and ulTaskGetRunTimePercent (#611) Allow ulTaskGetIdleRunTimeCounter and ulTaskGetIdleRunTimePercent to be used whenever configGENERATE_RUN_TIME_STATS is enabled, as this is the only requirement for these functions to work. * Fix some CMake documentation typos (#616) The quick start instructions for CMake mention the "master" git branch which has been replaced by "main" in the current repo. The main CMakeLists.txt documents how to integrate a custom port. Fix a typo in the suggested CMake code. * Added support of 64bit events. (#597) * Added support of 64bit even Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Added missing brackets Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Made proper name for tick macro. Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Improved macro evaluation Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Fixed missed port files + documentation Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Changes made on PR Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Fix macro definition. Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Formatted code with uncrustify Signed-off-by: Cervenka Dusan <cervenka@acrios.com> --------- Signed-off-by: Cervenka Dusan <cervenka@acrios.com> * Introduce portMEMORY_BARRIER for Microblaze port. (#621) The introduction of `portMEMORY_BARRIER` will ensure the places in the kernel use a barrier will work. For example, `xTaskResumeAll` has a memory barrier to ensure its correctness when compiled with optimization enabled. Without the barrier `xTaskResumeAll` can fail (e.g. start reading and writing to address 0 and/or infinite looping) when `xPendingReadyList` contains more than one task to restore. In `xTaskResumeAll` the compiler chooses to cache the `pxTCB` the first time through the loop for use in every subsequent loop. This is incorrect as the removal of `pxTCB->xEventListItem` will actually change the value of `pxTCB` if it was read again at the top of the loop. The barrier forces the compiler to read `pxTCB` again at the top of the loop. The compiler is operating correctly. The removal `pxTCB->xEventListItem` executes on a `List_t *` and `ListItem_t *`. This means that the compiler can assume that any `MiniListItem_t` values are unchanged by the loop (i.e. "strict-aliasing"). This allows the compiler to cache `pxTCB` as it is obtained via a `MiniListItem_t`. This is incorrect in this case because it is possible for a `ListItem_t *` to actually alias a `MiniListItem_t`. This is technically a "violation of aliasing rules" so we use the the barrier to disable the strict-aliasing optimization in this loop. * Do not call exit() on MSVC Port when calling vPortEndScheduler (#624) * make port exitable * correctly set xPortRunning to False * add suggestions from Review Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * add suggestions from Review Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update PR template to include checkbox for Unit Test related changes (#627) * Fix build failure introduced in PR #597 (#629) The PR #597 introduced a new config option configTICK_TYPE_WIDTH_IN_BITS which can be defined to one of the following: * TICK_TYPE_WIDTH_16_BITS - Tick type is 16 bit wide. * TICK_TYPE_WIDTH_32_BITS - Tick type is 32 bit wide. * TICK_TYPE_WIDTH_64_BITS - Tick type is 64 bit wide. Earlier we supported 16 and 32 bit width for tick type which was controlled using the config option configUSE_16_BIT_TICKS. The PR tried to maintain backward compatibility by honoring configUSE_16_BIT_TICKS. The backward compatibility did not work as expected though, as the macro configTICK_TYPE_WIDTH_IN_BITS was used before it was defined. This PR addresses it by ensuring that the macro configTICK_TYPE_WIDTH_IN_BITS is defined before it is used. Testing 1. configUSE_16_BIT_TICKS is defined to 0. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 109e: 4b50 ldr r3, [pc, #320] ; (11e0 <xTaskIncrementTick+0x150>) 10a0: f8d3 4134 ldr.w r4, [r3, #308] ; 0x134 10a4: 3401 adds r4, #1 10a6: f8c3 4134 str.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 32 bit. 2. configUSE_16_BIT_TICKS is defined to 1. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 10e2: 4b53 ldr r3, [pc, #332] ; (1230 <xTaskIncrementTick+0x15c>) 10e4: f8b3 4134 ldrh.w r4, [r3, #308] ; 0x134 10e8: b2a4 uxth r4, r4 10ea: 3401 adds r4, #1 10ec: b2a4 uxth r4, r4 10ee: f8a3 4134 strh.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 16 bit. 3. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_16_BITS. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 10e2: 4b53 ldr r3, [pc, #332] ; (1230 <xTaskIncrementTick+0x15c>) 10e4: f8b3 4134 ldrh.w r4, [r3, #308] ; 0x134 10e8: b2a4 uxth r4, r4 10ea: 3401 adds r4, #1 10ec: b2a4 uxth r4, r4 10ee: f8a3 4134 strh.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 16 bit. 4. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_32_BITS. Source (function xTaskIncrementTick in tasks.c): ``` const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; ``` Assembly: ``` 109e: 4b50 ldr r3, [pc, #320] ; (11e0 <xTaskIncrementTick+0x150>) 10a0: f8d3 4134 ldr.w r4, [r3, #308] ; 0x134 10a4: 3401 adds r4, #1 10a6: f8c3 4134 str.w r4, [r3, #308] ; 0x134 ``` It is clear from assembly that the tick type is 32 bit. 5. configTICK_TYPE_WIDTH_IN_BITS is defined to TICK_TYPE_WIDTH_64_BITS. ``` #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. ``` The testing was done for GCC/ARM_CM3 port which does not support 64 bit tick type. 6. Neither configUSE_16_BIT_TICKS nor configTICK_TYPE_WIDTH_IN_BITS defined. ``` #error Missing definition: One of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. ``` 7. Both configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS defined. ``` #error Only one of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. ``` Related issue - https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/628 Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Feature/fixing clang gnu compiler warnings (#620) * Adding in ability to support a library for freertos_config and a custom freertos_kernel_port (#558) * Using single name definition for libraries everywhere. (#558) * Supporting backwards compatibility with FREERTOS_CONFIG_FILE_DIRECTORY (#571) * Removing compiler warnings for GNU and Clang. (#571) * Added in documentation on how to consume from a main project. Added default PORT selection for native POSIX and MINGW platforms. * Only adding freertos_config if it exists. Removing auto generation of it from a FREERTOS_CONFIG_FILE_DIRECTORY. * Fixing clang and gnu compiler warnings. * Adding in project information and how to compile for GNU/clang * Fixing compiler issue with unused variable - no need to declare variable. * Adding in compile warnings for linux builds that kernel is okay with using. * Fixing more extra-semi-stmt clang warnings. * Moving definition of hooks into header files if features are enabled. * Fixing formatting with uncrustify. * Fixing merge conflicts with main merge. * Fixing compiler errors due to merge issues and formatting. * Fixing Line feeds. * Adding 'portNORETURN' into portmacros.h. Other Updates based on PR request * Further clean-up of clang and clang-tidy issues. * Removing compiler specific pragmas from common c files. * Fixing missing lexicon entry and uncrustify formatting changes. * Resolving merge issue multiple defnitions of proto for prvIdleTask * Fixing formatting issues that are not covered by uncrustify. Use clang-tidy instead if you want this level of control. * More uncrustify formatting issues. * Fixing extra bracket in #if statement. --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * POSIX port fixes (#626) * Fix types in POSIX port Use TaskFunction_t and StackType_t as other ports do. * Fix portTICK_RATE_MICROSECONDS in POSIX port --------- Co-authored-by: Jacques GUILLOU <jacques.guillou.job@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Cortex-M35P: Add Cortex-M35P port (#631) * Cortex-M35P: Add Cortex-M35P port The Cortex-M35P support added to kernel. The port hasn't been validated yet with TF-M. Hence TF-M support is not included in this port. Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> * Add portNORETURN to the newly added portmacro.h Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> * Introduced Github Status Badge for Unit Tests (#634) * Introduced Github Status Badge for Unit Tests * Github status badge to point to latest run * Github status badge UT points to latest results * Fixed URL for Github Status badge --------- Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> * Remove C99 requirement from CMake file (#633) * Remove C99 requirement from CMake file The kernel source is C89 compliant and does not need C99. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Explicitly set C89 requirement for kernel Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add Thread Local Storage (TLS) support using Picolibc functions (#343) * Pass top of stack to configINIT_TLS_BLOCK Picolibc wants to allocate the per-task TLS block within the stack segment, so it will need to modify the top of stack value. Pass the pxTopOfStack variable to make this explicit. Signed-off-by: Keith Packard <keithpac@amazon.com> * Move newlib-specific definitions to separate file This reduces the clutter in FreeRTOS.h caused by having newlib-specific macros present there. Signed-off-by: Keith Packard <keithpac@amazon.com> * Make TLS code depend only on configUSE_C_RUNTIME_TLS_SUPPORT Remove reference to configUSE_NEWLIB_REENTRANT as that only works when using newlib. configUSE_C_RUNTIME_TLS_SUPPORT is always set when configUSE_NEWLIB_REENTRANT is set, so using both was redundant in that case. Signed-off-by: Keith Packard <keithpac@amazon.com> * portable-ARC: Adapt ARC support to use generalized TLS support With generalized thread local storage (TLS) support present in the core, the two ARC ports need to have the changes to the TCB mirrored to them. Signed-off-by: Keith Packard <keithpac@amazon.com> * Add Thread Local Storage (TLS) support using Picolibc functions This patch provides definitions of the general TLS support macros in terms of the Picolibc TLS support functions. Picolibc is normally configured to use TLS internally for all variables that are intended to be task-local, so these changes are necessary for picolibc to work correctly with FreeRTOS. The picolibc helper functions rely on elements within the linker script to arrange the TLS data in memory and define some symbols. Applications wanting to use this mechanism will need changes in their linker script when migrating to picolibc. Signed-off-by: Keith Packard <keithpac@amazon.com> --------- Signed-off-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Interrupt priority assert improvements for CM3/4/7 (#602) * Interrupt priority assert improvements for CM3/4/7 In the ARM_CM3, ARM_CM4, and ARM_CM7 ports, change the assertion that `configMAX_SYSCALL_INTERRUPT_PRIORITY` is nonzero to account for the number of priority bits implemented by the hardware. Change these ports to also use the lowest priority for PendSV and SysTick, ignoring `configKERNEL_INTERRUPT_PRIORITY`. * Remove not needed configKERNEL_INTERRUPT_PRIORITY define Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Introduced code coverage status badge (#635) * Introduced code coverage status badge * Trying to fix the URL checker issue * Fix URL check Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * added portPOINTER_SIZE_TYPE and SIZE_MAX definition to PIC24/dsPIC port (#636) * added portPOINTER_SIZE_TYPE definition to PIC24/dsPIC port * Added SIZE_MAX definition to PIC24/dsPIC33 * Fix TLS and stack alignment when using picolibc (#637) Both the TLS block and stack must be correctly aligned when using picolibc. The architecture stack alignment is represented by the portBYTE_ALIGNMENT_MASK and the TLS block alignment is provided by the Picolibc _tls_align() inline function for Picolibc version 1.8 and above. For older versions of Picolibc, we'll assume that the TLS block requires the same alignment as the stack. For downward growing stacks, this requires aligning the start of the TLS block to the maximum of the stack alignment and the TLS alignment. With this, both the TLS block and stack will now be correctly aligned. For upward growing stacks, the two areas must be aligned independently; the TLS block is aligned from the start of the stack, then the tls space is allocated, and then the stack is aligned above that. It's probably useful to know here that the linker ensures that variables within the TLS block are assigned offsets that match their alignment requirements. If the TLS block itself is correctly aligned, then everything within will also be. I have only tested the downward growing stack branch of this patch. Signed-off-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Enable building the GCC Cortex-R5 port without an FPU (#586) * Ensure configUSE_TASK_FPU_SUPPORT option is set correctly If one does enable the FPU of the Cortex-R5 processor, then the GCC compiler will define the macro __ARM_FP. This can be used to ensure, that the configUSE_TASK_FPU_SUPPORT is set accordingly. * Enable the implementation of vPortTaskUsesFPU only if configUSE_TASK_FPU_SUPPORT is set to 1 * Remove error case in pxPortInitialiseStack The case of configUSE_TASK_FPU_SUPPORT is 0 is now handled * Enable access to FPU registers only if FPU is enabled * Make minor formating changes * Format ARM Cortex-R5 port * Address review comments from @ChristosZosi * Minor code review suggestions Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Fix freertos_kernel cmake property, Posix Port (#640) * Fix freertos_kernel cmake property, Posix Port * Moves the `set_property()` call below the target definition in top level CMakeLists file * Corrects billion value from `ULL` suffix (not C90 compliant) to `UL` suffix with cast to uint64_t * Add blank line to CMakeLists.txt * Add missing FreeRTOS+ defines * Run kernel demos and unit tests for PR changes (#645) * Run kernel demos and unit tests for PR changes Kernel demos check builds multiple demos from FreeRTOS/FreeRTOS and unit tests check runs unit tests in FreeRTOS/FreeRTOS. Both of these checks currently use main branch of FreeRTOS-Kernel. This commits updates these checks to use the changes in the PR. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Do not specify PR SHA explicitly as that is default Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Remove explicit PR SHA from kernel checks Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Add functions to get the buffers of statically created objects (#641) Added various ...GetStaticBuffer() functions to get the buffers of statically created objects. --------- Co-authored-by: Paul Bartell <pbartell@amazon.com> Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> * Cortex-M Assert when NVIC implements 8 PRIO bits (#639) * Cortex-M Assert when NVIC implements 8 PRIO bits * Fix CM3 ports * Fix ARM_CM3_MPU * Fix ARM CM3 * Fix ARM_CM4_MPU * Fix ARM_CM4 * Fix GCC ARM_CM7 * Fix IAR ARM ports * Uncrustify changes * Fix MikroC_ARM_CM4F port * Fix MikroC_ARM_CM4F port-(2) * Fix RVDS ARM ports * Revert changes for Tasking/ARM_CM4F port * Revert changes for Tasking/ARM_CM4F port-(2) * Update port.c Fix GCC/ARM_CM4F port * Update port.c * update GCC\ARM_CM4F port * update port.c * Assert to check configMAX_SYSCALL_INTERRUPT_PRIORITY is set to higher priority * Fix merge error: remove duplicate code * Fix typos --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-17-174.ec2.internal> * Remove C90 requirement from CMakeLists (#649) This is needed as it is breaking projects - https://forums.freertos.org/t/freertos-gcc-cmake/16984 We will re-evaluate and accordingly add this later. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Only add alignment padding when needed (#650) Heap 4 and Heap 5 add some padding to ensure that the allocated blocks are always aligned to portBYTE_ALIGNMENT bytes. The code until now was adding padding always even if the resulting block was already aligned. This commits updates the code to only add padding if the resulting block is not aligned. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * add a missing comma (#651) * fix conversion warning (#658) FreeRTOS-Kernel/portable/GCC/ARM_CM4F/port.c:399:41: error: conversion from 'uint32_t' {aka 'long unsigned int'} to 'uint8_t' {aka 'unsigned char'} may change value [-Werror=conversion] Signed-off-by: Vo Trung Chi <chi.votrung@vn.bosch.com> * ARMv7M: Adjust implemented priority bit assertions (#665) Adjust assertions related to the CMSIS __NVIC_PRIO_BITS and FreeRTOS configPRIO_BITS configuration macros such that these macros specify the minimum number of implemented priority bits supported by a config build rather than the exact number of implemented priority bits. Related to Qemu issue #1122 * Format portmacro.h in arm CM0 ports * portable/ARM_CM0: Add xPortIsInsideInterrupt Add missing xPortIsInsideInterrupt function to Cortex-M0 port. * tree-wide: Unify formatting of __cplusplus ifdefs * Paranthesize expression-like macro (#668) * Updated tasks.c checks for scheduler suspension (#670) This commit updates the checks for the variable uxSchedulerSuspended in tasks.c module to use a uniform format. Signed-off-by: Sudeep Mohanty <sudp.mohanty@gmail.com> * Fix cast alignment warning (#669) * Fix cast alignment warning Without this change, the code produces the following warning when compiled with `-Wcast-align` flag: ``` cast increases required alignment of target type ``` Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Align StackSize and StackAddress for macOS (#674) * Armv8-M (except Cortex-M23) interrupt priority checking (#673) * Armv8-M: Formatting changes Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> * Armv8-M: Add support for interrupt priority check FreeRTOS provides `FromISR` system calls which can be called directly from interrupt service routines. It is crucial that the priority of these ISRs is set to same or lower value (numerically higher) than that of `configMAX_SYSCALL_INTERRUPT_PRIORITY`. For more information refer to https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. Add a check to trigger an assert when an ISR with priority higher (numerically lower) than `configMAX_SYSCALL_INTERRUPT_PRIORITY` calls `FromISR` system calls if `configASSERT` macro is defined. In addition, add a config option `configQEMU_DISABLE_INTERRUPT_PRIO_BITS_CHECK` to disable interrupt priority check while running on QEMU. Based on the discussion https://gitlab.com/qemu-project/qemu/-/issues/1122, The interrupt priority bits in QEMU do not match the real hardware. Therefore the assert that checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. The config option `configQEMU_DISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the `FreeRTOSConfig.h` for QEMU targets. Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> * Use SHPR2 for calculating interrupt priority bits This removes the dependency on the secure software to mark the interrupt as non-secure. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Use the extended movx instruction instead of mov (#676) The following is from the MSP430X instruction set - ``` MOVX.W Move source word to destination word. The source operand is copied to the destination. The source operand is not affected. Both operands may be located in the full address space. ``` The movx instruction allows both the operands to be located in the full address space and therefore, works with large data model as well. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Fix eTaskGetState for pending ready tasks (#679) This commit fixes eTaskGetState so that eReady is returned for pending ready tasks. Co-authored-by: Darian Leung <darian@espressif.com> * Generates SBOM after source files are updated with release tag (#680) * update source file with release version info before SBOM generation * delete tag branch during cleanup * Add back croutines by reverting PR#590 (#685) * Add croutines to the code base * Add croutine changes to cmake, lexicon and readme * Add croutine file to portable cmake file * Add back more references from PR 591 * Remove __NVIC_PRIO_BITS and configPRIO_BITS check in port (#683) * Remove __NVIC_PRIO_BITS and configPRIO_BITS check in CM3, CM4 and ARMv8. * Add hardware not implemented bits check. These bits should be zero. --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Use UBaseType_t as interrupt mask (#689) * Use UBaseType_t as interrupt mask * Update GCC posix port to use UBaseType_t as interrupt mask * Fix clang warning in croutine and stream buffer (#686) * Fix document warning in croutine * Fix cast-qual warning in stream buffer * Use portTASK_FUNCTION_PROTO to replace portNORETURN (#688) * Use portTASK_FUNCTION_PROTO to replace portNORETURN * Fix typo in check comment of configMAX_SYSCALL_INTERRUPT_PRIORITY (#690) * Add constant type for portMAX_DELAY in port (#691) Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update static stream buffer size check (#693) * Use volatile size instead of sizeof directly to prevent always true/false warning * Fix typos in comments for the AT91SAM7S port (#695) Co-authored-by: RichardBarry <3073890+RichardBarry@users.noreply.github.com> * Fix #697: Missing portPOINTER_SIZE_TYPE definition for ATmega port (#698) * Remove empty expression statement compiler warning (#692) * Add do while( 0 ) loop for empty expression statement compiler warning * Update uxTaskGetSystemState for tasks in pending ready list (#702) * Update uxTaskGetSystemState to sync with eTaskGetState * Update in vTaskGetInfo for tasks in pending ready list should be in ready state. * Fix circular dependency in CMake project (#700) * Fix circular dependency in cmake project Fix for https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/687 In order for custom ports to also break the cycle, they must link against freertos_kernel_include instead of freertos_kernel. * Simplify include path * Memory Protection Unit (MPU) Enhancements (#705) Memory Protection Unit (MPU) Enhancements This commit introduces a new MPU wrapper that places additional restrictions on unprivileged tasks. The following is the list of changes introduced with the new MPU wrapper: 1. Opaque and indirectly verifiable integers for kernel object handles: All the kernel object handles (for example, queue handles) are now opaque integers. Previously object handles were raw pointers. 2. Saving the task context in Task Control Block (TCB): When a task is swapped out by the scheduler, the task's context is now saved in its TCB. Previously the task's context was saved on its stack. 3. Execute system calls on a separate privileged only stack: FreeRTOS system calls, which execute with elevated privilege, now use a separate privileged only stack. Previously system calls used the calling task's stack. The application writer can control the size of the system call stack using new configSYSTEM_CALL_STACK_SIZE config macro. 4. Memory bounds checks: FreeRTOS system calls which accept a pointer and de-reference it, now verify that the calling task has required permissions to access the memory location referenced by the pointer. 5. System call restrictions: The following system calls are no longer available to unprivileged tasks: - vQueueDelete - xQueueCreateMutex - xQueueCreateMutexStatic - xQueueCreateCountingSemaphore - xQueueCreateCountingSemaphoreStatic - xQueueGenericCreate - xQueueGenericCreateStatic - xQueueCreateSet - xQueueRemoveFromSet - xQueueGenericReset - xTaskCreate - xTaskCreateStatic - vTaskDelete - vTaskPrioritySet - vTaskSuspendAll - xTaskResumeAll - xTaskGetHandle - xTaskCallApplicationTaskHook - vTaskList - vTaskGetRunTimeStats - xTaskCatchUpTicks - xEventGroupCreate - xEventGroupCreateStatic - vEventGroupDelete - xStreamBufferGenericCreate - xStreamBufferGenericCreateStatic - vStreamBufferDelete - xStreamBufferReset Also, an unprivileged task can no longer use vTaskSuspend to suspend any task other than itself. We thank the following people for their inputs in these enhancements: - David Reiss of Meta Platforms, Inc. - Lan Luo, Xinhui Shao, Yumeng Wei, Zixia Liu, Huaiyu Yan and Zhen Ling of School of Computer Science and Engineering, Southeast University, China. - Xinwen Fu of Department of Computer Science, University of Massachusetts Lowell, USA. - Yuequi Chen, Zicheng Wang, Minghao Lin of University of Colorado Boulder, USA. * Update History for Version 10.6.0 (#706) Signed-off-by: kar-rahul-aws <karahulx@amazon.com> * Fixed compile options polluting project (#694) * Fixed compile options polluting project Moved add_library higher * Apply suggestions from code review Co-authored-by: Paul Bartell <paul.bartell@gmail.com> * fixed cmakelists keeping in mind the suggestions --------- Co-authored-by: Paul Bartell <paul.bartell@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Fix the comments in the CM3 and CM4 MPU Ports about the MPU Region numbers being loaded (#707) Co-authored-by: Soren Ptak <skptak@amazon.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Update xSemaphoreGetStaticBuffer prototype in comment (#704) Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> * Correct the misspelled name (#708) Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Cervenka Dusan <cervenka@acrios.com> Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Keith Packard <keithpac@amazon.com> Signed-off-by: Vo Trung Chi <chi.votrung@vn.bosch.com> Signed-off-by: Sudeep Mohanty <sudp.mohanty@gmail.com> Signed-off-by: kar-rahul-aws <karahulx@amazon.com> Co-authored-by: Archit Gupta <71798289+archigup@users.noreply.github.com> Co-authored-by: tcpluess <tpluess@ieee.org> Co-authored-by: pluess <pluess@faulhorn.mw.iap.unibe.ch> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Chris Copeland <chris@chrisnc.net> Co-authored-by: David J. Fiddes <35607151+davefiddes@users.noreply.github.com> Co-authored-by: Dusan Cervenka <cervenka@acrios.com> Co-authored-by: bbain <16752579+bbain@users.noreply.github.com> Co-authored-by: Ju1He1 <93189163+Ju1He1@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: phelter <paulheltera@gmail.com> Co-authored-by: jacky309 <jacques.guillou@gmail.com> Co-authored-by: Jacques GUILLOU <jacques.guillou.job@gmail.com> Co-authored-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com> Co-authored-by: Keith Packard <keithp@keithp.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Joseph Julicher <jjulicher@mac.com> Co-authored-by: Paul Bartell <pbartell@amazon.com> Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com> Co-authored-by: Kody Stribrny <89810515+kstribrnAmzn@users.noreply.github.com> Co-authored-by: Holden <holden-zenithaerotech.com> Co-authored-by: Darian <32921628+Dazza0@users.noreply.github.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-17-174.ec2.internal> Co-authored-by: Nicolas <nicolas.brunner@heig-vd.ch> Co-authored-by: Vo Trung Chi <chi.votrung@vn.bosch.com> Co-authored-by: Sudeep Mohanty <91244425+sudeep-mohanty@users.noreply.github.com> Co-authored-by: Monika Singh <108652024+moninom1@users.noreply.github.com> Co-authored-by: Darian Leung <darian@espressif.com> Co-authored-by: Tony Josi <tonyjosi@amazon.com> Co-authored-by: Evgeny Ermakov <22344340+unspecd@users.noreply.github.com> Co-authored-by: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Co-authored-by: Joris Putcuyps <joris.putcuyps@gmail.com> Co-authored-by: Patrick Cook <114708437+cookpate@users.noreply.github.com> Co-authored-by: Mr. Jake <norbertzpilicy@gmail.com> Co-authored-by: Paul Bartell <paul.bartell@gmail.com> Co-authored-by: Soren Ptak <Skptak@outlook.com> Co-authored-by: Soren Ptak <skptak@amazon.com> * Move default configNUMBER_OF_CORES definition forward in FreeRTOSConfig.h (#88) * Move default configNUMBER_OF_CORES definition forward in FreeRTOSConfig.h. --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Signed-off-by: Xinyu Zhang <xinyu.zhang@arm.com> Signed-off-by: Gabor Toth <gabor.toth@arm.com> Signed-off-by: Cristian Cristea <cristiancristea00@gmail.com> Signed-off-by: Cervenka Dusan <cervenka@acrios.com> Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Signed-off-by: Keith Packard <keithpac@amazon.com> Signed-off-by: Vo Trung Chi <chi.votrung@vn.bosch.com> Signed-off-by: Sudeep Mohanty <sudp.mohanty@gmail.com> Signed-off-by: kar-rahul-aws <karahulx@amazon.com> Co-authored-by: alfred gedeon <28123637+alfred2g@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: AndreiCherniaev <dungeonlords789@yandex.ru> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Tanmoy Sen <33438891+tanmoysen@users.noreply.github.com> Co-authored-by: Ravishankar Bhagavandas <bhagavar@amazon.com> Co-authored-by: eddie9712 <qw1562435@gmail.com> Co-authored-by: Graham Sanderson <graham.sanderson@raspberrypi.com> Co-authored-by: graham sanderson <graham.sanderson@raspeberryi.com> Co-authored-by: Xinyu Zhang <68640626+xinyu-tfm@users.noreply.github.com> Co-authored-by: Paul Bartell <pbartell@amazon.com> Co-authored-by: Joseph Julicher <jjulicher@mac.com> Co-authored-by: NomiChirps <70026509+NomiChirps@users.noreply.github.com> Co-authored-by: 0xjakob <18257824+0xjakob@users.noreply.github.com> Co-authored-by: Jakob Hasse <0xjakob@users.noreply.github.com> Co-authored-by: Xin Lin <47510956+xlin7799@users.noreply.github.com> Co-authored-by: Patrick Oppenlander <patrick.oppenlander@gmail.com> Co-authored-by: Gavin Lambert <uecasm@users.noreply.github.com> Co-authored-by: Chris Copeland <chris@chrisnc.net> Co-authored-by: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Co-authored-by: Paul Bartell <paul.bartell@gmail.com> Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Archit Gupta <71798289+archigup@users.noreply.github.com> Co-authored-by: Monika Singh <108652024+moninom1@users.noreply.github.com> Co-authored-by: Octaviarius <gomanchuk.as@gmail.com> Co-authored-by: Jakub Lužný <jakub@luzny.cz> Co-authored-by: newbrain <17814222+newbrain@users.noreply.github.com> Co-authored-by: Gabor Toth <gabor.toth@arm.com> Co-authored-by: Ming Yue <mingyue86010@gmail.com> Co-authored-by: David Chalco <david@chalco.io> Co-authored-by: Cristian Cristea <cristiancristea00@gmail.com> Co-authored-by: Jeff Tenney <jeff.tenney@gmail.com> Co-authored-by: Cobus van Eeden <35851496+cobusve@users.noreply.github.com> Co-authored-by: abhidixi11 <44424462+abhidixi11@users.noreply.github.com> Co-authored-by: Laukik Hase <laukik.hase@espressif.com> Co-authored-by: arshi016 <arshilife16@gmail.com> Co-authored-by: Niklas Gürtler <Erlkoenig90@users.noreply.github.com> Co-authored-by: Niklas Gürtler <niklas.guertler@tacterion.com> Co-authored-by: Hardy Griech <ntbox@gmx.net> Co-authored-by: Darian <32921628+Dazza0@users.noreply.github.com> Co-authored-by: tcpluess <tpluess@ieee.org> Co-authored-by: pluess <pluess@faulhorn.mw.iap.unibe.ch> Co-authored-by: David J. Fiddes <35607151+davefiddes@users.noreply.github.com> Co-authored-by: Dusan Cervenka <cervenka@acrios.com> Co-authored-by: bbain <16752579+bbain@users.noreply.github.com> Co-authored-by: Ju1He1 <93189163+Ju1He1@users.noreply.github.com> Co-authored-by: phelter <paulheltera@gmail.com> Co-authored-by: jacky309 <jacques.guillou@gmail.com> Co-authored-by: Jacques GUILLOU <jacques.guillou.job@gmail.com> Co-authored-by: Devaraj Ranganna <devaraj.ranganna@arm.com> Co-authored-by: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com> Co-authored-by: Keith Packard <keithp@keithp.com> Co-authored-by: Keith Packard <keithpac@amazon.com> Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com> Co-authored-by: Kody Stribrny <89810515+kstribrnAmzn@users.noreply.github.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-17-174.ec2.internal> Co-authored-by: Nicolas <nicolas.brunner@heig-vd.ch> Co-authored-by: Vo Trung Chi <chi.votrung@vn.bosch.com> Co-authored-by: Sudeep Mohanty <91244425+sudeep-mohanty@users.noreply.github.com> Co-authored-by: Darian Leung <darian@espressif.com> Co-authored-by: Tony Josi <tonyjosi@amazon.com> Co-authored-by: Evgeny Ermakov <22344340+unspecd@users.noreply.github.com> Co-authored-by: Joris Putcuyps <joris.putcuyps@gmail.com> Co-authored-by: Patrick Cook <114708437+cookpate@users.noreply.github.com> Co-authored-by: Mr. Jake <norbertzpilicy@gmail.com> Co-authored-by: Soren Ptak <Skptak@outlook.com> Co-authored-by: Soren Ptak <skptak@amazon.com>
7666 lines
304 KiB
C
7666 lines
304 KiB
C
/*
|
|
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
|
* Copyright (C) 2021 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
|
|
*
|
|
*/
|
|
|
|
/* Standard includes. */
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
/* 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. */
|
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
|
|
|
/* FreeRTOS includes. */
|
|
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
#include "timers.h"
|
|
#include "stack_macros.h"
|
|
|
|
/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified
|
|
* because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
|
|
* for the header files above, but not in this file, in order to generate the
|
|
* correct privileged Vs unprivileged linkage and placement. */
|
|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */
|
|
|
|
/* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting
|
|
* functions but without including stdio.h here. */
|
|
#if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
|
|
|
|
/* At the bottom of this file are two optional functions that can be used
|
|
* to generate human readable text from the raw data generated by the
|
|
* uxTaskGetSystemState() function. Note the formatting functions are provided
|
|
* for convenience only, and are NOT considered part of the kernel. */
|
|
#include <stdio.h>
|
|
#endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
#if ( configUSE_PREEMPTION == 0 )
|
|
|
|
/* If the cooperative scheduler is being used then a yield should not be
|
|
* performed just because a higher priority task has been woken. */
|
|
#define taskYIELD_IF_USING_PREEMPTION()
|
|
#else
|
|
#define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
|
|
#endif
|
|
#endif /* if ( configNUMBER_OF_CORES == 1 ) */
|
|
|
|
/* Values that can be assigned to the ucNotifyState member of the TCB. */
|
|
#define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) /* Must be zero as it is the initialised value. */
|
|
#define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 )
|
|
#define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 )
|
|
|
|
/*
|
|
* The value used to fill the stack of a task when the task is created. This
|
|
* is used purely for checking the high water mark for tasks.
|
|
*/
|
|
#define tskSTACK_FILL_BYTE ( 0xa5U )
|
|
|
|
/* Bits used to record how a task's stack and TCB were allocated. */
|
|
#define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 )
|
|
#define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 )
|
|
#define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 )
|
|
|
|
/* If any of the following are set then task stacks are filled with a known
|
|
* value so the high water mark can be determined. If none of the following are
|
|
* set then don't fill the stack so there is no unnecessary dependency on memset. */
|
|
#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
|
|
#define tskSET_NEW_STACKS_TO_KNOWN_VALUE 1
|
|
#else
|
|
#define tskSET_NEW_STACKS_TO_KNOWN_VALUE 0
|
|
#endif
|
|
|
|
/*
|
|
* Macros used by vListTask to indicate which state a task is in.
|
|
*/
|
|
#define tskRUNNING_CHAR ( 'X' )
|
|
#define tskBLOCKED_CHAR ( 'B' )
|
|
#define tskREADY_CHAR ( 'R' )
|
|
#define tskDELETED_CHAR ( 'D' )
|
|
#define tskSUSPENDED_CHAR ( 'S' )
|
|
|
|
/*
|
|
* Some kernel aware debuggers require the data the debugger needs access to to
|
|
* be global, rather than file scope.
|
|
*/
|
|
#ifdef portREMOVE_STATIC_QUALIFIER
|
|
#define static
|
|
#endif
|
|
|
|
/* The name allocated to the Idle task. This can be overridden by defining
|
|
* configIDLE_TASK_NAME in FreeRTOSConfig.h. */
|
|
#ifndef configIDLE_TASK_NAME
|
|
#define configIDLE_TASK_NAME "IDLE"
|
|
#endif
|
|
|
|
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
|
|
|
|
/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
|
|
* performed in a generic way that is not optimised to any particular
|
|
* microcontroller architecture. */
|
|
|
|
/* uxTopReadyPriority holds the priority of the highest priority ready
|
|
* state task. */
|
|
#define taskRECORD_READY_PRIORITY( uxPriority ) \
|
|
do { \
|
|
if( ( uxPriority ) > uxTopReadyPriority ) \
|
|
{ \
|
|
uxTopReadyPriority = ( uxPriority ); \
|
|
} \
|
|
} while( 0 ) /* taskRECORD_READY_PRIORITY */
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
|
|
do { \
|
|
UBaseType_t uxTopPriority = uxTopReadyPriority; \
|
|
\
|
|
/* Find the highest priority queue that contains ready tasks. */ \
|
|
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
|
|
{ \
|
|
configASSERT( uxTopPriority ); \
|
|
--uxTopPriority; \
|
|
} \
|
|
\
|
|
/* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
|
|
* the same priority get an equal share of the processor time. */ \
|
|
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
|
|
uxTopReadyPriority = uxTopPriority; \
|
|
} while( 0 ) /* taskSELECT_HIGHEST_PRIORITY_TASK */
|
|
#endif /* if ( configNUMBER_OF_CORES == 1 ) */
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
|
|
* they are only required when a port optimised method of task selection is
|
|
* being used. */
|
|
#define taskRESET_READY_PRIORITY( uxPriority )
|
|
#define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
|
|
|
|
#else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
#error configUSE_PORT_OPTIMISED_TASK_SELECTION not supported in FreeRTOS SMP.
|
|
#endif
|
|
|
|
/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
|
|
* performed in a way that is tailored to the particular microcontroller
|
|
* architecture being used. */
|
|
|
|
/* A port optimised version is provided. Call the port defined macros. */
|
|
#define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( ( uxPriority ), uxTopReadyPriority )
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
|
|
do { \
|
|
UBaseType_t uxTopPriority; \
|
|
\
|
|
/* Find the highest priority list that contains ready tasks. */ \
|
|
portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
|
|
configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
|
|
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
|
|
} while( 0 )
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* A port optimised version is provided, call it only if the TCB being reset
|
|
* is being referenced from a ready list. If it is referenced from a delayed
|
|
* or suspended list then it won't be in a ready list. */
|
|
#define taskRESET_READY_PRIORITY( uxPriority ) \
|
|
do { \
|
|
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
|
|
{ \
|
|
portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
|
|
} \
|
|
} while( 0 )
|
|
|
|
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
|
|
* count overflows. */
|
|
#define taskSWITCH_DELAYED_LISTS() \
|
|
do { \
|
|
List_t * pxTemp; \
|
|
\
|
|
/* The delayed tasks list should be empty when the lists are switched. */ \
|
|
configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \
|
|
\
|
|
pxTemp = pxDelayedTaskList; \
|
|
pxDelayedTaskList = pxOverflowDelayedTaskList; \
|
|
pxOverflowDelayedTaskList = pxTemp; \
|
|
xNumOfOverflows++; \
|
|
prvResetNextTaskUnblockTime(); \
|
|
} while( 0 )
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*
|
|
* Place the task represented by pxTCB into the appropriate ready list for
|
|
* the task. It is inserted at the end of the list.
|
|
*/
|
|
#define prvAddTaskToReadyList( pxTCB ) \
|
|
do { \
|
|
traceMOVED_TASK_TO_READY_STATE( pxTCB ); \
|
|
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
|
|
listINSERT_END( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
|
|
tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ); \
|
|
} while( 0 )
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*
|
|
* Several functions take a TaskHandle_t parameter that can optionally be NULL,
|
|
* where NULL is used to indicate that the handle of the currently executing
|
|
* task should be used in place of the parameter. This macro simply checks to
|
|
* see if the parameter is NULL and returns a pointer to the appropriate TCB.
|
|
*/
|
|
#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? pxCurrentTCB : ( pxHandle ) )
|
|
|
|
/* The item value of the event list item is normally used to hold the priority
|
|
* of the task to which it belongs (coded to allow it to be held in reverse
|
|
* priority order). However, it is occasionally borrowed for other purposes. It
|
|
* is important its value is not updated due to a task priority change while it is
|
|
* being used for another purpose. The following bit definition is used to inform
|
|
* the scheduler that the value should not be changed - in which case it is the
|
|
* responsibility of whichever module is using the value to ensure it gets set back
|
|
* to its original value when it is released. */
|
|
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
|
#define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U
|
|
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
|
#define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL
|
|
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS )
|
|
#define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000000000000000ULL
|
|
#endif
|
|
|
|
/* Task state. */
|
|
typedef BaseType_t TaskRunning_t;
|
|
|
|
/* Indicates that the task is not actively running on any core. */
|
|
#define taskTASK_NOT_RUNNING ( TaskRunning_t ) ( -1 )
|
|
|
|
/* Indicates that the task is actively running but scheduled to yield. */
|
|
#define taskTASK_YIELDING ( TaskRunning_t ) ( -2 )
|
|
|
|
/* Returns pdTRUE if the task is actively running and not scheduled to yield. */
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
#define taskTASK_IS_RUNNING( pxTCB ) ( ( ( pxTCB ) == pxCurrentTCB ) ? ( pdTRUE ) : ( pdFALSE ) )
|
|
#else
|
|
#define taskTASK_IS_RUNNING( pxTCB ) ( ( ( ( pxTCB )->xTaskRunState >= ( BaseType_t ) 0 ) && ( ( pxTCB )->xTaskRunState < ( BaseType_t ) configNUMBER_OF_CORES ) ) ? ( pdTRUE ) : ( pdFALSE ) )
|
|
#endif
|
|
|
|
/* Indicates that the task is an Idle task. */
|
|
#define taskATTRIBUTE_IS_IDLE ( UBaseType_t ) ( 1UL << 0UL )
|
|
|
|
#if ( ( configNUMBER_OF_CORES > 1 ) && ( portCRITICAL_NESTING_IN_TCB == 1 ) )
|
|
#define portGET_CRITICAL_NESTING_COUNT() ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting )
|
|
#define portSET_CRITICAL_NESTING_COUNT( x ) ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting = ( x ) )
|
|
#define portINCREMENT_CRITICAL_NESTING_COUNT() ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting++ )
|
|
#define portDECREMENT_CRITICAL_NESTING_COUNT() ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting-- )
|
|
#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( portCRITICAL_NESTING_IN_TCB == 1 ) ) */
|
|
|
|
/* Code below here allows infinite loop controlling, especially for the infinite loop
|
|
* in idle task function (for example when performing unit tests). */
|
|
#ifndef INFINITE_LOOP
|
|
#define INFINITE_LOOP() 1
|
|
#endif
|
|
|
|
/*
|
|
* Task control block. A task control block (TCB) is allocated for each task,
|
|
* and stores task state information, including a pointer to the task's context
|
|
* (the task's run time environment, including register values)
|
|
*/
|
|
typedef struct tskTaskControlBlock /* The old naming convention is used to prevent breaking kernel aware debuggers. */
|
|
{
|
|
volatile StackType_t * pxTopOfStack; /**< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
|
|
|
|
#if ( portUSING_MPU_WRAPPERS == 1 )
|
|
xMPU_SETTINGS xMPUSettings; /**< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
|
|
#endif
|
|
|
|
#if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 )
|
|
UBaseType_t uxCoreAffinityMask; /*< Used to link the task to certain cores. UBaseType_t must have greater than or equal to the number of bits as confNUM_CORES. */
|
|
#endif
|
|
|
|
ListItem_t xStateListItem; /**< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
|
|
ListItem_t xEventListItem; /**< Used to reference a task from an event list. */
|
|
UBaseType_t uxPriority; /**< The priority of the task. 0 is the lowest priority. */
|
|
StackType_t * pxStack; /**< Points to the start of the stack. */
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
volatile TaskRunning_t xTaskRunState; /**< Used to identify the core the task is running on, if the task is running. Otherwise, identifies the task's state - not running or yielding. */
|
|
UBaseType_t uxTaskAttributes; /**< Task's attributes - currently used to identify the idle tasks. */
|
|
#endif
|
|
char pcTaskName[ configMAX_TASK_NAME_LEN ]; /**< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
|
|
|
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
|
|
BaseType_t xPreemptionDisable; /**< Used to prevent the task from being preempted. */
|
|
#endif
|
|
|
|
#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
|
|
StackType_t * pxEndOfStack; /**< Points to the highest valid address for the stack. */
|
|
#endif
|
|
|
|
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
|
UBaseType_t uxCriticalNesting; /**< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
|
|
#endif
|
|
|
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
|
UBaseType_t uxTCBNumber; /**< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
|
|
UBaseType_t uxTaskNumber; /**< Stores a number specifically for use by third party trace code. */
|
|
#endif
|
|
|
|
#if ( configUSE_MUTEXES == 1 )
|
|
UBaseType_t uxBasePriority; /**< The priority last assigned to the task - used by the priority inheritance mechanism. */
|
|
UBaseType_t uxMutexesHeld;
|
|
#endif
|
|
|
|
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
|
|
TaskHookFunction_t pxTaskTag;
|
|
#endif
|
|
|
|
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
|
|
void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
|
|
#endif
|
|
|
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /**< Stores the amount of time the task has spent in the Running state. */
|
|
#endif
|
|
|
|
#if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
|
|
configTLS_BLOCK_TYPE xTLSBlock; /**< Memory block used as Thread Local Storage (TLS) Block for the task. */
|
|
#endif
|
|
|
|
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
|
|
volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
|
|
volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
|
|
#endif
|
|
|
|
/* See the comments in FreeRTOS.h with the definition of
|
|
* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
|
|
#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
|
|
uint8_t ucStaticallyAllocated; /**< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
|
|
#endif
|
|
|
|
#if ( INCLUDE_xTaskAbortDelay == 1 )
|
|
uint8_t ucDelayAborted;
|
|
#endif
|
|
|
|
#if ( configUSE_POSIX_ERRNO == 1 )
|
|
int iTaskErrno;
|
|
#endif
|
|
} tskTCB;
|
|
|
|
/* The old tskTCB name is maintained above then typedefed to the new TCB_t name
|
|
* below to enable the use of older kernel aware debuggers. */
|
|
typedef tskTCB TCB_t;
|
|
|
|
/*lint -save -e956 A manual analysis and inspection has been used to determine
|
|
* which static variables must be declared volatile. */
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
|
|
#else
|
|
/* MISRA Ref 8.4.1 [Declaration shall be visible] */
|
|
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-84 */
|
|
/* coverity[misra_c_2012_rule_8_4_violation] */
|
|
portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCBs[ configNUMBER_OF_CORES ];
|
|
#define pxCurrentTCB xTaskGetCurrentTaskHandle()
|
|
#endif
|
|
|
|
/* Lists for ready and blocked tasks. --------------------
|
|
* xDelayedTaskList1 and xDelayedTaskList2 could be moved to function scope but
|
|
* doing so breaks some kernel aware debuggers and debuggers that rely on removing
|
|
* the static qualifier. */
|
|
PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; /**< Prioritised ready tasks. */
|
|
PRIVILEGED_DATA static List_t xDelayedTaskList1; /**< Delayed tasks. */
|
|
PRIVILEGED_DATA static List_t xDelayedTaskList2; /**< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
|
|
PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /**< Points to the delayed task list currently being used. */
|
|
PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /**< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
|
|
PRIVILEGED_DATA static List_t xPendingReadyList; /**< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */
|
|
|
|
#if ( INCLUDE_vTaskDelete == 1 )
|
|
|
|
PRIVILEGED_DATA static List_t xTasksWaitingTermination; /**< Tasks that have been deleted - but their memory not yet freed. */
|
|
PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
|
|
|
|
#endif
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
|
|
PRIVILEGED_DATA static List_t xSuspendedTaskList; /**< Tasks that are currently suspended. */
|
|
|
|
#endif
|
|
|
|
/* Global POSIX errno. Its value is changed upon context switching to match
|
|
* the errno of the currently running task. */
|
|
#if ( configUSE_POSIX_ERRNO == 1 )
|
|
int FreeRTOS_errno = 0;
|
|
#endif
|
|
|
|
/* Other file private variables. --------------------------------*/
|
|
PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
|
|
PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
|
|
PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
|
|
PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
|
|
PRIVILEGED_DATA static volatile TickType_t xPendedTicks = ( TickType_t ) 0U;
|
|
PRIVILEGED_DATA static volatile BaseType_t xYieldPendings[ configNUMBER_OF_CORES ] = { pdFALSE };
|
|
PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
|
|
PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
|
|
PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */
|
|
PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandles[ configNUMBER_OF_CORES ]; /**< Holds the handles of the idle tasks. The idle tasks are created automatically when the scheduler is started. */
|
|
|
|
/* Improve support for OpenOCD. The kernel tracks Ready tasks via priority lists.
|
|
* For tracking the state of remote threads, OpenOCD uses uxTopUsedPriority
|
|
* to determine the number of priority lists to read back from the remote target. */
|
|
const volatile UBaseType_t uxTopUsedPriority = configMAX_PRIORITIES - 1U;
|
|
|
|
/* Context switches are held pending while the scheduler is suspended. Also,
|
|
* interrupts must not manipulate the xStateListItem of a TCB, or any of the
|
|
* lists the xStateListItem can be referenced from, if the scheduler is suspended.
|
|
* If an interrupt needs to unblock a task while the scheduler is suspended then it
|
|
* moves the task's event list item into the xPendingReadyList, ready for the
|
|
* kernel to move the task from the pending ready list into the real ready list
|
|
* when the scheduler is unsuspended. The pending ready list itself can only be
|
|
* accessed from a critical section.
|
|
*
|
|
* Updates to uxSchedulerSuspended must be protected by both the task lock and the ISR lock
|
|
* and must not be done from an ISR. Reads must be protected by either lock and may be done
|
|
* from either an ISR or a task. */
|
|
PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) 0U;
|
|
|
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
|
|
/* Do not move these variables to function scope as doing so prevents the
|
|
* code working with debuggers that need to remove the static qualifier. */
|
|
PRIVILEGED_DATA static configRUN_TIME_COUNTER_TYPE ulTaskSwitchedInTime[ configNUMBER_OF_CORES ] = { 0U }; /**< Holds the value of a timer/counter the last time a task was switched in. */
|
|
PRIVILEGED_DATA static volatile configRUN_TIME_COUNTER_TYPE ulTotalRunTime[ configNUMBER_OF_CORES ] = { 0U }; /**< Holds the total amount of execution time as defined by the run time counter clock. */
|
|
|
|
#endif
|
|
|
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configNUMBER_OF_CORES > 1 )
|
|
|
|
/* Do not move these variables to function scope as doing so prevents the
|
|
* code working with debuggers that need to remove the static qualifier. */
|
|
static StaticTask_t xIdleTCBBuffers[ configNUMBER_OF_CORES - 1 ];
|
|
static StackType_t xIdleTaskStackBuffers[ configNUMBER_OF_CORES - 1 ][ configMINIMAL_STACK_SIZE ];
|
|
|
|
#endif /* #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configNUMBER_OF_CORES > 1 ) */
|
|
|
|
/*lint -restore */
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* File private functions. --------------------------------*/
|
|
|
|
/*
|
|
* Creates the idle tasks during scheduler start.
|
|
*/
|
|
static BaseType_t prvCreateIdleTasks( void );
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
|
|
/*
|
|
* Checks to see if another task moved the current task out of the ready
|
|
* list while it was waiting to enter a critical section and yields, if so.
|
|
*/
|
|
static void prvCheckForRunStateChange( void );
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
|
|
/*
|
|
* Yields the given core.
|
|
*/
|
|
static void prvYieldCore( BaseType_t xCoreID );
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
|
|
/*
|
|
* Yields a core, or cores if multiple priorities are not allowed to run
|
|
* simultaneously, to allow the task pxTCB to run.
|
|
*/
|
|
static void prvYieldForTask( const TCB_t * pxTCB );
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
|
|
/*
|
|
* Selects the highest priority available task for the given core.
|
|
*/
|
|
static void prvSelectHighestPriorityTask( BaseType_t xCoreID );
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
|
|
/**
|
|
* Utility task that simply returns pdTRUE if the task referenced by xTask is
|
|
* currently in the Suspended state, or pdFALSE if the task referenced by xTask
|
|
* is in any other state.
|
|
*/
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
|
|
static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
|
|
|
|
#endif /* INCLUDE_vTaskSuspend */
|
|
|
|
/*
|
|
* Utility to ready all the lists used by the scheduler. This is called
|
|
* automatically upon the creation of the first task.
|
|
*/
|
|
static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
|
|
|
|
/*
|
|
* The idle task, which as all tasks is implemented as a never ending loop.
|
|
* The idle task is automatically created and added to the ready lists upon
|
|
* creation of the first user task.
|
|
*
|
|
* In the FreeRTOS SMP, configNUMBER_OF_CORES - 1 minimal idle tasks are also
|
|
* created to ensure that each core has an idle task to run when no other
|
|
* task is available to run.
|
|
*
|
|
* The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
|
|
* language extensions. The equivalent prototype for these functions are:
|
|
*
|
|
* void prvIdleTask( void *pvParameters );
|
|
* void prvMinimalIdleTask( void *pvParameters );
|
|
*
|
|
*/
|
|
static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ) PRIVILEGED_FUNCTION;
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
static portTASK_FUNCTION_PROTO( prvMinimalIdleTask, pvParameters ) PRIVILEGED_FUNCTION;
|
|
#endif
|
|
|
|
/*
|
|
* Utility to free all memory allocated by the scheduler to hold a TCB,
|
|
* including the stack pointed to by the TCB.
|
|
*
|
|
* This does not free memory allocated by the task itself (i.e. memory
|
|
* allocated by calls to pvPortMalloc from within the tasks application code).
|
|
*/
|
|
#if ( INCLUDE_vTaskDelete == 1 )
|
|
|
|
static void prvDeleteTCB( TCB_t * pxTCB ) PRIVILEGED_FUNCTION;
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Used only by the idle task. This checks to see if anything has been placed
|
|
* in the list of tasks waiting to be deleted. If so the task is cleaned up
|
|
* and its TCB deleted.
|
|
*/
|
|
static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
|
|
|
|
/*
|
|
* The currently executing task is entering the Blocked state. Add the task to
|
|
* either the current or the overflow delayed task list.
|
|
*/
|
|
static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
|
|
const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
|
|
|
|
/*
|
|
* Fills an TaskStatus_t structure with information on each task that is
|
|
* referenced from the pxList list (which may be a ready list, a delayed list,
|
|
* a suspended list, etc.).
|
|
*
|
|
* THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
|
|
* NORMAL APPLICATION CODE.
|
|
*/
|
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
|
|
|
static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
|
|
List_t * pxList,
|
|
eTaskState eState ) PRIVILEGED_FUNCTION;
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Searches pxList for a task with name pcNameToQuery - returning a handle to
|
|
* the task if it is found, or NULL if the task is not found.
|
|
*/
|
|
#if ( INCLUDE_xTaskGetHandle == 1 )
|
|
|
|
static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
|
|
const char pcNameToQuery[] ) PRIVILEGED_FUNCTION;
|
|
|
|
#endif
|
|
|
|
/*
|
|
* When a task is created, the stack of the task is filled with a known value.
|
|
* This function determines the 'high water mark' of the task stack by
|
|
* determining how much of the stack remains at the original preset value.
|
|
*/
|
|
#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
|
|
|
|
static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Return the amount of time, in ticks, that will pass before the kernel will
|
|
* next move a task from the Blocked state to the Running state.
|
|
*
|
|
* This conditional compilation should use inequality to 0, not equality to 1.
|
|
* This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
|
|
* defined low power mode implementations require configUSE_TICKLESS_IDLE to be
|
|
* set to a value other than 1.
|
|
*/
|
|
#if ( configUSE_TICKLESS_IDLE != 0 )
|
|
|
|
static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Set xNextTaskUnblockTime to the time at which the next Blocked state task
|
|
* will exit the Blocked state.
|
|
*/
|
|
static void prvResetNextTaskUnblockTime( void ) PRIVILEGED_FUNCTION;
|
|
|
|
#if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
|
|
|
|
/*
|
|
* Helper function used to pad task names with spaces when printing out
|
|
* human readable tables of task information.
|
|
*/
|
|
static char * prvWriteNameToBuffer( char * pcBuffer,
|
|
const char * pcTaskName ) PRIVILEGED_FUNCTION;
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Called after a Task_t structure has been allocated either statically or
|
|
* dynamically to fill in the structure's members.
|
|
*/
|
|
static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
|
|
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
|
const uint32_t ulStackDepth,
|
|
void * const pvParameters,
|
|
UBaseType_t uxPriority,
|
|
TaskHandle_t * const pxCreatedTask,
|
|
TCB_t * pxNewTCB,
|
|
const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION;
|
|
|
|
/*
|
|
* Called after a new task has been created and initialised to place the task
|
|
* under the control of the scheduler.
|
|
*/
|
|
static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
|
|
|
|
/*
|
|
* freertos_tasks_c_additions_init() should only be called if the user definable
|
|
* macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is the only macro
|
|
* called by the function.
|
|
*/
|
|
#ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
|
|
|
|
static void freertos_tasks_c_additions_init( void ) PRIVILEGED_FUNCTION;
|
|
|
|
#endif
|
|
|
|
#if ( configUSE_MINIMAL_IDLE_HOOK == 1 )
|
|
extern void vApplicationMinimalIdleHook( void );
|
|
#endif /* #if ( configUSE_MINIMAL_IDLE_HOOK == 1 ) */
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
static void prvCheckForRunStateChange( void )
|
|
{
|
|
UBaseType_t uxPrevCriticalNesting;
|
|
const TCB_t * pxThisTCB;
|
|
|
|
/* This should be skipped if called from an ISR. If the task on the current
|
|
* core is no longer running, then vTaskSwitchContext() probably should
|
|
* be run before returning, but we don't have a way to force that to happen
|
|
* from here. */
|
|
if( portCHECK_IF_IN_ISR() == pdFALSE )
|
|
{
|
|
/* This function is always called with interrupts disabled
|
|
* so this is safe. */
|
|
pxThisTCB = pxCurrentTCBs[ portGET_CORE_ID() ];
|
|
|
|
while( pxThisTCB->xTaskRunState == taskTASK_YIELDING )
|
|
{
|
|
/* We are only here if we just entered a critical section
|
|
* or if we just suspended the scheduler, and another task
|
|
* has requested that we yield.
|
|
*
|
|
* This is slightly complicated since we need to save and restore
|
|
* the suspension and critical nesting counts, as well as release
|
|
* and reacquire the correct locks. And then, do it all over again
|
|
* if our state changed again during the reacquisition. */
|
|
uxPrevCriticalNesting = portGET_CRITICAL_NESTING_COUNT();
|
|
|
|
if( uxPrevCriticalNesting > 0U )
|
|
{
|
|
portSET_CRITICAL_NESTING_COUNT( 0U );
|
|
portRELEASE_ISR_LOCK();
|
|
}
|
|
else
|
|
{
|
|
/* The scheduler is suspended. uxSchedulerSuspended is updated
|
|
* only when the task is not requested to yield. */
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
portRELEASE_TASK_LOCK();
|
|
|
|
portMEMORY_BARRIER();
|
|
configASSERT( pxThisTCB->xTaskRunState == taskTASK_YIELDING );
|
|
|
|
portENABLE_INTERRUPTS();
|
|
|
|
/* Enabling interrupts should cause this core to immediately
|
|
* service the pending interrupt and yield. If the run state is still
|
|
* yielding here then that is a problem. */
|
|
configASSERT( pxThisTCB->xTaskRunState != taskTASK_YIELDING );
|
|
|
|
portDISABLE_INTERRUPTS();
|
|
portGET_TASK_LOCK();
|
|
portGET_ISR_LOCK();
|
|
|
|
portSET_CRITICAL_NESTING_COUNT( uxPrevCriticalNesting );
|
|
|
|
if( uxPrevCriticalNesting == 0U )
|
|
{
|
|
portRELEASE_ISR_LOCK();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
static void prvYieldCore( BaseType_t xCoreID )
|
|
{
|
|
/* This must be called from a critical section and xCoreID must be valid. */
|
|
if( ( portCHECK_IF_IN_ISR() == pdTRUE ) && ( xCoreID == portGET_CORE_ID() ) )
|
|
{
|
|
xYieldPendings[ xCoreID ] = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
if( pxCurrentTCBs[ xCoreID ]->xTaskRunState != taskTASK_YIELDING )
|
|
{
|
|
if( xCoreID == portGET_CORE_ID() )
|
|
{
|
|
xYieldPendings[ xCoreID ] = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
portYIELD_CORE( xCoreID );
|
|
pxCurrentTCBs[ xCoreID ]->xTaskRunState = taskTASK_YIELDING;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
static void prvYieldForTask( const TCB_t * pxTCB )
|
|
{
|
|
BaseType_t xLowestPriorityToPreempt;
|
|
BaseType_t xCurrentCoreTaskPriority;
|
|
BaseType_t xLowestPriorityCore = ( BaseType_t ) -1;
|
|
BaseType_t xCoreID;
|
|
|
|
#if ( configRUN_MULTIPLE_PRIORITIES == 0 )
|
|
BaseType_t xYieldCount = 0;
|
|
#endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
|
|
|
|
/* This must be called from a critical section. */
|
|
configASSERT( portGET_CRITICAL_NESTING_COUNT() > 0U );
|
|
|
|
#if ( configRUN_MULTIPLE_PRIORITIES == 0 )
|
|
|
|
/* No task should yield for this one if it is a lower priority
|
|
* than priority level of currently ready tasks. */
|
|
if( pxTCB->uxPriority >= uxTopReadyPriority )
|
|
#else
|
|
/* Yield is not required for a task which is already running. */
|
|
if( taskTASK_IS_RUNNING( pxTCB ) == pdFALSE )
|
|
#endif
|
|
{
|
|
xLowestPriorityToPreempt = ( BaseType_t ) pxTCB->uxPriority;
|
|
|
|
/* xLowestPriorityToPreempt will be decremented to -1 if the priority of pxTCB
|
|
* is 0. This is ok as we will give system idle tasks a priority of -1 below. */
|
|
--xLowestPriorityToPreempt;
|
|
|
|
for( xCoreID = ( BaseType_t ) 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ )
|
|
{
|
|
xCurrentCoreTaskPriority = ( BaseType_t ) pxCurrentTCBs[ xCoreID ]->uxPriority;
|
|
|
|
/* System idle tasks are being assigned a priority of tskIDLE_PRIORITY - 1 here. */
|
|
if( ( pxCurrentTCBs[ xCoreID ]->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) != 0U )
|
|
{
|
|
xCurrentCoreTaskPriority = xCurrentCoreTaskPriority - 1;
|
|
}
|
|
|
|
if( ( taskTASK_IS_RUNNING( pxCurrentTCBs[ xCoreID ] ) != pdFALSE ) && ( xYieldPendings[ xCoreID ] == pdFALSE ) )
|
|
{
|
|
#if ( configRUN_MULTIPLE_PRIORITIES == 0 )
|
|
if( taskTASK_IS_RUNNING( pxTCB ) == pdFALSE )
|
|
#endif
|
|
{
|
|
if( xCurrentCoreTaskPriority <= xLowestPriorityToPreempt )
|
|
{
|
|
#if ( configUSE_CORE_AFFINITY == 1 )
|
|
if( ( pxTCB->uxCoreAffinityMask & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) != 0U )
|
|
#endif
|
|
{
|
|
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
|
|
if( pxCurrentTCBs[ xCoreID ]->xPreemptionDisable == pdFALSE )
|
|
#endif
|
|
{
|
|
xLowestPriorityToPreempt = xCurrentCoreTaskPriority;
|
|
xLowestPriorityCore = xCoreID;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
#if ( configRUN_MULTIPLE_PRIORITIES == 0 )
|
|
{
|
|
/* Yield all currently running non-idle tasks with a priority lower than
|
|
* the task that needs to run. */
|
|
if( ( xCurrentCoreTaskPriority > ( ( BaseType_t ) tskIDLE_PRIORITY - 1 ) ) &&
|
|
( xCurrentCoreTaskPriority < ( BaseType_t ) pxTCB->uxPriority ) )
|
|
{
|
|
prvYieldCore( xCoreID );
|
|
xYieldCount++;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
#if ( configRUN_MULTIPLE_PRIORITIES == 0 )
|
|
if( ( xYieldCount == 0 ) && ( xLowestPriorityCore >= 0 ) )
|
|
#else /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
|
|
if( xLowestPriorityCore >= 0 )
|
|
#endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
|
|
{
|
|
prvYieldCore( xLowestPriorityCore );
|
|
}
|
|
|
|
#if ( configRUN_MULTIPLE_PRIORITIES == 0 )
|
|
/* Verify that the calling core always yields to higher priority tasks. */
|
|
if( ( ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) == 0 ) &&
|
|
( pxTCB->uxPriority > pxCurrentTCBs[ portGET_CORE_ID() ]->uxPriority ) )
|
|
{
|
|
configASSERT( ( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) ||
|
|
( taskTASK_IS_RUNNING( pxCurrentTCBs[ portGET_CORE_ID() ] ) == pdFALSE ) );
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
static void prvSelectHighestPriorityTask( BaseType_t xCoreID )
|
|
{
|
|
UBaseType_t uxCurrentPriority = uxTopReadyPriority;
|
|
BaseType_t xTaskScheduled = pdFALSE;
|
|
BaseType_t xDecrementTopPriority = pdTRUE;
|
|
|
|
#if ( configUSE_CORE_AFFINITY == 1 )
|
|
const TCB_t * pxPreviousTCB = NULL;
|
|
#endif
|
|
#if ( configRUN_MULTIPLE_PRIORITIES == 0 )
|
|
BaseType_t xPriorityDropped = pdFALSE;
|
|
#endif
|
|
|
|
/* This function should be called when scheduler is running. */
|
|
configASSERT( xSchedulerRunning == pdTRUE );
|
|
|
|
/* A new task is created and a running task with the same priority yields
|
|
* itself to run the new task. When a running task yields itself, it is still
|
|
* in the ready list. This running task will be selected before the new task
|
|
* since the new task is always added to the end of the ready list.
|
|
* The other problem is that the running task still in the same position of
|
|
* the ready list when it yields itself. It is possible that it will be selected
|
|
* earlier then other tasks which waits longer than this task.
|
|
*
|
|
* To fix these problems, the running task should be put to the end of the
|
|
* ready list before searching for the ready task in the ready list. */
|
|
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxCurrentTCBs[ xCoreID ]->uxPriority ] ),
|
|
&pxCurrentTCBs[ xCoreID ]->xStateListItem ) == pdTRUE )
|
|
{
|
|
( void ) uxListRemove( &pxCurrentTCBs[ xCoreID ]->xStateListItem );
|
|
vListInsertEnd( &( pxReadyTasksLists[ pxCurrentTCBs[ xCoreID ]->uxPriority ] ),
|
|
&pxCurrentTCBs[ xCoreID ]->xStateListItem );
|
|
}
|
|
|
|
while( xTaskScheduled == pdFALSE )
|
|
{
|
|
#if ( configRUN_MULTIPLE_PRIORITIES == 0 )
|
|
{
|
|
if( uxCurrentPriority < uxTopReadyPriority )
|
|
{
|
|
/* We can't schedule any tasks, other than idle, that have a
|
|
* priority lower than the priority of a task currently running
|
|
* on another core. */
|
|
uxCurrentPriority = tskIDLE_PRIORITY;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxCurrentPriority ] ) ) == pdFALSE )
|
|
{
|
|
const List_t * const pxReadyList = &( pxReadyTasksLists[ uxCurrentPriority ] );
|
|
const ListItem_t * pxEndMarker = listGET_END_MARKER( pxReadyList );
|
|
ListItem_t * pxIterator;
|
|
|
|
/* The ready task list for uxCurrentPriority is not empty, so uxTopReadyPriority
|
|
* must not be decremented any further. */
|
|
xDecrementTopPriority = pdFALSE;
|
|
|
|
for( pxIterator = listGET_HEAD_ENTRY( pxReadyList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) )
|
|
{
|
|
TCB_t * pxTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
|
|
|
|
#if ( configRUN_MULTIPLE_PRIORITIES == 0 )
|
|
{
|
|
/* When falling back to the idle priority because only one priority
|
|
* level is allowed to run at a time, we should ONLY schedule the true
|
|
* idle tasks, not user tasks at the idle priority. */
|
|
if( uxCurrentPriority < uxTopReadyPriority )
|
|
{
|
|
if( ( pxTCB->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
#endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
|
|
|
|
if( pxTCB->xTaskRunState == taskTASK_NOT_RUNNING )
|
|
{
|
|
#if ( configUSE_CORE_AFFINITY == 1 )
|
|
if( ( pxTCB->uxCoreAffinityMask & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) != 0U )
|
|
#endif
|
|
{
|
|
/* If the task is not being executed by any core swap it in. */
|
|
pxCurrentTCBs[ xCoreID ]->xTaskRunState = taskTASK_NOT_RUNNING;
|
|
#if ( configUSE_CORE_AFFINITY == 1 )
|
|
pxPreviousTCB = pxCurrentTCBs[ xCoreID ];
|
|
#endif
|
|
pxTCB->xTaskRunState = ( TaskRunning_t ) xCoreID;
|
|
pxCurrentTCBs[ xCoreID ] = pxTCB;
|
|
xTaskScheduled = pdTRUE;
|
|
}
|
|
}
|
|
else if( pxTCB == pxCurrentTCBs[ xCoreID ] )
|
|
{
|
|
configASSERT( ( pxTCB->xTaskRunState == xCoreID ) || ( pxTCB->xTaskRunState == taskTASK_YIELDING ) );
|
|
|
|
#if ( configUSE_CORE_AFFINITY == 1 )
|
|
if( ( pxTCB->uxCoreAffinityMask & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) != 0U )
|
|
#endif
|
|
{
|
|
/* The task is already running on this core, mark it as scheduled. */
|
|
pxTCB->xTaskRunState = ( TaskRunning_t ) xCoreID;
|
|
xTaskScheduled = pdTRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* This task is running on the core other than xCoreID. */
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
if( xTaskScheduled != pdFALSE )
|
|
{
|
|
/* A task has been selected to run on this core. */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( xDecrementTopPriority != pdFALSE )
|
|
{
|
|
uxTopReadyPriority--;
|
|
#if ( configRUN_MULTIPLE_PRIORITIES == 0 )
|
|
{
|
|
xPriorityDropped = pdTRUE;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* There are configNUMBER_OF_CORES Idle tasks created when scheduler started.
|
|
* The scheduler should be able to select a task to run when uxCurrentPriority
|
|
* is tskIDLE_PRIORITY. uxCurrentPriority is never decreased to value blow
|
|
* tskIDLE_PRIORITY. */
|
|
if( uxCurrentPriority > tskIDLE_PRIORITY )
|
|
{
|
|
uxCurrentPriority--;
|
|
}
|
|
else
|
|
{
|
|
/* This function is called when idle task is not created. Break the
|
|
* loop to prevent uxCurrentPriority overrun. */
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if ( configRUN_MULTIPLE_PRIORITIES == 0 )
|
|
{
|
|
if( xTaskScheduled == pdTRUE )
|
|
{
|
|
if( xPriorityDropped != pdFALSE )
|
|
{
|
|
/* There may be several ready tasks that were being prevented from running because there was
|
|
* a higher priority task running. Now that the last of the higher priority tasks is no longer
|
|
* running, make sure all the other idle tasks yield. */
|
|
BaseType_t x;
|
|
|
|
for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configNUMBER_OF_CORES; x++ )
|
|
{
|
|
if( ( pxCurrentTCBs[ x ]->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) != 0 )
|
|
{
|
|
prvYieldCore( x );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
|
|
|
|
#if ( configUSE_CORE_AFFINITY == 1 )
|
|
{
|
|
if( xTaskScheduled == pdTRUE )
|
|
{
|
|
if( ( pxPreviousTCB != NULL ) && ( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxPreviousTCB->uxPriority ] ), &( pxPreviousTCB->xStateListItem ) ) != pdFALSE ) )
|
|
{
|
|
/* A ready task was just evicted from this core. See if it can be
|
|
* scheduled on any other core. */
|
|
UBaseType_t uxCoreMap = pxPreviousTCB->uxCoreAffinityMask;
|
|
BaseType_t xLowestPriority = ( BaseType_t ) pxPreviousTCB->uxPriority;
|
|
BaseType_t xLowestPriorityCore = -1;
|
|
BaseType_t x;
|
|
|
|
if( ( pxPreviousTCB->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) != 0U )
|
|
{
|
|
xLowestPriority = xLowestPriority - 1;
|
|
}
|
|
|
|
if( ( uxCoreMap & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) != 0U )
|
|
{
|
|
/* The ready task that was removed from this core is not excluded from it.
|
|
* Only look at the intersection of the cores the removed task is allowed to run
|
|
* on with the cores that the new task is excluded from. It is possible that the
|
|
* new task was only placed onto this core because it is excluded from another.
|
|
* Check to see if the previous task could run on one of those cores. */
|
|
uxCoreMap &= ~( pxCurrentTCBs[ xCoreID ]->uxCoreAffinityMask );
|
|
}
|
|
else
|
|
{
|
|
/* The ready task that was removed from this core is excluded from it. */
|
|
}
|
|
|
|
uxCoreMap &= ( ( 1U << configNUMBER_OF_CORES ) - 1U );
|
|
|
|
for( x = ( ( BaseType_t ) configNUMBER_OF_CORES - 1 ); x >= ( BaseType_t ) 0; x-- )
|
|
{
|
|
UBaseType_t uxCore = ( UBaseType_t ) x;
|
|
BaseType_t xTaskPriority;
|
|
|
|
if( ( uxCoreMap & ( ( UBaseType_t ) 1U << uxCore ) ) != 0U )
|
|
{
|
|
xTaskPriority = ( BaseType_t ) pxCurrentTCBs[ uxCore ]->uxPriority;
|
|
|
|
if( ( pxCurrentTCBs[ uxCore ]->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) != 0U )
|
|
{
|
|
xTaskPriority = xTaskPriority - ( BaseType_t ) 1;
|
|
}
|
|
|
|
uxCoreMap &= ~( ( UBaseType_t ) 1U << uxCore );
|
|
|
|
if( ( xTaskPriority < xLowestPriority ) &&
|
|
( taskTASK_IS_RUNNING( pxCurrentTCBs[ uxCore ] ) != pdFALSE ) &&
|
|
( xYieldPendings[ uxCore ] == pdFALSE ) )
|
|
{
|
|
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
|
|
if( pxCurrentTCBs[ uxCore ]->xPreemptionDisable == pdFALSE )
|
|
#endif
|
|
{
|
|
xLowestPriority = xTaskPriority;
|
|
xLowestPriorityCore = ( BaseType_t ) uxCore;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( xLowestPriorityCore >= 0 )
|
|
{
|
|
prvYieldCore( xLowestPriorityCore );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif /* #if ( configUSE_CORE_AFFINITY == 1 ) */
|
|
}
|
|
|
|
#endif /* ( configNUMBER_OF_CORES > 1 ) */
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
|
|
|
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
|
|
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
|
const uint32_t ulStackDepth,
|
|
void * const pvParameters,
|
|
UBaseType_t uxPriority,
|
|
StackType_t * const puxStackBuffer,
|
|
StaticTask_t * const pxTaskBuffer )
|
|
#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
|
{
|
|
return xTaskCreateStaticAffinitySet( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, tskNO_AFFINITY );
|
|
}
|
|
|
|
TaskHandle_t xTaskCreateStaticAffinitySet( TaskFunction_t pxTaskCode,
|
|
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
|
const uint32_t ulStackDepth,
|
|
void * const pvParameters,
|
|
UBaseType_t uxPriority,
|
|
StackType_t * const puxStackBuffer,
|
|
StaticTask_t * const pxTaskBuffer,
|
|
UBaseType_t uxCoreAffinityMask )
|
|
#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
|
|
{
|
|
TCB_t * pxNewTCB;
|
|
TaskHandle_t xReturn;
|
|
|
|
configASSERT( puxStackBuffer != NULL );
|
|
configASSERT( pxTaskBuffer != NULL );
|
|
|
|
#if ( configASSERT_DEFINED == 1 )
|
|
{
|
|
/* Sanity check that the size of the structure used to declare a
|
|
* variable of type StaticTask_t equals the size of the real task
|
|
* structure. */
|
|
volatile size_t xSize = sizeof( StaticTask_t );
|
|
configASSERT( xSize == sizeof( TCB_t ) );
|
|
( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */
|
|
}
|
|
#endif /* configASSERT_DEFINED */
|
|
|
|
if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
|
|
{
|
|
/* The memory used for the task's TCB and stack are passed into this
|
|
* function - use them. */
|
|
pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
|
|
( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
|
|
pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
|
|
|
|
#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
|
|
{
|
|
/* Tasks can be created statically or dynamically, so note this
|
|
* task was created statically in case the task is later deleted. */
|
|
pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
|
|
}
|
|
#endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
|
|
|
|
prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );
|
|
|
|
#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
|
{
|
|
/* Set the task's affinity before scheduling it. */
|
|
pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask;
|
|
}
|
|
#endif
|
|
|
|
prvAddNewTaskToReadyList( pxNewTCB );
|
|
}
|
|
else
|
|
{
|
|
xReturn = NULL;
|
|
}
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* SUPPORT_STATIC_ALLOCATION */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
|
|
|
|
BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition,
|
|
TaskHandle_t * pxCreatedTask )
|
|
#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
|
{
|
|
return xTaskCreateRestrictedStaticAffinitySet( pxTaskDefinition, tskNO_AFFINITY, pxCreatedTask );
|
|
}
|
|
|
|
BaseType_t xTaskCreateRestrictedStaticAffinitySet( const TaskParameters_t * const pxTaskDefinition,
|
|
UBaseType_t uxCoreAffinityMask,
|
|
TaskHandle_t * pxCreatedTask )
|
|
#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
|
|
{
|
|
TCB_t * pxNewTCB;
|
|
BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
|
|
|
configASSERT( pxTaskDefinition->puxStackBuffer != NULL );
|
|
configASSERT( pxTaskDefinition->pxTaskBuffer != NULL );
|
|
|
|
if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != NULL ) )
|
|
{
|
|
/* Allocate space for the TCB. Where the memory comes from depends
|
|
* on the implementation of the port malloc function and whether or
|
|
* not static allocation is being used. */
|
|
pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer;
|
|
( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
|
|
|
|
/* Store the stack location in the TCB. */
|
|
pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
|
|
|
|
#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
|
|
{
|
|
/* Tasks can be created statically or dynamically, so note this
|
|
* task was created statically in case the task is later deleted. */
|
|
pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
|
|
}
|
|
#endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
|
|
|
|
prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
|
|
pxTaskDefinition->pcName,
|
|
( uint32_t ) pxTaskDefinition->usStackDepth,
|
|
pxTaskDefinition->pvParameters,
|
|
pxTaskDefinition->uxPriority,
|
|
pxCreatedTask, pxNewTCB,
|
|
pxTaskDefinition->xRegions );
|
|
|
|
#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
|
{
|
|
/* Set the task's affinity before scheduling it. */
|
|
pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask;
|
|
}
|
|
#endif
|
|
|
|
prvAddNewTaskToReadyList( pxNewTCB );
|
|
xReturn = pdPASS;
|
|
}
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
|
|
|
|
BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition,
|
|
TaskHandle_t * pxCreatedTask )
|
|
#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
|
{
|
|
return xTaskCreateRestrictedAffinitySet( pxTaskDefinition, tskNO_AFFINITY, pxCreatedTask );
|
|
}
|
|
|
|
BaseType_t xTaskCreateRestrictedAffinitySet( const TaskParameters_t * const pxTaskDefinition,
|
|
UBaseType_t uxCoreAffinityMask,
|
|
TaskHandle_t * pxCreatedTask )
|
|
#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
|
|
{
|
|
TCB_t * pxNewTCB;
|
|
BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
|
|
|
configASSERT( pxTaskDefinition->puxStackBuffer );
|
|
|
|
if( pxTaskDefinition->puxStackBuffer != NULL )
|
|
{
|
|
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
|
|
|
|
if( pxNewTCB != NULL )
|
|
{
|
|
( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
|
|
|
|
/* Store the stack location in the TCB. */
|
|
pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
|
|
|
|
#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
|
|
{
|
|
/* Tasks can be created statically or dynamically, so note
|
|
* this task had a statically allocated stack in case it is
|
|
* later deleted. The TCB was allocated dynamically. */
|
|
pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;
|
|
}
|
|
#endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
|
|
|
|
prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
|
|
pxTaskDefinition->pcName,
|
|
( uint32_t ) pxTaskDefinition->usStackDepth,
|
|
pxTaskDefinition->pvParameters,
|
|
pxTaskDefinition->uxPriority,
|
|
pxCreatedTask, pxNewTCB,
|
|
pxTaskDefinition->xRegions );
|
|
|
|
#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
|
{
|
|
/* Set the task's affinity before scheduling it. */
|
|
pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask;
|
|
}
|
|
#endif
|
|
|
|
prvAddNewTaskToReadyList( pxNewTCB );
|
|
xReturn = pdPASS;
|
|
}
|
|
}
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* portUSING_MPU_WRAPPERS */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
|
|
|
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
|
|
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
|
const configSTACK_DEPTH_TYPE usStackDepth,
|
|
void * const pvParameters,
|
|
UBaseType_t uxPriority,
|
|
TaskHandle_t * const pxCreatedTask )
|
|
#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
|
{
|
|
return xTaskCreateAffinitySet( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, tskNO_AFFINITY, pxCreatedTask );
|
|
}
|
|
|
|
BaseType_t xTaskCreateAffinitySet( TaskFunction_t pxTaskCode,
|
|
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
|
const configSTACK_DEPTH_TYPE usStackDepth,
|
|
void * const pvParameters,
|
|
UBaseType_t uxPriority,
|
|
UBaseType_t uxCoreAffinityMask,
|
|
TaskHandle_t * const pxCreatedTask )
|
|
#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
|
|
{
|
|
TCB_t * pxNewTCB;
|
|
BaseType_t xReturn;
|
|
|
|
/* If the stack grows down then allocate the stack then the TCB so the stack
|
|
* does not grow into the TCB. Likewise if the stack grows up then allocate
|
|
* the TCB then the stack. */
|
|
#if ( portSTACK_GROWTH > 0 )
|
|
{
|
|
/* Allocate space for the TCB. Where the memory comes from depends on
|
|
* the implementation of the port malloc function and whether or not static
|
|
* allocation is being used. */
|
|
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
|
|
|
|
if( pxNewTCB != NULL )
|
|
{
|
|
( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
|
|
|
|
/* Allocate space for the stack used by the task being created.
|
|
* The base of the stack memory stored in the TCB so the task can
|
|
* be deleted later if required. */
|
|
pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
|
|
if( pxNewTCB->pxStack == NULL )
|
|
{
|
|
/* Could not allocate the stack. Delete the allocated TCB. */
|
|
vPortFree( pxNewTCB );
|
|
pxNewTCB = NULL;
|
|
}
|
|
}
|
|
}
|
|
#else /* portSTACK_GROWTH */
|
|
{
|
|
StackType_t * pxStack;
|
|
|
|
/* Allocate space for the stack used by the task being created. */
|
|
pxStack = pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */
|
|
|
|
if( pxStack != NULL )
|
|
{
|
|
/* Allocate space for the TCB. */
|
|
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */
|
|
|
|
if( pxNewTCB != NULL )
|
|
{
|
|
( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
|
|
|
|
/* Store the stack location in the TCB. */
|
|
pxNewTCB->pxStack = pxStack;
|
|
}
|
|
else
|
|
{
|
|
/* The stack cannot be used as the TCB was not created. Free
|
|
* it again. */
|
|
vPortFreeStack( pxStack );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pxNewTCB = NULL;
|
|
}
|
|
}
|
|
#endif /* portSTACK_GROWTH */
|
|
|
|
if( pxNewTCB != NULL )
|
|
{
|
|
#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */
|
|
{
|
|
/* Tasks can be created statically or dynamically, so note this
|
|
* task was created dynamically in case it is later deleted. */
|
|
pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
|
|
}
|
|
#endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
|
|
|
|
prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
|
|
|
|
#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
|
{
|
|
/* Set the task's affinity before scheduling it. */
|
|
pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask;
|
|
}
|
|
#endif
|
|
|
|
prvAddNewTaskToReadyList( pxNewTCB );
|
|
xReturn = pdPASS;
|
|
}
|
|
else
|
|
{
|
|
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
|
}
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
|
|
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
|
const uint32_t ulStackDepth,
|
|
void * const pvParameters,
|
|
UBaseType_t uxPriority,
|
|
TaskHandle_t * const pxCreatedTask,
|
|
TCB_t * pxNewTCB,
|
|
const MemoryRegion_t * const xRegions )
|
|
{
|
|
StackType_t * pxTopOfStack;
|
|
UBaseType_t x;
|
|
|
|
#if ( portUSING_MPU_WRAPPERS == 1 )
|
|
/* Should the task be created in privileged mode? */
|
|
BaseType_t xRunPrivileged;
|
|
|
|
if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
|
|
{
|
|
xRunPrivileged = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
xRunPrivileged = pdFALSE;
|
|
}
|
|
uxPriority &= ~portPRIVILEGE_BIT;
|
|
#endif /* portUSING_MPU_WRAPPERS == 1 */
|
|
|
|
/* Avoid dependency on memset() if it is not required. */
|
|
#if ( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )
|
|
{
|
|
/* Fill the stack with a known value to assist debugging. */
|
|
( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
|
|
}
|
|
#endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */
|
|
|
|
/* Calculate the top of stack address. This depends on whether the stack
|
|
* grows from high memory to low (as per the 80x86) or vice versa.
|
|
* portSTACK_GROWTH is used to make the result positive or negative as required
|
|
* by the port. */
|
|
#if ( portSTACK_GROWTH < 0 )
|
|
{
|
|
pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] );
|
|
pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 !e9033 !e9078 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. Checked by assert(). */
|
|
|
|
/* Check the alignment of the calculated top of stack is correct. */
|
|
configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
|
|
|
|
#if ( configRECORD_STACK_HIGH_ADDRESS == 1 )
|
|
{
|
|
/* Also record the stack's high address, which may assist
|
|
* debugging. */
|
|
pxNewTCB->pxEndOfStack = pxTopOfStack;
|
|
}
|
|
#endif /* configRECORD_STACK_HIGH_ADDRESS */
|
|
}
|
|
#else /* portSTACK_GROWTH */
|
|
{
|
|
pxTopOfStack = pxNewTCB->pxStack;
|
|
|
|
/* Check the alignment of the stack buffer is correct. */
|
|
configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
|
|
|
|
/* The other extreme of the stack space is required if stack checking is
|
|
* performed. */
|
|
pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
|
|
}
|
|
#endif /* portSTACK_GROWTH */
|
|
|
|
/* Store the task name in the TCB. */
|
|
if( pcName != NULL )
|
|
{
|
|
for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
|
|
{
|
|
pxNewTCB->pcTaskName[ x ] = pcName[ x ];
|
|
|
|
/* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
|
|
* configMAX_TASK_NAME_LEN characters just in case the memory after the
|
|
* string is not accessible (extremely unlikely). */
|
|
if( pcName[ x ] == ( char ) 0x00 )
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
/* Ensure the name string is terminated in the case that the string length
|
|
* was greater or equal to configMAX_TASK_NAME_LEN. */
|
|
pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* This is used as an array index so must ensure it's not too large. */
|
|
configASSERT( uxPriority < configMAX_PRIORITIES );
|
|
|
|
if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
|
|
{
|
|
uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
pxNewTCB->uxPriority = uxPriority;
|
|
#if ( configUSE_MUTEXES == 1 )
|
|
{
|
|
pxNewTCB->uxBasePriority = uxPriority;
|
|
}
|
|
#endif /* configUSE_MUTEXES */
|
|
|
|
vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
|
|
vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
|
|
|
|
/* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get
|
|
* back to the containing TCB from a generic item in a list. */
|
|
listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
|
|
|
|
/* Event lists are always in priority order. */
|
|
listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
|
|
|
|
#if ( portUSING_MPU_WRAPPERS == 1 )
|
|
{
|
|
vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth );
|
|
}
|
|
#else
|
|
{
|
|
/* Avoid compiler warning about unreferenced parameter. */
|
|
( void ) xRegions;
|
|
}
|
|
#endif
|
|
|
|
#if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
|
|
{
|
|
/* Allocate and initialize memory for the task's TLS Block. */
|
|
configINIT_TLS_BLOCK( pxNewTCB->xTLSBlock, pxTopOfStack );
|
|
}
|
|
#endif
|
|
|
|
#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
|
{
|
|
pxNewTCB->uxCoreAffinityMask = tskNO_AFFINITY;
|
|
}
|
|
#endif
|
|
|
|
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
|
|
{
|
|
pxNewTCB->xPreemptionDisable = 0;
|
|
}
|
|
#endif
|
|
|
|
/* Initialize the TCB stack to look as if the task was already running,
|
|
* but had been interrupted by the scheduler. The return address is set
|
|
* to the start of the task function. Once the stack has been initialised
|
|
* the top of stack variable is updated. */
|
|
#if ( portUSING_MPU_WRAPPERS == 1 )
|
|
{
|
|
/* If the port has capability to detect stack overflow,
|
|
* pass the stack end address to the stack initialization
|
|
* function as well. */
|
|
#if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
|
|
{
|
|
#if ( portSTACK_GROWTH < 0 )
|
|
{
|
|
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters, xRunPrivileged, &( pxNewTCB->xMPUSettings ) );
|
|
}
|
|
#else /* portSTACK_GROWTH */
|
|
{
|
|
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters, xRunPrivileged, &( pxNewTCB->xMPUSettings ) );
|
|
}
|
|
#endif /* portSTACK_GROWTH */
|
|
}
|
|
#else /* portHAS_STACK_OVERFLOW_CHECKING */
|
|
{
|
|
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged, &( pxNewTCB->xMPUSettings ) );
|
|
}
|
|
#endif /* portHAS_STACK_OVERFLOW_CHECKING */
|
|
}
|
|
#else /* portUSING_MPU_WRAPPERS */
|
|
{
|
|
/* If the port has capability to detect stack overflow,
|
|
* pass the stack end address to the stack initialization
|
|
* function as well. */
|
|
#if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
|
|
{
|
|
#if ( portSTACK_GROWTH < 0 )
|
|
{
|
|
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters );
|
|
}
|
|
#else /* portSTACK_GROWTH */
|
|
{
|
|
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters );
|
|
}
|
|
#endif /* portSTACK_GROWTH */
|
|
}
|
|
#else /* portHAS_STACK_OVERFLOW_CHECKING */
|
|
{
|
|
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
|
|
}
|
|
#endif /* portHAS_STACK_OVERFLOW_CHECKING */
|
|
}
|
|
#endif /* portUSING_MPU_WRAPPERS */
|
|
|
|
/* Initialize task state and task attributes. */
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
{
|
|
pxNewTCB->xTaskRunState = taskTASK_NOT_RUNNING;
|
|
|
|
/* Is this an idle task? */
|
|
if( ( ( TaskFunction_t ) pxTaskCode == ( TaskFunction_t ) prvIdleTask ) || ( ( TaskFunction_t ) pxTaskCode == ( TaskFunction_t ) prvMinimalIdleTask ) )
|
|
{
|
|
pxNewTCB->uxTaskAttributes |= taskATTRIBUTE_IS_IDLE;
|
|
}
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
|
|
if( pxCreatedTask != NULL )
|
|
{
|
|
/* Pass the handle out in an anonymous way. The handle can be used to
|
|
* change the created task's priority, delete the created task, etc.*/
|
|
*pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
|
|
static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
|
|
{
|
|
/* Ensure interrupts don't access the task lists while the lists are being
|
|
* updated. */
|
|
taskENTER_CRITICAL();
|
|
{
|
|
uxCurrentNumberOfTasks++;
|
|
|
|
if( pxCurrentTCB == NULL )
|
|
{
|
|
/* There are no other tasks, or all the other tasks are in
|
|
* the suspended state - make this the current task. */
|
|
pxCurrentTCB = pxNewTCB;
|
|
|
|
if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
|
|
{
|
|
/* This is the first task to be created so do the preliminary
|
|
* initialisation required. We will not recover if this call
|
|
* fails, but we will report the failure. */
|
|
prvInitialiseTaskLists();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* If the scheduler is not already running, make this task the
|
|
* current task if it is the highest priority task to be created
|
|
* so far. */
|
|
if( xSchedulerRunning == pdFALSE )
|
|
{
|
|
if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
|
|
{
|
|
pxCurrentTCB = pxNewTCB;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
uxTaskNumber++;
|
|
|
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
|
{
|
|
/* Add a counter into the TCB for tracing only. */
|
|
pxNewTCB->uxTCBNumber = uxTaskNumber;
|
|
}
|
|
#endif /* configUSE_TRACE_FACILITY */
|
|
traceTASK_CREATE( pxNewTCB );
|
|
|
|
prvAddTaskToReadyList( pxNewTCB );
|
|
|
|
portSETUP_TCB( pxNewTCB );
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
/* If the created task is of a higher priority than the current task
|
|
* then it should run now. */
|
|
if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
|
|
{
|
|
taskYIELD_IF_USING_PREEMPTION();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
|
|
static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
|
|
{
|
|
/* Ensure interrupts don't access the task lists while the lists are being
|
|
* updated. */
|
|
taskENTER_CRITICAL();
|
|
{
|
|
uxCurrentNumberOfTasks++;
|
|
|
|
if( xSchedulerRunning == pdFALSE )
|
|
{
|
|
if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
|
|
{
|
|
/* This is the first task to be created so do the preliminary
|
|
* initialisation required. We will not recover if this call
|
|
* fails, but we will report the failure. */
|
|
prvInitialiseTaskLists();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
if( ( pxNewTCB->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) != 0U )
|
|
{
|
|
BaseType_t xCoreID;
|
|
|
|
/* Check if a core is free. */
|
|
for( xCoreID = ( BaseType_t ) 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ )
|
|
{
|
|
if( pxCurrentTCBs[ xCoreID ] == NULL )
|
|
{
|
|
pxNewTCB->xTaskRunState = xCoreID;
|
|
pxCurrentTCBs[ xCoreID ] = pxNewTCB;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
uxTaskNumber++;
|
|
|
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
|
{
|
|
/* Add a counter into the TCB for tracing only. */
|
|
pxNewTCB->uxTCBNumber = uxTaskNumber;
|
|
}
|
|
#endif /* configUSE_TRACE_FACILITY */
|
|
traceTASK_CREATE( pxNewTCB );
|
|
|
|
prvAddTaskToReadyList( pxNewTCB );
|
|
|
|
portSETUP_TCB( pxNewTCB );
|
|
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
/* If the created task is of a higher priority than another
|
|
* currently running task and preemption is on then it should
|
|
* run now. */
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
prvYieldForTask( pxNewTCB );
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_vTaskDelete == 1 )
|
|
|
|
void vTaskDelete( TaskHandle_t xTaskToDelete )
|
|
{
|
|
TCB_t * pxTCB;
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
/* If null is passed in here then it is the calling task that is
|
|
* being deleted. */
|
|
pxTCB = prvGetTCBFromHandle( xTaskToDelete );
|
|
|
|
/* Remove task from the ready/delayed list. */
|
|
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
|
{
|
|
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* Is the task waiting on an event also? */
|
|
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
|
|
{
|
|
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* Increment the uxTaskNumber also so kernel aware debuggers can
|
|
* detect that the task lists need re-generating. This is done before
|
|
* portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will
|
|
* not return. */
|
|
uxTaskNumber++;
|
|
|
|
/* If the task is running (or yielding), we must add it to the
|
|
* termination list so that an idle task can delete it when it is
|
|
* no longer running. */
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
if( pxTCB == pxCurrentTCB )
|
|
#else
|
|
if( pxTCB->xTaskRunState != taskTASK_NOT_RUNNING )
|
|
#endif
|
|
{
|
|
/* A running task is being deleted. This cannot complete within the
|
|
* task itself, as a context switch to another task is required.
|
|
* Place the task in the termination list. The idle task will
|
|
* check the termination list and free up any memory allocated by
|
|
* the scheduler for the TCB and stack of the deleted task. */
|
|
vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
|
|
|
|
/* Increment the ucTasksDeleted variable so the idle task knows
|
|
* there is a task that has been deleted and that it should therefore
|
|
* check the xTasksWaitingTermination list. */
|
|
++uxDeletedTasksWaitingCleanUp;
|
|
|
|
/* Call the delete hook before portPRE_TASK_DELETE_HOOK() as
|
|
* portPRE_TASK_DELETE_HOOK() does not return in the Win32 port. */
|
|
traceTASK_DELETE( pxTCB );
|
|
|
|
/* The pre-delete hook is primarily for the Windows simulator,
|
|
* in which Windows specific clean up operations are performed,
|
|
* after which it is not possible to yield away from this task -
|
|
* hence xYieldPending is used to latch that a context switch is
|
|
* required. */
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPendings[ 0 ] );
|
|
#else
|
|
portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPendings[ pxTCB->xTaskRunState ] );
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
--uxCurrentNumberOfTasks;
|
|
traceTASK_DELETE( pxTCB );
|
|
|
|
/* Reset the next expected unblock time in case it referred to
|
|
* the task that has just been deleted. */
|
|
prvResetNextTaskUnblockTime();
|
|
}
|
|
}
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
taskEXIT_CRITICAL();
|
|
|
|
/* If the task is not deleting itself, call prvDeleteTCB from outside of
|
|
* critical section. If a task deletes itself, prvDeleteTCB is called
|
|
* from prvCheckTasksWaitingTermination which is called from Idle task. */
|
|
if( pxTCB != pxCurrentTCB )
|
|
{
|
|
prvDeleteTCB( pxTCB );
|
|
}
|
|
|
|
/* Force a reschedule if it is the currently running task that has just
|
|
* been deleted. */
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
if( pxTCB == pxCurrentTCB )
|
|
{
|
|
configASSERT( uxSchedulerSuspended == 0 );
|
|
portYIELD_WITHIN_API();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
/* If a running task is not deleting itself, call prvDeleteTCB. If a running
|
|
* task deletes itself, prvDeleteTCB is called from prvCheckTasksWaitingTermination
|
|
* which is called from Idle task. */
|
|
if( pxTCB->xTaskRunState == taskTASK_NOT_RUNNING )
|
|
{
|
|
prvDeleteTCB( pxTCB );
|
|
}
|
|
|
|
/* Force a reschedule if the task that has just been deleted was running. */
|
|
if( ( xSchedulerRunning != pdFALSE ) && ( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) )
|
|
{
|
|
if( pxTCB->xTaskRunState == portGET_CORE_ID() )
|
|
{
|
|
configASSERT( uxSchedulerSuspended == 0 );
|
|
vTaskYieldWithinAPI();
|
|
}
|
|
else
|
|
{
|
|
prvYieldCore( pxTCB->xTaskRunState );
|
|
}
|
|
}
|
|
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
|
|
#endif /* INCLUDE_vTaskDelete */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_xTaskDelayUntil == 1 )
|
|
|
|
BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
|
|
const TickType_t xTimeIncrement )
|
|
{
|
|
TickType_t xTimeToWake;
|
|
BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
|
|
|
|
configASSERT( pxPreviousWakeTime );
|
|
configASSERT( ( xTimeIncrement > 0U ) );
|
|
|
|
vTaskSuspendAll();
|
|
{
|
|
/* Minor optimisation. The tick count cannot change in this
|
|
* block. */
|
|
const TickType_t xConstTickCount = xTickCount;
|
|
|
|
configASSERT( uxSchedulerSuspended == 1U );
|
|
|
|
/* Generate the tick time at which the task wants to wake. */
|
|
xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
|
|
|
|
if( xConstTickCount < *pxPreviousWakeTime )
|
|
{
|
|
/* The tick count has overflowed since this function was
|
|
* lasted called. In this case the only time we should ever
|
|
* actually delay is if the wake time has also overflowed,
|
|
* and the wake time is greater than the tick time. When this
|
|
* is the case it is as if neither time had overflowed. */
|
|
if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
|
|
{
|
|
xShouldDelay = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* The tick time has not overflowed. In this case we will
|
|
* delay if either the wake time has overflowed, and/or the
|
|
* tick time is less than the wake time. */
|
|
if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
|
|
{
|
|
xShouldDelay = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
/* Update the wake time ready for the next call. */
|
|
*pxPreviousWakeTime = xTimeToWake;
|
|
|
|
if( xShouldDelay != pdFALSE )
|
|
{
|
|
traceTASK_DELAY_UNTIL( xTimeToWake );
|
|
|
|
/* prvAddCurrentTaskToDelayedList() needs the block time, not
|
|
* the time to wake, so subtract the current tick count. */
|
|
prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
xAlreadyYielded = xTaskResumeAll();
|
|
|
|
/* Force a reschedule if xTaskResumeAll has not already done so, we may
|
|
* have put ourselves to sleep. */
|
|
if( xAlreadyYielded == pdFALSE )
|
|
{
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
portYIELD_WITHIN_API();
|
|
#else
|
|
vTaskYieldWithinAPI();
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
return xShouldDelay;
|
|
}
|
|
|
|
#endif /* INCLUDE_xTaskDelayUntil */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_vTaskDelay == 1 )
|
|
|
|
void vTaskDelay( const TickType_t xTicksToDelay )
|
|
{
|
|
BaseType_t xAlreadyYielded = pdFALSE;
|
|
|
|
/* A delay time of zero just forces a reschedule. */
|
|
if( xTicksToDelay > ( TickType_t ) 0U )
|
|
{
|
|
vTaskSuspendAll();
|
|
{
|
|
configASSERT( uxSchedulerSuspended == 1U );
|
|
|
|
traceTASK_DELAY();
|
|
|
|
/* A task that is removed from the event list while the
|
|
* scheduler is suspended will not get placed in the ready
|
|
* list or removed from the blocked list until the scheduler
|
|
* is resumed.
|
|
*
|
|
* This task cannot be in an event list as it is the currently
|
|
* executing task. */
|
|
prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
|
|
}
|
|
xAlreadyYielded = xTaskResumeAll();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* Force a reschedule if xTaskResumeAll has not already done so, we may
|
|
* have put ourselves to sleep. */
|
|
if( xAlreadyYielded == pdFALSE )
|
|
{
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
portYIELD_WITHIN_API();
|
|
#else
|
|
vTaskYieldWithinAPI();
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
#endif /* INCLUDE_vTaskDelay */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) )
|
|
|
|
eTaskState eTaskGetState( TaskHandle_t xTask )
|
|
{
|
|
eTaskState eReturn;
|
|
List_t const * pxStateList;
|
|
List_t const * pxEventList;
|
|
List_t const * pxDelayedList;
|
|
List_t const * pxOverflowedDelayedList;
|
|
const TCB_t * const pxTCB = xTask;
|
|
|
|
configASSERT( pxTCB );
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
if( pxTCB == pxCurrentTCB )
|
|
{
|
|
/* The task calling this function is querying its own state. */
|
|
eReturn = eRunning;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
taskENTER_CRITICAL();
|
|
{
|
|
pxStateList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );
|
|
pxEventList = listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) );
|
|
pxDelayedList = pxDelayedTaskList;
|
|
pxOverflowedDelayedList = pxOverflowDelayedTaskList;
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
if( pxEventList == &xPendingReadyList )
|
|
{
|
|
/* The task has been placed on the pending ready list, so its
|
|
* state is eReady regardless of what list the task's state list
|
|
* item is currently placed on. */
|
|
eReturn = eReady;
|
|
}
|
|
else if( ( pxStateList == pxDelayedList ) || ( pxStateList == pxOverflowedDelayedList ) )
|
|
{
|
|
/* The task being queried is referenced from one of the Blocked
|
|
* lists. */
|
|
eReturn = eBlocked;
|
|
}
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
else if( pxStateList == &xSuspendedTaskList )
|
|
{
|
|
/* The task being queried is referenced from the suspended
|
|
* list. Is it genuinely suspended or is it blocked
|
|
* indefinitely? */
|
|
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
|
|
{
|
|
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
|
|
{
|
|
BaseType_t x;
|
|
|
|
/* The task does not appear on the event list item of
|
|
* and of the RTOS objects, but could still be in the
|
|
* blocked state if it is waiting on its notification
|
|
* rather than waiting on an object. If not, is
|
|
* suspended. */
|
|
eReturn = eSuspended;
|
|
|
|
for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
|
|
{
|
|
if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
|
|
{
|
|
eReturn = eBlocked;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
|
|
{
|
|
eReturn = eSuspended;
|
|
}
|
|
#endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
|
|
}
|
|
else
|
|
{
|
|
eReturn = eBlocked;
|
|
}
|
|
}
|
|
#endif /* if ( INCLUDE_vTaskSuspend == 1 ) */
|
|
|
|
#if ( INCLUDE_vTaskDelete == 1 )
|
|
else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) )
|
|
{
|
|
/* The task being queried is referenced from the deleted
|
|
* tasks list, or it is not referenced from any lists at
|
|
* all. */
|
|
eReturn = eDeleted;
|
|
}
|
|
#endif
|
|
|
|
else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */
|
|
{
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
/* If the task is not in any other state, it must be in the
|
|
* Ready (including pending ready) state. */
|
|
eReturn = eReady;
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
|
|
{
|
|
/* Is it actively running on a core? */
|
|
eReturn = eRunning;
|
|
}
|
|
else
|
|
{
|
|
/* If the task is not in any other state, it must be in the
|
|
* Ready (including pending ready) state. */
|
|
eReturn = eReady;
|
|
}
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
}
|
|
|
|
return eReturn;
|
|
} /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
|
|
|
|
#endif /* INCLUDE_eTaskGetState */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_uxTaskPriorityGet == 1 )
|
|
|
|
UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )
|
|
{
|
|
TCB_t const * pxTCB;
|
|
UBaseType_t uxReturn;
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
/* If null is passed in here then it is the priority of the task
|
|
* that called uxTaskPriorityGet() that is being queried. */
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
uxReturn = pxTCB->uxPriority;
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
return uxReturn;
|
|
}
|
|
|
|
#endif /* INCLUDE_uxTaskPriorityGet */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_uxTaskPriorityGet == 1 )
|
|
|
|
UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask )
|
|
{
|
|
TCB_t const * pxTCB;
|
|
UBaseType_t uxReturn;
|
|
UBaseType_t uxSavedInterruptStatus;
|
|
|
|
/* RTOS ports that support interrupt nesting have the concept of a
|
|
* maximum system call (or maximum API call) interrupt priority.
|
|
* Interrupts that are above the maximum system call priority are keep
|
|
* permanently enabled, even when the RTOS kernel is in a critical section,
|
|
* but cannot make any calls to FreeRTOS API functions. If configASSERT()
|
|
* is defined in FreeRTOSConfig.h then
|
|
* portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
|
|
* failure if a FreeRTOS API function is called from an interrupt that has
|
|
* been assigned a priority above the configured maximum system call
|
|
* priority. Only FreeRTOS functions that end in FromISR can be called
|
|
* from interrupts that have been assigned a priority at or (logically)
|
|
* below the maximum system call interrupt priority. FreeRTOS maintains a
|
|
* separate interrupt safe API to ensure interrupt entry is as fast and as
|
|
* simple as possible. More information (albeit Cortex-M specific) is
|
|
* provided on the following link:
|
|
* https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
|
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
|
|
|
|
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
|
|
{
|
|
/* If null is passed in here then it is the priority of the calling
|
|
* task that is being queried. */
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
uxReturn = pxTCB->uxPriority;
|
|
}
|
|
taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
|
|
|
|
return uxReturn;
|
|
}
|
|
|
|
#endif /* INCLUDE_uxTaskPriorityGet */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_vTaskPrioritySet == 1 )
|
|
|
|
void vTaskPrioritySet( TaskHandle_t xTask,
|
|
UBaseType_t uxNewPriority )
|
|
{
|
|
TCB_t * pxTCB;
|
|
UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
|
|
BaseType_t xYieldRequired = pdFALSE;
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
BaseType_t xYieldForTask = pdFALSE;
|
|
#endif
|
|
|
|
configASSERT( uxNewPriority < configMAX_PRIORITIES );
|
|
|
|
/* Ensure the new priority is valid. */
|
|
if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
|
|
{
|
|
uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
/* If null is passed in here then it is the priority of the calling
|
|
* task that is being changed. */
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
|
|
traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
|
|
|
|
#if ( configUSE_MUTEXES == 1 )
|
|
{
|
|
uxCurrentBasePriority = pxTCB->uxBasePriority;
|
|
}
|
|
#else
|
|
{
|
|
uxCurrentBasePriority = pxTCB->uxPriority;
|
|
}
|
|
#endif
|
|
|
|
if( uxCurrentBasePriority != uxNewPriority )
|
|
{
|
|
/* The priority change may have readied a task of higher
|
|
* priority than a running task. */
|
|
if( uxNewPriority > uxCurrentBasePriority )
|
|
{
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
if( pxTCB != pxCurrentTCB )
|
|
{
|
|
/* The priority of a task other than the currently
|
|
* running task is being raised. Is the priority being
|
|
* raised above that of the running task? */
|
|
if( uxNewPriority > pxCurrentTCB->uxPriority )
|
|
{
|
|
xYieldRequired = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* The priority of the running task is being raised,
|
|
* but the running task must already be the highest
|
|
* priority task able to run so no yield is required. */
|
|
}
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
/* The priority of a task is being raised so
|
|
* perform a yield for this task later. */
|
|
xYieldForTask = pdTRUE;
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
else if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
|
|
{
|
|
/* Setting the priority of a running task down means
|
|
* there may now be another task of higher priority that
|
|
* is ready to execute. */
|
|
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
|
|
if( pxTCB->xPreemptionDisable == pdFALSE )
|
|
#endif
|
|
{
|
|
xYieldRequired = pdTRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Setting the priority of any other task down does not
|
|
* require a yield as the running task must be above the
|
|
* new priority of the task being modified. */
|
|
}
|
|
|
|
/* Remember the ready list the task might be referenced from
|
|
* before its uxPriority member is changed so the
|
|
* taskRESET_READY_PRIORITY() macro can function correctly. */
|
|
uxPriorityUsedOnEntry = pxTCB->uxPriority;
|
|
|
|
#if ( configUSE_MUTEXES == 1 )
|
|
{
|
|
/* Only change the priority being used if the task is not
|
|
* currently using an inherited priority. */
|
|
if( pxTCB->uxBasePriority == pxTCB->uxPriority )
|
|
{
|
|
pxTCB->uxPriority = uxNewPriority;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* The base priority gets set whatever. */
|
|
pxTCB->uxBasePriority = uxNewPriority;
|
|
}
|
|
#else /* if ( configUSE_MUTEXES == 1 ) */
|
|
{
|
|
pxTCB->uxPriority = uxNewPriority;
|
|
}
|
|
#endif /* if ( configUSE_MUTEXES == 1 ) */
|
|
|
|
/* Only reset the event list item value if the value is not
|
|
* being used for anything else. */
|
|
if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
|
|
{
|
|
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* If the task is in the blocked or suspended list we need do
|
|
* nothing more than change its priority variable. However, if
|
|
* the task is in a ready list it needs to be removed and placed
|
|
* in the list appropriate to its new priority. */
|
|
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
|
|
{
|
|
/* The task is currently in its ready list - remove before
|
|
* adding it to its new ready list. As we are in a critical
|
|
* section we can do this even if the scheduler is suspended. */
|
|
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
|
{
|
|
/* It is known that the task is in its ready list so
|
|
* there is no need to check again and the port level
|
|
* reset macro can be called directly. */
|
|
portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
prvAddTaskToReadyList( pxTCB );
|
|
}
|
|
else
|
|
{
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
#else
|
|
{
|
|
/* It's possible that xYieldForTask was already set to pdTRUE because
|
|
* its priority is being raised. However, since it is not in a ready list
|
|
* we don't actually need to yield for it. */
|
|
xYieldForTask = pdFALSE;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
if( xYieldRequired != pdFALSE )
|
|
{
|
|
taskYIELD_IF_USING_PREEMPTION();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
{
|
|
if( xYieldRequired != pdFALSE )
|
|
{
|
|
prvYieldCore( pxTCB->xTaskRunState );
|
|
}
|
|
else if( xYieldForTask != pdFALSE )
|
|
{
|
|
prvYieldForTask( pxTCB );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#endif /* #if ( configUSE_PREEMPTION == 1 ) */
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
|
|
/* Remove compiler warning about unused variables when the port
|
|
* optimised task selection is not being used. */
|
|
( void ) uxPriorityUsedOnEntry;
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
|
|
#endif /* INCLUDE_vTaskPrioritySet */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
|
void vTaskCoreAffinitySet( const TaskHandle_t xTask,
|
|
UBaseType_t uxCoreAffinityMask )
|
|
{
|
|
TCB_t * pxTCB;
|
|
BaseType_t xCoreID;
|
|
UBaseType_t uxPrevCoreAffinityMask;
|
|
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
UBaseType_t uxPrevNotAllowedCores;
|
|
#endif
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
|
|
uxPrevCoreAffinityMask = pxTCB->uxCoreAffinityMask;
|
|
pxTCB->uxCoreAffinityMask = uxCoreAffinityMask;
|
|
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
|
|
{
|
|
xCoreID = ( BaseType_t ) pxTCB->xTaskRunState;
|
|
|
|
/* If the task can no longer run on the core it was running,
|
|
* request the core to yield. */
|
|
if( ( uxCoreAffinityMask & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) == 0U )
|
|
{
|
|
prvYieldCore( xCoreID );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
{
|
|
/* Calculate the cores on which this task was not allowed to
|
|
* run previously. */
|
|
uxPrevNotAllowedCores = ( ~uxPrevCoreAffinityMask ) & ( ( 1U << configNUMBER_OF_CORES ) - 1U );
|
|
|
|
/* Does the new core mask enables this task to run on any of the
|
|
* previously not allowed cores? If yes, check if this task can be
|
|
* scheduled on any of those cores. */
|
|
if( ( uxPrevNotAllowedCores & uxCoreAffinityMask ) != 0U )
|
|
{
|
|
prvYieldForTask( pxTCB );
|
|
}
|
|
}
|
|
#else /* #if( configUSE_PREEMPTION == 1 ) */
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
#endif /* #if( configUSE_PREEMPTION == 1 ) */
|
|
}
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
|
UBaseType_t vTaskCoreAffinityGet( ConstTaskHandle_t xTask )
|
|
{
|
|
const TCB_t * pxTCB;
|
|
UBaseType_t uxCoreAffinityMask;
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
uxCoreAffinityMask = pxTCB->uxCoreAffinityMask;
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
return uxCoreAffinityMask;
|
|
}
|
|
#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
|
|
|
|
void vTaskPreemptionDisable( const TaskHandle_t xTask )
|
|
{
|
|
TCB_t * pxTCB;
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
|
|
pxTCB->xPreemptionDisable = pdTRUE;
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
|
|
#endif /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
|
|
|
|
void vTaskPreemptionEnable( const TaskHandle_t xTask )
|
|
{
|
|
TCB_t * pxTCB;
|
|
BaseType_t xCoreID;
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
|
|
pxTCB->xPreemptionDisable = pdFALSE;
|
|
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
|
|
{
|
|
xCoreID = ( BaseType_t ) pxTCB->xTaskRunState;
|
|
prvYieldCore( xCoreID );
|
|
}
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
|
|
#endif /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
|
|
void vTaskSuspend( TaskHandle_t xTaskToSuspend )
|
|
{
|
|
TCB_t * pxTCB;
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
TaskRunning_t xTaskRunningOnCore;
|
|
#endif
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
/* If null is passed in here then it is the running task that is
|
|
* being suspended. */
|
|
pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
|
|
|
|
traceTASK_SUSPEND( pxTCB );
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
xTaskRunningOnCore = pxTCB->xTaskRunState;
|
|
#endif
|
|
|
|
/* Remove task from the ready/delayed list and place in the
|
|
* suspended list. */
|
|
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
|
{
|
|
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* Is the task waiting on an event also? */
|
|
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
|
|
{
|
|
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
|
|
|
|
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
|
|
{
|
|
BaseType_t x;
|
|
|
|
for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
|
|
{
|
|
if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
|
|
{
|
|
/* The task was blocked to wait for a notification, but is
|
|
* now suspended, so no notification was received. */
|
|
pxTCB->ucNotifyState[ x ] = taskNOT_WAITING_NOTIFICATION;
|
|
}
|
|
}
|
|
}
|
|
#endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
|
|
}
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
taskEXIT_CRITICAL();
|
|
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
/* Reset the next expected unblock time in case it referred to the
|
|
* task that is now in the Suspended state. */
|
|
taskENTER_CRITICAL();
|
|
{
|
|
prvResetNextTaskUnblockTime();
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
if( pxTCB == pxCurrentTCB )
|
|
{
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
/* The current task has just been suspended. */
|
|
configASSERT( uxSchedulerSuspended == 0 );
|
|
portYIELD_WITHIN_API();
|
|
}
|
|
else
|
|
{
|
|
/* The scheduler is not running, but the task that was pointed
|
|
* to by pxCurrentTCB has just been suspended and pxCurrentTCB
|
|
* must be adjusted to point to a different task. */
|
|
if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) /*lint !e931 Right has no side effect, just volatile. */
|
|
{
|
|
/* No other tasks are ready, so set pxCurrentTCB back to
|
|
* NULL so when the next task is created pxCurrentTCB will
|
|
* be set to point to it no matter what its relative priority
|
|
* is. */
|
|
pxCurrentTCB = NULL;
|
|
}
|
|
else
|
|
{
|
|
vTaskSwitchContext();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
/* Reset the next expected unblock time in case it referred to the
|
|
* task that is now in the Suspended state. */
|
|
prvResetNextTaskUnblockTime();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
|
|
{
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
if( xTaskRunningOnCore == portGET_CORE_ID() )
|
|
{
|
|
/* The current task has just been suspended. */
|
|
configASSERT( uxSchedulerSuspended == 0 );
|
|
vTaskYieldWithinAPI();
|
|
}
|
|
else
|
|
{
|
|
prvYieldCore( xTaskRunningOnCore );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* This code path is not possible because only Idle tasks are
|
|
* assigned a core before the scheduler is started ( i.e.
|
|
* taskTASK_IS_RUNNING is only true for idle tasks before
|
|
* the scheduler is started ) and idle tasks cannot be
|
|
* suspended. */
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
|
|
#endif /* INCLUDE_vTaskSuspend */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
|
|
static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
|
|
{
|
|
BaseType_t xReturn = pdFALSE;
|
|
const TCB_t * const pxTCB = xTask;
|
|
|
|
/* Accesses xPendingReadyList so must be called from a critical
|
|
* section. */
|
|
|
|
/* It does not make sense to check if the calling task is suspended. */
|
|
configASSERT( xTask );
|
|
|
|
/* Is the task being resumed actually in the suspended list? */
|
|
if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )
|
|
{
|
|
/* Has the task already been resumed from within an ISR? */
|
|
if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
|
|
{
|
|
/* Is it in the suspended list because it is in the Suspended
|
|
* state, or because is is blocked with no timeout? */
|
|
if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) /*lint !e961. The cast is only redundant when NULL is used. */
|
|
{
|
|
xReturn = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
return xReturn;
|
|
} /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
|
|
|
|
#endif /* INCLUDE_vTaskSuspend */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
|
|
void vTaskResume( TaskHandle_t xTaskToResume )
|
|
{
|
|
TCB_t * const pxTCB = xTaskToResume;
|
|
|
|
/* It does not make sense to resume the calling task. */
|
|
configASSERT( xTaskToResume );
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
|
|
/* The parameter cannot be NULL as it is impossible to resume the
|
|
* currently executing task. */
|
|
if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) )
|
|
#else
|
|
|
|
/* The parameter cannot be NULL as it is impossible to resume the
|
|
* currently executing task. It is also impossible to resume a task
|
|
* that is actively running on another core but it is not safe
|
|
* to check their run state here. Therefore, we get into a critical
|
|
* section and check if the task is actually suspended or not. */
|
|
if( pxTCB != NULL )
|
|
#endif
|
|
{
|
|
taskENTER_CRITICAL();
|
|
{
|
|
if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
|
|
{
|
|
traceTASK_RESUME( pxTCB );
|
|
|
|
/* The ready list can be accessed even if the scheduler is
|
|
* suspended because this is inside a critical section. */
|
|
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
|
|
prvAddTaskToReadyList( pxTCB );
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
/* A higher priority task may have just been resumed. */
|
|
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
|
|
{
|
|
/* This yield may not cause the task just resumed to run,
|
|
* but will leave the lists in the correct state for the
|
|
* next yield. */
|
|
taskYIELD_IF_USING_PREEMPTION();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
{
|
|
prvYieldForTask( pxTCB );
|
|
}
|
|
#endif /* #if ( configUSE_PREEMPTION == 1 ) */
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
#endif /* INCLUDE_vTaskSuspend */
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
|
|
|
|
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
|
|
{
|
|
BaseType_t xYieldRequired = pdFALSE;
|
|
TCB_t * const pxTCB = xTaskToResume;
|
|
UBaseType_t uxSavedInterruptStatus;
|
|
|
|
configASSERT( xTaskToResume );
|
|
|
|
/* RTOS ports that support interrupt nesting have the concept of a
|
|
* maximum system call (or maximum API call) interrupt priority.
|
|
* Interrupts that are above the maximum system call priority are keep
|
|
* permanently enabled, even when the RTOS kernel is in a critical section,
|
|
* but cannot make any calls to FreeRTOS API functions. If configASSERT()
|
|
* is defined in FreeRTOSConfig.h then
|
|
* portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
|
|
* failure if a FreeRTOS API function is called from an interrupt that has
|
|
* been assigned a priority above the configured maximum system call
|
|
* priority. Only FreeRTOS functions that end in FromISR can be called
|
|
* from interrupts that have been assigned a priority at or (logically)
|
|
* below the maximum system call interrupt priority. FreeRTOS maintains a
|
|
* separate interrupt safe API to ensure interrupt entry is as fast and as
|
|
* simple as possible. More information (albeit Cortex-M specific) is
|
|
* provided on the following link:
|
|
* https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
|
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
|
|
|
|
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
|
|
{
|
|
if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
|
|
{
|
|
traceTASK_RESUME_FROM_ISR( pxTCB );
|
|
|
|
/* Check the ready lists can be accessed. */
|
|
if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
|
|
{
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
/* Ready lists can be accessed so move the task from the
|
|
* suspended list to the ready list directly. */
|
|
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
|
|
{
|
|
xYieldRequired = pdTRUE;
|
|
|
|
/* Mark that a yield is pending in case the user is not
|
|
* using the return value to initiate a context switch
|
|
* from the ISR using portYIELD_FROM_ISR. */
|
|
xYieldPendings[ 0 ] = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
|
|
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
|
|
prvAddTaskToReadyList( pxTCB );
|
|
}
|
|
else
|
|
{
|
|
/* The delayed or ready lists cannot be accessed so the task
|
|
* is held in the pending ready list until the scheduler is
|
|
* unsuspended. */
|
|
vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
|
|
}
|
|
|
|
#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PREEMPTION == 1 ) )
|
|
{
|
|
prvYieldForTask( pxTCB );
|
|
|
|
if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE )
|
|
{
|
|
xYieldRequired = pdTRUE;
|
|
}
|
|
}
|
|
#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PREEMPTION == 1 ) ) */
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
|
|
|
|
return xYieldRequired;
|
|
}
|
|
|
|
#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static BaseType_t prvCreateIdleTasks( void )
|
|
{
|
|
BaseType_t xReturn = pdPASS;
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
/* Add the idle task at the lowest priority. */
|
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
|
{
|
|
StaticTask_t * pxIdleTaskTCBBuffer = NULL;
|
|
StackType_t * pxIdleTaskStackBuffer = NULL;
|
|
uint32_t ulIdleTaskStackSize;
|
|
|
|
/* The Idle task is created using user provided RAM - obtain the
|
|
* address of the RAM then create the idle task. */
|
|
vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
|
|
xIdleTaskHandles[ 0 ] = xTaskCreateStatic( prvIdleTask,
|
|
configIDLE_TASK_NAME,
|
|
ulIdleTaskStackSize,
|
|
( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */
|
|
portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
|
|
pxIdleTaskStackBuffer,
|
|
pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
|
|
|
|
if( xIdleTaskHandles[ 0 ] != NULL )
|
|
{
|
|
xReturn = pdPASS;
|
|
}
|
|
else
|
|
{
|
|
xReturn = pdFAIL;
|
|
}
|
|
}
|
|
#else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
|
|
{
|
|
/* The Idle task is being created using dynamically allocated RAM. */
|
|
xReturn = xTaskCreate( prvIdleTask,
|
|
configIDLE_TASK_NAME,
|
|
configMINIMAL_STACK_SIZE,
|
|
( void * ) NULL,
|
|
portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
|
|
&xIdleTaskHandles[ 0 ] ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
|
|
}
|
|
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
BaseType_t xCoreID;
|
|
char cIdleName[ configMAX_TASK_NAME_LEN ];
|
|
|
|
/* Add each idle task at the lowest priority. */
|
|
for( xCoreID = ( BaseType_t ) 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ )
|
|
{
|
|
BaseType_t x;
|
|
|
|
if( xReturn == pdFAIL )
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configMAX_TASK_NAME_LEN; x++ )
|
|
{
|
|
cIdleName[ x ] = configIDLE_TASK_NAME[ x ];
|
|
|
|
/* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
|
|
* configMAX_TASK_NAME_LEN characters just in case the memory after the
|
|
* string is not accessible (extremely unlikely). */
|
|
if( cIdleName[ x ] == ( char ) 0x00 )
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
/* Append the idle task number to the end of the name if there is space. */
|
|
if( x < ( BaseType_t ) configMAX_TASK_NAME_LEN )
|
|
{
|
|
cIdleName[ x ] = ( char ) ( xCoreID + '0' );
|
|
x++;
|
|
|
|
/* And append a null character if there is space. */
|
|
if( x < ( BaseType_t ) configMAX_TASK_NAME_LEN )
|
|
{
|
|
cIdleName[ x ] = '\0';
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
|
{
|
|
if( xCoreID == 0 )
|
|
{
|
|
StaticTask_t * pxIdleTaskTCBBuffer = NULL;
|
|
StackType_t * pxIdleTaskStackBuffer = NULL;
|
|
uint32_t ulIdleTaskStackSize;
|
|
|
|
/* The Idle task is created using user provided RAM - obtain the
|
|
* address of the RAM then create the idle task. */
|
|
vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
|
|
xIdleTaskHandles[ xCoreID ] = xTaskCreateStatic( prvIdleTask,
|
|
cIdleName,
|
|
ulIdleTaskStackSize,
|
|
( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */
|
|
portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
|
|
pxIdleTaskStackBuffer,
|
|
pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
|
|
}
|
|
else
|
|
{
|
|
xIdleTaskHandles[ xCoreID ] = xTaskCreateStatic( prvMinimalIdleTask,
|
|
cIdleName,
|
|
configMINIMAL_STACK_SIZE,
|
|
( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */
|
|
portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
|
|
xIdleTaskStackBuffers[ xCoreID - 1 ],
|
|
&xIdleTCBBuffers[ xCoreID - 1 ] ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
|
|
}
|
|
|
|
if( xIdleTaskHandles[ xCoreID ] != NULL )
|
|
{
|
|
xReturn = pdPASS;
|
|
}
|
|
else
|
|
{
|
|
xReturn = pdFAIL;
|
|
}
|
|
}
|
|
#else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
|
|
{
|
|
if( xCoreID == 0 )
|
|
{
|
|
/* The Idle task is being created using dynamically allocated RAM. */
|
|
xReturn = xTaskCreate( prvIdleTask,
|
|
cIdleName,
|
|
configMINIMAL_STACK_SIZE,
|
|
( void * ) NULL,
|
|
portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
|
|
&xIdleTaskHandles[ xCoreID ] ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
|
|
}
|
|
else
|
|
{
|
|
xReturn = xTaskCreate( prvMinimalIdleTask,
|
|
cIdleName,
|
|
configMINIMAL_STACK_SIZE,
|
|
( void * ) NULL,
|
|
portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
|
|
&xIdleTaskHandles[ xCoreID ] ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
|
|
}
|
|
}
|
|
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
|
}
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void vTaskStartScheduler( void )
|
|
{
|
|
BaseType_t xReturn;
|
|
|
|
xReturn = prvCreateIdleTasks();
|
|
|
|
#if ( configUSE_TIMERS == 1 )
|
|
{
|
|
if( xReturn == pdPASS )
|
|
{
|
|
xReturn = xTimerCreateTimerTask();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#endif /* configUSE_TIMERS */
|
|
|
|
if( xReturn == pdPASS )
|
|
{
|
|
/* freertos_tasks_c_additions_init() should only be called if the user
|
|
* definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is
|
|
* the only macro called by the function. */
|
|
#ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
|
|
{
|
|
freertos_tasks_c_additions_init();
|
|
}
|
|
#endif
|
|
|
|
/* Interrupts are turned off here, to ensure a tick does not occur
|
|
* before or during the call to xPortStartScheduler(). The stacks of
|
|
* the created tasks contain a status word with interrupts switched on
|
|
* so interrupts will automatically get re-enabled when the first task
|
|
* starts to run. */
|
|
portDISABLE_INTERRUPTS();
|
|
|
|
#if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
|
|
{
|
|
/* Switch C-Runtime's TLS Block to point to the TLS
|
|
* block specific to the task that will run first. */
|
|
configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
|
|
}
|
|
#endif
|
|
|
|
xNextTaskUnblockTime = portMAX_DELAY;
|
|
xSchedulerRunning = pdTRUE;
|
|
xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
|
|
|
|
/* If configGENERATE_RUN_TIME_STATS is defined then the following
|
|
* macro must be defined to configure the timer/counter used to generate
|
|
* the run time counter time base. NOTE: If configGENERATE_RUN_TIME_STATS
|
|
* is set to 0 and the following line fails to build then ensure you do not
|
|
* have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your
|
|
* FreeRTOSConfig.h file. */
|
|
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
|
|
|
|
traceTASK_SWITCHED_IN();
|
|
|
|
/* Setting up the timer tick is hardware specific and thus in the
|
|
* portable interface. */
|
|
xPortStartScheduler();
|
|
|
|
/* In most cases, xPortStartScheduler() will not return. If it
|
|
* returns pdTRUE then there was not enough heap memory available
|
|
* to create either the Idle or the Timer task. If it returned
|
|
* pdFALSE, then the application called xTaskEndScheduler().
|
|
* Most ports don't implement xTaskEndScheduler() as there is
|
|
* nothing to return to. */
|
|
}
|
|
else
|
|
{
|
|
/* This line will only be reached if the kernel could not be started,
|
|
* because there was not enough FreeRTOS heap to create the idle task
|
|
* or the timer task. */
|
|
configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
|
|
}
|
|
|
|
/* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
|
|
* meaning xIdleTaskHandles are not used anywhere else. */
|
|
( void ) xIdleTaskHandles;
|
|
|
|
/* OpenOCD makes use of uxTopUsedPriority for thread debugging. Prevent uxTopUsedPriority
|
|
* from getting optimized out as it is no longer used by the kernel. */
|
|
( void ) uxTopUsedPriority;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void vTaskEndScheduler( void )
|
|
{
|
|
/* Stop the scheduler interrupts and call the portable scheduler end
|
|
* routine so the original ISRs can be restored if necessary. The port
|
|
* layer must ensure interrupts enable bit is left in the correct state. */
|
|
portDISABLE_INTERRUPTS();
|
|
xSchedulerRunning = pdFALSE;
|
|
vPortEndScheduler();
|
|
}
|
|
/*----------------------------------------------------------*/
|
|
|
|
void vTaskSuspendAll( void )
|
|
{
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
/* A critical section is not required as the variable is of type
|
|
* BaseType_t. Please read Richard Barry's reply in the following link to a
|
|
* post in the FreeRTOS support forum before reporting this as a bug! -
|
|
* https://goo.gl/wu4acr */
|
|
|
|
/* portSOFTWARE_BARRIER() is only implemented for emulated/simulated ports that
|
|
* do not otherwise exhibit real time behaviour. */
|
|
portSOFTWARE_BARRIER();
|
|
|
|
/* The scheduler is suspended if uxSchedulerSuspended is non-zero. An increment
|
|
* is used to allow calls to vTaskSuspendAll() to nest. */
|
|
++uxSchedulerSuspended;
|
|
|
|
/* Enforces ordering for ports and optimised compilers that may otherwise place
|
|
* the above increment elsewhere. */
|
|
portMEMORY_BARRIER();
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
UBaseType_t ulState;
|
|
|
|
/* This must only be called from within a task. */
|
|
portASSERT_IF_IN_ISR();
|
|
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
/* Writes to uxSchedulerSuspended must be protected by both the task AND ISR locks.
|
|
* We must disable interrupts before we grab the locks in the event that this task is
|
|
* interrupted and switches context before incrementing uxSchedulerSuspended.
|
|
* It is safe to re-enable interrupts after releasing the ISR lock and incrementing
|
|
* uxSchedulerSuspended since that will prevent context switches. */
|
|
ulState = portSET_INTERRUPT_MASK();
|
|
|
|
/* portSOFRWARE_BARRIER() is only implemented for emulated/simulated ports that
|
|
* do not otherwise exhibit real time behaviour. */
|
|
portSOFTWARE_BARRIER();
|
|
|
|
portGET_TASK_LOCK();
|
|
|
|
/* uxSchedulerSuspended is increased after prvCheckForRunStateChange. The
|
|
* purpose is to prevent altering the variable when fromISR APIs are readying
|
|
* it. */
|
|
if( uxSchedulerSuspended == 0U )
|
|
{
|
|
if( portGET_CRITICAL_NESTING_COUNT() == 0U )
|
|
{
|
|
prvCheckForRunStateChange();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
portGET_ISR_LOCK();
|
|
|
|
/* The scheduler is suspended if uxSchedulerSuspended is non-zero. An increment
|
|
* is used to allow calls to vTaskSuspendAll() to nest. */
|
|
++uxSchedulerSuspended;
|
|
portRELEASE_ISR_LOCK();
|
|
|
|
portCLEAR_INTERRUPT_MASK( ulState );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TICKLESS_IDLE != 0 )
|
|
|
|
static TickType_t prvGetExpectedIdleTime( void )
|
|
{
|
|
TickType_t xReturn;
|
|
UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
|
|
|
|
/* uxHigherPriorityReadyTasks takes care of the case where
|
|
* configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
|
|
* task that are in the Ready state, even though the idle task is
|
|
* running. */
|
|
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
|
|
{
|
|
if( uxTopReadyPriority > tskIDLE_PRIORITY )
|
|
{
|
|
uxHigherPriorityReadyTasks = pdTRUE;
|
|
}
|
|
}
|
|
#else
|
|
{
|
|
const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
|
|
|
|
/* When port optimised task selection is used the uxTopReadyPriority
|
|
* variable is used as a bit map. If bits other than the least
|
|
* significant bit are set then there are tasks that have a priority
|
|
* above the idle priority that are in the Ready state. This takes
|
|
* care of the case where the co-operative scheduler is in use. */
|
|
if( uxTopReadyPriority > uxLeastSignificantBit )
|
|
{
|
|
uxHigherPriorityReadyTasks = pdTRUE;
|
|
}
|
|
}
|
|
#endif /* if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) */
|
|
|
|
if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
|
|
{
|
|
xReturn = 0;
|
|
}
|
|
else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
|
|
{
|
|
/* There are other idle priority tasks in the ready state. If
|
|
* time slicing is used then the very next tick interrupt must be
|
|
* processed. */
|
|
xReturn = 0;
|
|
}
|
|
else if( uxHigherPriorityReadyTasks != pdFALSE )
|
|
{
|
|
/* There are tasks in the Ready state that have a priority above the
|
|
* idle priority. This path can only be reached if
|
|
* configUSE_PREEMPTION is 0. */
|
|
xReturn = 0;
|
|
}
|
|
else
|
|
{
|
|
xReturn = xNextTaskUnblockTime - xTickCount;
|
|
}
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* configUSE_TICKLESS_IDLE */
|
|
/*----------------------------------------------------------*/
|
|
|
|
BaseType_t xTaskResumeAll( void )
|
|
{
|
|
TCB_t * pxTCB = NULL;
|
|
BaseType_t xAlreadyYielded = pdFALSE;
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
if( xSchedulerRunning != pdFALSE )
|
|
#endif
|
|
{
|
|
/* It is possible that an ISR caused a task to be removed from an event
|
|
* list while the scheduler was suspended. If this was the case then the
|
|
* removed task will have been added to the xPendingReadyList. Once the
|
|
* scheduler has been resumed it is safe to move all the pending ready
|
|
* tasks from this list into their appropriate ready list. */
|
|
taskENTER_CRITICAL();
|
|
{
|
|
BaseType_t xCoreID;
|
|
xCoreID = portGET_CORE_ID();
|
|
|
|
/* If uxSchedulerSuspended is zero then this function does not match a
|
|
* previous call to vTaskSuspendAll(). */
|
|
configASSERT( uxSchedulerSuspended != 0U );
|
|
|
|
--uxSchedulerSuspended;
|
|
portRELEASE_TASK_LOCK();
|
|
|
|
if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
|
|
{
|
|
if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
|
|
{
|
|
/* Move any readied tasks from the pending list into the
|
|
* appropriate ready list. */
|
|
while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
|
|
{
|
|
pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); /*lint !e9079 void * is used as this macro is used with timers too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
|
|
listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
|
|
portMEMORY_BARRIER();
|
|
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
|
|
prvAddTaskToReadyList( pxTCB );
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
/* If the moved task has a priority higher than the current
|
|
* task then a yield must be performed. */
|
|
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
|
|
{
|
|
xYieldPendings[ xCoreID ] = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
/* All appropriate tasks yield at the moment a task is added to xPendingReadyList.
|
|
* If the current core yielded then vTaskSwitchContext() has already been called
|
|
* which sets xYieldPendings for the current core to pdTRUE. */
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
|
|
if( pxTCB != NULL )
|
|
{
|
|
/* A task was unblocked while the scheduler was suspended,
|
|
* which may have prevented the next unblock time from being
|
|
* re-calculated, in which case re-calculate it now. Mainly
|
|
* important for low power tickless implementations, where
|
|
* this can prevent an unnecessary exit from low power
|
|
* state. */
|
|
prvResetNextTaskUnblockTime();
|
|
}
|
|
|
|
/* If any ticks occurred while the scheduler was suspended then
|
|
* they should be processed now. This ensures the tick count does
|
|
* not slip, and that any delayed tasks are resumed at the correct
|
|
* time.
|
|
*
|
|
* It should be safe to call xTaskIncrementTick here from any core
|
|
* since we are in a critical section and xTaskIncrementTick itself
|
|
* protects itself within a critical section. Suspending the scheduler
|
|
* from any core causes xTaskIncrementTick to increment uxPendedCounts. */
|
|
{
|
|
TickType_t xPendedCounts = xPendedTicks; /* Non-volatile copy. */
|
|
|
|
if( xPendedCounts > ( TickType_t ) 0U )
|
|
{
|
|
do
|
|
{
|
|
if( xTaskIncrementTick() != pdFALSE )
|
|
{
|
|
/* Other cores are interrupted from
|
|
* within xTaskIncrementTick(). */
|
|
xYieldPendings[ xCoreID ] = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
--xPendedCounts;
|
|
} while( xPendedCounts > ( TickType_t ) 0U );
|
|
|
|
xPendedTicks = 0;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
if( xYieldPendings[ xCoreID ] != pdFALSE )
|
|
{
|
|
#if ( configUSE_PREEMPTION != 0 )
|
|
{
|
|
xAlreadyYielded = pdTRUE;
|
|
}
|
|
#endif /* #if ( configUSE_PREEMPTION != 0 ) */
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
taskYIELD_IF_USING_PREEMPTION();
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
|
|
return xAlreadyYielded;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
TickType_t xTaskGetTickCount( void )
|
|
{
|
|
TickType_t xTicks;
|
|
|
|
/* Critical section required if running on a 16 bit processor. */
|
|
portTICK_TYPE_ENTER_CRITICAL();
|
|
{
|
|
xTicks = xTickCount;
|
|
}
|
|
portTICK_TYPE_EXIT_CRITICAL();
|
|
|
|
return xTicks;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
TickType_t xTaskGetTickCountFromISR( void )
|
|
{
|
|
TickType_t xReturn;
|
|
UBaseType_t uxSavedInterruptStatus;
|
|
|
|
/* RTOS ports that support interrupt nesting have the concept of a maximum
|
|
* system call (or maximum API call) interrupt priority. Interrupts that are
|
|
* above the maximum system call priority are kept permanently enabled, even
|
|
* when the RTOS kernel is in a critical section, but cannot make any calls to
|
|
* FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
|
|
* then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
|
|
* failure if a FreeRTOS API function is called from an interrupt that has been
|
|
* assigned a priority above the configured maximum system call priority.
|
|
* Only FreeRTOS functions that end in FromISR can be called from interrupts
|
|
* that have been assigned a priority at or (logically) below the maximum
|
|
* system call interrupt priority. FreeRTOS maintains a separate interrupt
|
|
* safe API to ensure interrupt entry is as fast and as simple as possible.
|
|
* More information (albeit Cortex-M specific) is provided on the following
|
|
* link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
|
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
|
|
|
|
uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR();
|
|
{
|
|
xReturn = xTickCount;
|
|
}
|
|
portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
|
|
|
|
return xReturn;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
UBaseType_t uxTaskGetNumberOfTasks( void )
|
|
{
|
|
/* A critical section is not required because the variables are of type
|
|
* BaseType_t. */
|
|
return uxCurrentNumberOfTasks;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
|
{
|
|
TCB_t * pxTCB;
|
|
|
|
/* If null is passed in here then the name of the calling task is being
|
|
* queried. */
|
|
pxTCB = prvGetTCBFromHandle( xTaskToQuery );
|
|
configASSERT( pxTCB );
|
|
return &( pxTCB->pcTaskName[ 0 ] );
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_xTaskGetHandle == 1 )
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
|
|
const char pcNameToQuery[] )
|
|
{
|
|
TCB_t * pxNextTCB;
|
|
TCB_t * pxFirstTCB;
|
|
TCB_t * pxReturn = NULL;
|
|
UBaseType_t x;
|
|
char cNextChar;
|
|
BaseType_t xBreakLoop;
|
|
|
|
/* This function is called with the scheduler suspended. */
|
|
|
|
if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
|
|
{
|
|
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
|
|
|
|
do
|
|
{
|
|
listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
|
|
|
|
/* Check each character in the name looking for a match or
|
|
* mismatch. */
|
|
xBreakLoop = pdFALSE;
|
|
|
|
for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
|
|
{
|
|
cNextChar = pxNextTCB->pcTaskName[ x ];
|
|
|
|
if( cNextChar != pcNameToQuery[ x ] )
|
|
{
|
|
/* Characters didn't match. */
|
|
xBreakLoop = pdTRUE;
|
|
}
|
|
else if( cNextChar == ( char ) 0x00 )
|
|
{
|
|
/* Both strings terminated, a match must have been
|
|
* found. */
|
|
pxReturn = pxNextTCB;
|
|
xBreakLoop = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
if( xBreakLoop != pdFALSE )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( pxReturn != NULL )
|
|
{
|
|
/* The handle has been found. */
|
|
break;
|
|
}
|
|
} while( pxNextTCB != pxFirstTCB );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
return pxReturn;
|
|
}
|
|
#else /* if ( configNUMBER_OF_CORES == 1 ) */
|
|
static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
|
|
const char pcNameToQuery[] )
|
|
{
|
|
TCB_t * pxReturn = NULL;
|
|
UBaseType_t x;
|
|
char cNextChar;
|
|
BaseType_t xBreakLoop;
|
|
const ListItem_t * pxEndMarker = listGET_END_MARKER( pxList );
|
|
ListItem_t * pxIterator;
|
|
|
|
/* This function is called with the scheduler suspended. */
|
|
|
|
if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
|
|
{
|
|
for( pxIterator = listGET_HEAD_ENTRY( pxList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) )
|
|
{
|
|
TCB_t * pxTCB = listGET_LIST_ITEM_OWNER( pxIterator );
|
|
|
|
/* Check each character in the name looking for a match or
|
|
* mismatch. */
|
|
xBreakLoop = pdFALSE;
|
|
|
|
for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
|
|
{
|
|
cNextChar = pxTCB->pcTaskName[ x ];
|
|
|
|
if( cNextChar != pcNameToQuery[ x ] )
|
|
{
|
|
/* Characters didn't match. */
|
|
xBreakLoop = pdTRUE;
|
|
}
|
|
else if( cNextChar == ( char ) 0x00 )
|
|
{
|
|
/* Both strings terminated, a match must have been
|
|
* found. */
|
|
pxReturn = pxTCB;
|
|
xBreakLoop = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
if( xBreakLoop != pdFALSE )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( pxReturn != NULL )
|
|
{
|
|
/* The handle has been found. */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
return pxReturn;
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
|
|
#endif /* INCLUDE_xTaskGetHandle */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_xTaskGetHandle == 1 )
|
|
|
|
TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
|
{
|
|
UBaseType_t uxQueue = configMAX_PRIORITIES;
|
|
TCB_t * pxTCB;
|
|
|
|
/* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
|
|
configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
|
|
|
|
vTaskSuspendAll();
|
|
{
|
|
/* Search the ready lists. */
|
|
do
|
|
{
|
|
uxQueue--;
|
|
pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery );
|
|
|
|
if( pxTCB != NULL )
|
|
{
|
|
/* Found the handle. */
|
|
break;
|
|
}
|
|
} while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
|
|
/* Search the delayed lists. */
|
|
if( pxTCB == NULL )
|
|
{
|
|
pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery );
|
|
}
|
|
|
|
if( pxTCB == NULL )
|
|
{
|
|
pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery );
|
|
}
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
{
|
|
if( pxTCB == NULL )
|
|
{
|
|
/* Search the suspended list. */
|
|
pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if ( INCLUDE_vTaskDelete == 1 )
|
|
{
|
|
if( pxTCB == NULL )
|
|
{
|
|
/* Search the deleted list. */
|
|
pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery );
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
( void ) xTaskResumeAll();
|
|
|
|
return pxTCB;
|
|
}
|
|
|
|
#endif /* INCLUDE_xTaskGetHandle */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
|
|
|
BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask,
|
|
StackType_t ** ppuxStackBuffer,
|
|
StaticTask_t ** ppxTaskBuffer )
|
|
{
|
|
BaseType_t xReturn;
|
|
TCB_t * pxTCB;
|
|
|
|
configASSERT( ppuxStackBuffer != NULL );
|
|
configASSERT( ppxTaskBuffer != NULL );
|
|
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
|
|
#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 )
|
|
{
|
|
if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB )
|
|
{
|
|
*ppuxStackBuffer = pxTCB->pxStack;
|
|
*ppxTaskBuffer = ( StaticTask_t * ) pxTCB;
|
|
xReturn = pdTRUE;
|
|
}
|
|
else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
|
|
{
|
|
*ppuxStackBuffer = pxTCB->pxStack;
|
|
*ppxTaskBuffer = NULL;
|
|
xReturn = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
xReturn = pdFALSE;
|
|
}
|
|
}
|
|
#else /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */
|
|
{
|
|
*ppuxStackBuffer = pxTCB->pxStack;
|
|
*ppxTaskBuffer = ( StaticTask_t * ) pxTCB;
|
|
xReturn = pdTRUE;
|
|
}
|
|
#endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
|
|
|
UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
|
|
const UBaseType_t uxArraySize,
|
|
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
|
|
{
|
|
UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
|
|
|
|
vTaskSuspendAll();
|
|
{
|
|
/* Is there a space in the array for each task in the system? */
|
|
if( uxArraySize >= uxCurrentNumberOfTasks )
|
|
{
|
|
/* Fill in an TaskStatus_t structure with information on each
|
|
* task in the Ready state. */
|
|
do
|
|
{
|
|
uxQueue--;
|
|
uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
|
|
} while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
|
|
/* Fill in an TaskStatus_t structure with information on each
|
|
* task in the Blocked state. */
|
|
uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
|
|
uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
|
|
|
|
#if ( INCLUDE_vTaskDelete == 1 )
|
|
{
|
|
/* Fill in an TaskStatus_t structure with information on
|
|
* each task that has been deleted but not yet cleaned up. */
|
|
uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
|
|
}
|
|
#endif
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
{
|
|
/* Fill in an TaskStatus_t structure with information on
|
|
* each task in the Suspended state. */
|
|
uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
|
|
}
|
|
#endif
|
|
|
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
{
|
|
if( pulTotalRunTime != NULL )
|
|
{
|
|
#ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
|
|
portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
|
|
#else
|
|
*pulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
|
|
#endif
|
|
}
|
|
}
|
|
#else /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
|
|
{
|
|
if( pulTotalRunTime != NULL )
|
|
{
|
|
*pulTotalRunTime = 0;
|
|
}
|
|
}
|
|
#endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
( void ) xTaskResumeAll();
|
|
|
|
return uxTask;
|
|
}
|
|
|
|
#endif /* configUSE_TRACE_FACILITY */
|
|
/*----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
|
|
|
|
/* SMP_TODO : This function returns only idle task handle for core 0.
|
|
* Consider to add another function to return the idle task handles. */
|
|
TaskHandle_t xTaskGetIdleTaskHandle( void )
|
|
{
|
|
/* If xTaskGetIdleTaskHandle() is called before the scheduler has been
|
|
* started, then xIdleTaskHandles will be NULL. */
|
|
configASSERT( ( xIdleTaskHandles[ 0 ] != NULL ) );
|
|
return xIdleTaskHandles[ 0 ];
|
|
}
|
|
|
|
#endif /* INCLUDE_xTaskGetIdleTaskHandle */
|
|
/*----------------------------------------------------------*/
|
|
|
|
/* This conditional compilation should use inequality to 0, not equality to 1.
|
|
* This is to ensure vTaskStepTick() is available when user defined low power mode
|
|
* implementations require configUSE_TICKLESS_IDLE to be set to a value other than
|
|
* 1. */
|
|
#if ( configUSE_TICKLESS_IDLE != 0 )
|
|
|
|
void vTaskStepTick( TickType_t xTicksToJump )
|
|
{
|
|
/* Correct the tick count value after a period during which the tick
|
|
* was suppressed. Note this does *not* call the tick hook function for
|
|
* each stepped tick. */
|
|
configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
|
|
|
|
if( ( xTickCount + xTicksToJump ) == xNextTaskUnblockTime )
|
|
{
|
|
/* Arrange for xTickCount to reach xNextTaskUnblockTime in
|
|
* xTaskIncrementTick() when the scheduler resumes. This ensures
|
|
* that any delayed tasks are resumed at the correct time. */
|
|
configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
|
|
configASSERT( xTicksToJump != ( TickType_t ) 0 );
|
|
|
|
/* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
|
|
taskENTER_CRITICAL();
|
|
{
|
|
xPendedTicks++;
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
xTicksToJump--;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
xTickCount += xTicksToJump;
|
|
traceINCREASE_TICK_COUNT( xTicksToJump );
|
|
}
|
|
|
|
#endif /* configUSE_TICKLESS_IDLE */
|
|
/*----------------------------------------------------------*/
|
|
|
|
BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp )
|
|
{
|
|
BaseType_t xYieldOccurred;
|
|
|
|
/* Must not be called with the scheduler suspended as the implementation
|
|
* relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */
|
|
configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U );
|
|
|
|
/* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occurring when
|
|
* the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */
|
|
vTaskSuspendAll();
|
|
|
|
/* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
|
|
taskENTER_CRITICAL();
|
|
{
|
|
xPendedTicks += xTicksToCatchUp;
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
xYieldOccurred = xTaskResumeAll();
|
|
|
|
return xYieldOccurred;
|
|
}
|
|
/*----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_xTaskAbortDelay == 1 )
|
|
|
|
BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
|
|
{
|
|
TCB_t * pxTCB = xTask;
|
|
BaseType_t xReturn;
|
|
|
|
configASSERT( pxTCB );
|
|
|
|
vTaskSuspendAll();
|
|
{
|
|
/* A task can only be prematurely removed from the Blocked state if
|
|
* it is actually in the Blocked state. */
|
|
if( eTaskGetState( xTask ) == eBlocked )
|
|
{
|
|
xReturn = pdPASS;
|
|
|
|
/* Remove the reference to the task from the blocked list. An
|
|
* interrupt won't touch the xStateListItem because the
|
|
* scheduler is suspended. */
|
|
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
|
|
|
|
/* Is the task waiting on an event also? If so remove it from
|
|
* the event list too. Interrupts can touch the event list item,
|
|
* even though the scheduler is suspended, so a critical section
|
|
* is used. */
|
|
taskENTER_CRITICAL();
|
|
{
|
|
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
|
|
{
|
|
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
|
|
|
|
/* This lets the task know it was forcibly removed from the
|
|
* blocked state so it should not re-evaluate its block time and
|
|
* then block again. */
|
|
pxTCB->ucDelayAborted = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
/* Place the unblocked task into the appropriate ready list. */
|
|
prvAddTaskToReadyList( pxTCB );
|
|
|
|
/* A task being unblocked cannot cause an immediate context
|
|
* switch if preemption is turned off. */
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
{
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
/* Preemption is on, but a context switch should only be
|
|
* performed if the unblocked task has a priority that is
|
|
* higher than the currently executing task. */
|
|
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
|
|
{
|
|
/* Pend the yield to be performed when the scheduler
|
|
* is unsuspended. */
|
|
xYieldPendings[ 0 ] = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
taskENTER_CRITICAL();
|
|
{
|
|
prvYieldForTask( pxTCB );
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
#endif /* #if ( configUSE_PREEMPTION == 1 ) */
|
|
}
|
|
else
|
|
{
|
|
xReturn = pdFAIL;
|
|
}
|
|
}
|
|
( void ) xTaskResumeAll();
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* INCLUDE_xTaskAbortDelay */
|
|
/*----------------------------------------------------------*/
|
|
|
|
BaseType_t xTaskIncrementTick( void )
|
|
{
|
|
TCB_t * pxTCB;
|
|
TickType_t xItemValue;
|
|
BaseType_t xSwitchRequired = pdFALSE;
|
|
|
|
#if ( configUSE_PREEMPTION == 1 ) && ( configNUMBER_OF_CORES > 1 )
|
|
BaseType_t xYieldRequiredForCore[ configNUMBER_OF_CORES ] = { pdFALSE };
|
|
#endif /* #if ( configUSE_PREEMPTION == 1 ) && ( configNUMBER_OF_CORES > 1 ) */
|
|
|
|
/* Called by the portable layer each time a tick interrupt occurs.
|
|
* Increments the tick then checks to see if the new tick value will cause any
|
|
* tasks to be unblocked. */
|
|
traceTASK_INCREMENT_TICK( xTickCount );
|
|
|
|
/* Tick increment should occur on every kernel timer event. Core 0 has the
|
|
* responsibility to increment the tick, or increment the pended ticks if the
|
|
* scheduler is suspended. If pended ticks is greater than zero, the core that
|
|
* calls xTaskResumeAll has the responsibility to increment the tick. */
|
|
if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
|
|
{
|
|
/* Minor optimisation. The tick count cannot change in this
|
|
* block. */
|
|
const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
|
|
|
|
/* Increment the RTOS tick, switching the delayed and overflowed
|
|
* delayed lists if it wraps to 0. */
|
|
xTickCount = xConstTickCount;
|
|
|
|
if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */
|
|
{
|
|
taskSWITCH_DELAYED_LISTS();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* See if this tick has made a timeout expire. Tasks are stored in
|
|
* the queue in the order of their wake time - meaning once one task
|
|
* has been found whose block time has not expired there is no need to
|
|
* look any further down the list. */
|
|
if( xConstTickCount >= xNextTaskUnblockTime )
|
|
{
|
|
for( ; ; )
|
|
{
|
|
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
|
|
{
|
|
/* The delayed list is empty. Set xNextTaskUnblockTime
|
|
* to the maximum possible value so it is extremely
|
|
* unlikely that the
|
|
* if( xTickCount >= xNextTaskUnblockTime ) test will pass
|
|
* next time through. */
|
|
xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
/* The delayed list is not empty, get the value of the
|
|
* item at the head of the delayed list. This is the time
|
|
* at which the task at the head of the delayed list must
|
|
* be removed from the Blocked state. */
|
|
pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
|
|
xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
|
|
|
|
if( xConstTickCount < xItemValue )
|
|
{
|
|
/* It is not time to unblock this item yet, but the
|
|
* item value is the time at which the task at the head
|
|
* of the blocked list must be removed from the Blocked
|
|
* state - so record the item value in
|
|
* xNextTaskUnblockTime. */
|
|
xNextTaskUnblockTime = xItemValue;
|
|
break; /*lint !e9011 Code structure here is deemed easier to understand with multiple breaks. */
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* It is time to remove the item from the Blocked state. */
|
|
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
|
|
|
|
/* Is the task waiting on an event also? If so remove
|
|
* it from the event list. */
|
|
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
|
|
{
|
|
listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* Place the unblocked task into the appropriate ready
|
|
* list. */
|
|
prvAddTaskToReadyList( pxTCB );
|
|
|
|
/* A task being unblocked cannot cause an immediate
|
|
* context switch if preemption is turned off. */
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
{
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
/* Preemption is on, but a context switch should
|
|
* only be performed if the unblocked task's
|
|
* priority is higher than the currently executing
|
|
* task.
|
|
* The case of equal priority tasks sharing
|
|
* processing time (which happens when both
|
|
* preemption and time slicing are on) is
|
|
* handled below.*/
|
|
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
|
|
{
|
|
xSwitchRequired = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#else /* #if( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
prvYieldForTask( pxTCB );
|
|
}
|
|
#endif /* #if( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
#endif /* #if ( configUSE_PREEMPTION == 1 ) */
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Tasks of equal priority to the currently running task will share
|
|
* processing time (time slice) if preemption is on, and the application
|
|
* writer has not explicitly turned time slicing off. */
|
|
#if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
|
|
{
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
|
|
{
|
|
xSwitchRequired = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
BaseType_t xCoreID;
|
|
|
|
for( xCoreID = 0; xCoreID < ( ( BaseType_t ) configNUMBER_OF_CORES ); xCoreID++ )
|
|
{
|
|
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCBs[ xCoreID ]->uxPriority ] ) ) > 1 )
|
|
{
|
|
xYieldRequiredForCore[ xCoreID ] = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
#endif /* #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
|
|
|
|
#if ( configUSE_TICK_HOOK == 1 )
|
|
{
|
|
/* Guard against the tick hook being called when the pended tick
|
|
* count is being unwound (when the scheduler is being unlocked). */
|
|
if( xPendedTicks == ( TickType_t ) 0 )
|
|
{
|
|
vApplicationTickHook();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#endif /* configUSE_TICK_HOOK */
|
|
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
{
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
/* For single core the core ID is always 0. */
|
|
if( xYieldPendings[ 0 ] != pdFALSE )
|
|
{
|
|
xSwitchRequired = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
BaseType_t xCoreID, xCurrentCoreID;
|
|
xCurrentCoreID = portGET_CORE_ID();
|
|
|
|
for( xCoreID = 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ )
|
|
{
|
|
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
|
|
if( pxCurrentTCBs[ xCoreID ]->xPreemptionDisable == pdFALSE )
|
|
#endif
|
|
{
|
|
if( ( xYieldRequiredForCore[ xCoreID ] != pdFALSE ) || ( xYieldPendings[ xCoreID ] != pdFALSE ) )
|
|
{
|
|
if( xCoreID == xCurrentCoreID )
|
|
{
|
|
xSwitchRequired = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
prvYieldCore( xCoreID );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
#endif /* #if ( configUSE_PREEMPTION == 1 ) */
|
|
}
|
|
else
|
|
{
|
|
++xPendedTicks;
|
|
|
|
/* The tick hook gets called at regular intervals, even if the
|
|
* scheduler is locked. */
|
|
#if ( configUSE_TICK_HOOK == 1 )
|
|
{
|
|
vApplicationTickHook();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return xSwitchRequired;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
|
|
|
|
void vTaskSetApplicationTaskTag( TaskHandle_t xTask,
|
|
TaskHookFunction_t pxHookFunction )
|
|
{
|
|
TCB_t * xTCB;
|
|
|
|
/* If xTask is NULL then it is the task hook of the calling task that is
|
|
* getting set. */
|
|
if( xTask == NULL )
|
|
{
|
|
xTCB = ( TCB_t * ) pxCurrentTCB;
|
|
}
|
|
else
|
|
{
|
|
xTCB = xTask;
|
|
}
|
|
|
|
/* Save the hook function in the TCB. A critical section is required as
|
|
* the value can be accessed from an interrupt. */
|
|
taskENTER_CRITICAL();
|
|
{
|
|
xTCB->pxTaskTag = pxHookFunction;
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
|
|
#endif /* configUSE_APPLICATION_TASK_TAG */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
|
|
|
|
TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
|
|
{
|
|
TCB_t * pxTCB;
|
|
TaskHookFunction_t xReturn;
|
|
|
|
/* If xTask is NULL then set the calling task's hook. */
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
|
|
/* Save the hook function in the TCB. A critical section is required as
|
|
* the value can be accessed from an interrupt. */
|
|
taskENTER_CRITICAL();
|
|
{
|
|
xReturn = pxTCB->pxTaskTag;
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* configUSE_APPLICATION_TASK_TAG */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
|
|
|
|
TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask )
|
|
{
|
|
TCB_t * pxTCB;
|
|
TaskHookFunction_t xReturn;
|
|
UBaseType_t uxSavedInterruptStatus;
|
|
|
|
/* If xTask is NULL then set the calling task's hook. */
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
|
|
/* Save the hook function in the TCB. A critical section is required as
|
|
* the value can be accessed from an interrupt. */
|
|
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
|
|
{
|
|
xReturn = pxTCB->pxTaskTag;
|
|
}
|
|
taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* configUSE_APPLICATION_TASK_TAG */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
|
|
|
|
BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask,
|
|
void * pvParameter )
|
|
{
|
|
TCB_t * xTCB;
|
|
BaseType_t xReturn;
|
|
|
|
/* If xTask is NULL then we are calling our own task hook. */
|
|
if( xTask == NULL )
|
|
{
|
|
xTCB = pxCurrentTCB;
|
|
}
|
|
else
|
|
{
|
|
xTCB = xTask;
|
|
}
|
|
|
|
if( xTCB->pxTaskTag != NULL )
|
|
{
|
|
xReturn = xTCB->pxTaskTag( pvParameter );
|
|
}
|
|
else
|
|
{
|
|
xReturn = pdFAIL;
|
|
}
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* configUSE_APPLICATION_TASK_TAG */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
void vTaskSwitchContext( void )
|
|
{
|
|
if( uxSchedulerSuspended != ( UBaseType_t ) 0U )
|
|
{
|
|
/* The scheduler is currently suspended - do not allow a context
|
|
* switch. */
|
|
xYieldPendings[ 0 ] = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
xYieldPendings[ 0 ] = pdFALSE;
|
|
traceTASK_SWITCHED_OUT();
|
|
|
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
{
|
|
#ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
|
|
portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime[ 0 ] );
|
|
#else
|
|
ulTotalRunTime[ 0 ] = portGET_RUN_TIME_COUNTER_VALUE();
|
|
#endif
|
|
|
|
/* Add the amount of time the task has been running to the
|
|
* accumulated time so far. The time the task started running was
|
|
* stored in ulTaskSwitchedInTime. Note that there is no overflow
|
|
* protection here so count values are only valid until the timer
|
|
* overflows. The guard against negative values is to protect
|
|
* against suspect run time stat counter implementations - which
|
|
* are provided by the application, not the kernel. */
|
|
if( ulTotalRunTime[ 0 ] > ulTaskSwitchedInTime[ 0 ] )
|
|
{
|
|
pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime[ 0 ] - ulTaskSwitchedInTime[ 0 ] );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
ulTaskSwitchedInTime[ 0 ] = ulTotalRunTime[ 0 ];
|
|
}
|
|
#endif /* configGENERATE_RUN_TIME_STATS */
|
|
|
|
/* Check for stack overflow, if configured. */
|
|
taskCHECK_FOR_STACK_OVERFLOW();
|
|
|
|
/* Before the currently running task is switched out, save its errno. */
|
|
#if ( configUSE_POSIX_ERRNO == 1 )
|
|
{
|
|
pxCurrentTCB->iTaskErrno = FreeRTOS_errno;
|
|
}
|
|
#endif
|
|
|
|
/* Select a new task to run using either the generic C or port
|
|
* optimised asm code. */
|
|
taskSELECT_HIGHEST_PRIORITY_TASK(); /*lint !e9079 void * is used as this macro is used with timers too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
|
|
traceTASK_SWITCHED_IN();
|
|
|
|
/* After the new task is switched in, update the global errno. */
|
|
#if ( configUSE_POSIX_ERRNO == 1 )
|
|
{
|
|
FreeRTOS_errno = pxCurrentTCB->iTaskErrno;
|
|
}
|
|
#endif
|
|
|
|
#if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
|
|
{
|
|
/* Switch C-Runtime's TLS Block to point to the TLS
|
|
* Block specific to this task. */
|
|
configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
#else /* if ( configNUMBER_OF_CORES == 1 ) */
|
|
void vTaskSwitchContext( BaseType_t xCoreID )
|
|
{
|
|
/* Acquire both locks:
|
|
* - The ISR lock protects the ready list from simultaneous access by
|
|
* both other ISRs and tasks.
|
|
* - We also take the task lock to pause here in case another core has
|
|
* suspended the scheduler. We don't want to simply set xYieldPending
|
|
* and move on if another core suspended the scheduler. We should only
|
|
* do that if the current core has suspended the scheduler. */
|
|
|
|
portGET_TASK_LOCK(); /* Must always acquire the task lock first. */
|
|
portGET_ISR_LOCK();
|
|
{
|
|
/* vTaskSwitchContext() must never be called from within a critical section.
|
|
* This is not necessarily true for single core FreeRTOS, but it is for this
|
|
* SMP port. */
|
|
configASSERT( portGET_CRITICAL_NESTING_COUNT() == 0 );
|
|
|
|
if( uxSchedulerSuspended != ( UBaseType_t ) 0U )
|
|
{
|
|
/* The scheduler is currently suspended - do not allow a context
|
|
* switch. */
|
|
xYieldPendings[ xCoreID ] = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
xYieldPendings[ xCoreID ] = pdFALSE;
|
|
traceTASK_SWITCHED_OUT();
|
|
|
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
{
|
|
#ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
|
|
portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime[ xCoreID ] );
|
|
#else
|
|
ulTotalRunTime[ xCoreID ] = portGET_RUN_TIME_COUNTER_VALUE();
|
|
#endif
|
|
|
|
/* Add the amount of time the task has been running to the
|
|
* accumulated time so far. The time the task started running was
|
|
* stored in ulTaskSwitchedInTime. Note that there is no overflow
|
|
* protection here so count values are only valid until the timer
|
|
* overflows. The guard against negative values is to protect
|
|
* against suspect run time stat counter implementations - which
|
|
* are provided by the application, not the kernel. */
|
|
if( ulTotalRunTime[ xCoreID ] > ulTaskSwitchedInTime[ xCoreID ] )
|
|
{
|
|
pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime[ xCoreID ] - ulTaskSwitchedInTime[ xCoreID ] );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
ulTaskSwitchedInTime[ xCoreID ] = ulTotalRunTime[ xCoreID ];
|
|
}
|
|
#endif /* configGENERATE_RUN_TIME_STATS */
|
|
|
|
/* Check for stack overflow, if configured. */
|
|
taskCHECK_FOR_STACK_OVERFLOW();
|
|
|
|
/* Before the currently running task is switched out, save its errno. */
|
|
#if ( configUSE_POSIX_ERRNO == 1 )
|
|
{
|
|
pxCurrentTCB->iTaskErrno = FreeRTOS_errno;
|
|
}
|
|
#endif
|
|
|
|
/* Select a new task to run. */
|
|
prvSelectHighestPriorityTask( xCoreID );
|
|
traceTASK_SWITCHED_IN();
|
|
|
|
/* After the new task is switched in, update the global errno. */
|
|
#if ( configUSE_POSIX_ERRNO == 1 )
|
|
{
|
|
FreeRTOS_errno = pxCurrentTCB->iTaskErrno;
|
|
}
|
|
#endif
|
|
|
|
#if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
|
|
{
|
|
/* Switch C-Runtime's TLS Block to point to the TLS
|
|
* Block specific to this task. */
|
|
configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
portRELEASE_ISR_LOCK();
|
|
portRELEASE_TASK_LOCK();
|
|
}
|
|
#endif /* if ( configNUMBER_OF_CORES > 1 ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void vTaskPlaceOnEventList( List_t * const pxEventList,
|
|
const TickType_t xTicksToWait )
|
|
{
|
|
configASSERT( pxEventList );
|
|
|
|
/* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
|
|
* SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
|
|
|
|
/* Place the event list item of the TCB in the appropriate event list.
|
|
* This is placed in the list in priority order so the highest priority task
|
|
* is the first to be woken by the event.
|
|
*
|
|
* Note: Lists are sorted in ascending order by ListItem_t.xItemValue.
|
|
* Normally, the xItemValue of a TCB's ListItem_t members is:
|
|
* xItemValue = ( configMAX_PRIORITIES - uxPriority )
|
|
* Therefore, the event list is sorted in descending priority order.
|
|
*
|
|
* The queue that contains the event list is locked, preventing
|
|
* simultaneous access from interrupts. */
|
|
vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
|
|
|
|
prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,
|
|
const TickType_t xItemValue,
|
|
const TickType_t xTicksToWait )
|
|
{
|
|
configASSERT( pxEventList );
|
|
|
|
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
|
|
* the event groups implementation. */
|
|
configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
|
|
|
|
/* Store the item value in the event list item. It is safe to access the
|
|
* event list item here as interrupts won't access the event list item of a
|
|
* task that is not in the Blocked state. */
|
|
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
|
|
|
|
/* Place the event list item of the TCB at the end of the appropriate event
|
|
* list. It is safe to access the event list here because it is part of an
|
|
* event group implementation - and interrupts don't access event groups
|
|
* directly (instead they access them indirectly by pending function calls to
|
|
* the task level). */
|
|
listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
|
|
|
|
prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TIMERS == 1 )
|
|
|
|
void vTaskPlaceOnEventListRestricted( List_t * const pxEventList,
|
|
TickType_t xTicksToWait,
|
|
const BaseType_t xWaitIndefinitely )
|
|
{
|
|
configASSERT( pxEventList );
|
|
|
|
/* This function should not be called by application code hence the
|
|
* 'Restricted' in its name. It is not part of the public API. It is
|
|
* designed for use by kernel code, and has special calling requirements -
|
|
* it should be called with the scheduler suspended. */
|
|
|
|
|
|
/* Place the event list item of the TCB in the appropriate event list.
|
|
* In this case it is assume that this is the only task that is going to
|
|
* be waiting on this event list, so the faster vListInsertEnd() function
|
|
* can be used in place of vListInsert. */
|
|
listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
|
|
|
|
/* If the task should block indefinitely then set the block time to a
|
|
* value that will be recognised as an indefinite delay inside the
|
|
* prvAddCurrentTaskToDelayedList() function. */
|
|
if( xWaitIndefinitely != pdFALSE )
|
|
{
|
|
xTicksToWait = portMAX_DELAY;
|
|
}
|
|
|
|
traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );
|
|
prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );
|
|
}
|
|
|
|
#endif /* configUSE_TIMERS */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
|
|
{
|
|
TCB_t * pxUnblockedTCB;
|
|
BaseType_t xReturn;
|
|
|
|
/* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
|
|
* called from a critical section within an ISR. */
|
|
|
|
/* The event list is sorted in priority order, so the first in the list can
|
|
* be removed as it is known to be the highest priority. Remove the TCB from
|
|
* the delayed list, and add it to the ready list.
|
|
*
|
|
* If an event is for a queue that is locked then this function will never
|
|
* get called - the lock count on the queue will get modified instead. This
|
|
* means exclusive access to the event list is guaranteed here.
|
|
*
|
|
* This function assumes that a check has already been made to ensure that
|
|
* pxEventList is not empty. */
|
|
pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
|
|
configASSERT( pxUnblockedTCB );
|
|
listREMOVE_ITEM( &( pxUnblockedTCB->xEventListItem ) );
|
|
|
|
if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
|
|
{
|
|
listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
|
|
prvAddTaskToReadyList( pxUnblockedTCB );
|
|
|
|
#if ( configUSE_TICKLESS_IDLE != 0 )
|
|
{
|
|
/* If a task is blocked on a kernel object then xNextTaskUnblockTime
|
|
* might be set to the blocked task's time out time. If the task is
|
|
* unblocked for a reason other than a timeout xNextTaskUnblockTime is
|
|
* normally left unchanged, because it is automatically reset to a new
|
|
* value when the tick count equals xNextTaskUnblockTime. However if
|
|
* tickless idling is used it might be more important to enter sleep mode
|
|
* at the earliest possible time - so reset xNextTaskUnblockTime here to
|
|
* ensure it is updated at the earliest possible time. */
|
|
prvResetNextTaskUnblockTime();
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
/* The delayed and ready lists cannot be accessed, so hold this task
|
|
* pending until the scheduler is resumed. */
|
|
listINSERT_END( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
|
|
}
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
|
|
{
|
|
/* Return true if the task removed from the event list has a higher
|
|
* priority than the calling task. This allows the calling task to know if
|
|
* it should force a context switch now. */
|
|
xReturn = pdTRUE;
|
|
|
|
/* Mark that a yield is pending in case the user is not using the
|
|
* "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
|
|
xYieldPendings[ 0 ] = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
xReturn = pdFALSE;
|
|
}
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
xReturn = pdFALSE;
|
|
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
{
|
|
prvYieldForTask( pxUnblockedTCB );
|
|
|
|
if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE )
|
|
{
|
|
xReturn = pdTRUE;
|
|
}
|
|
}
|
|
#endif /* #if ( configUSE_PREEMPTION == 1 ) */
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
|
|
return xReturn;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
|
|
const TickType_t xItemValue )
|
|
{
|
|
TCB_t * pxUnblockedTCB;
|
|
|
|
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
|
|
* the event flags implementation. */
|
|
configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
|
|
|
|
/* Store the new item value in the event list. */
|
|
listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
|
|
|
|
/* Remove the event list form the event flag. Interrupts do not access
|
|
* event flags. */
|
|
pxUnblockedTCB = listGET_LIST_ITEM_OWNER( pxEventListItem ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
|
|
configASSERT( pxUnblockedTCB );
|
|
listREMOVE_ITEM( pxEventListItem );
|
|
|
|
#if ( configUSE_TICKLESS_IDLE != 0 )
|
|
{
|
|
/* If a task is blocked on a kernel object then xNextTaskUnblockTime
|
|
* might be set to the blocked task's time out time. If the task is
|
|
* unblocked for a reason other than a timeout xNextTaskUnblockTime is
|
|
* normally left unchanged, because it is automatically reset to a new
|
|
* value when the tick count equals xNextTaskUnblockTime. However if
|
|
* tickless idling is used it might be more important to enter sleep mode
|
|
* at the earliest possible time - so reset xNextTaskUnblockTime here to
|
|
* ensure it is updated at the earliest possible time. */
|
|
prvResetNextTaskUnblockTime();
|
|
}
|
|
#endif
|
|
|
|
/* Remove the task from the delayed list and add it to the ready list. The
|
|
* scheduler is suspended so interrupts will not be accessing the ready
|
|
* lists. */
|
|
listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
|
|
prvAddTaskToReadyList( pxUnblockedTCB );
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
|
|
{
|
|
/* The unblocked task has a priority above that of the calling task, so
|
|
* a context switch is required. This function is called with the
|
|
* scheduler suspended so xYieldPending is set so the context switch
|
|
* occurs immediately that the scheduler is resumed (unsuspended). */
|
|
xYieldPendings[ 0 ] = pdTRUE;
|
|
}
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
{
|
|
taskENTER_CRITICAL();
|
|
{
|
|
prvYieldForTask( pxUnblockedTCB );
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
#endif
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
|
|
{
|
|
configASSERT( pxTimeOut );
|
|
taskENTER_CRITICAL();
|
|
{
|
|
pxTimeOut->xOverflowCount = xNumOfOverflows;
|
|
pxTimeOut->xTimeOnEntering = xTickCount;
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut )
|
|
{
|
|
/* For internal use only as it does not use a critical section. */
|
|
pxTimeOut->xOverflowCount = xNumOfOverflows;
|
|
pxTimeOut->xTimeOnEntering = xTickCount;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
|
|
TickType_t * const pxTicksToWait )
|
|
{
|
|
BaseType_t xReturn;
|
|
|
|
configASSERT( pxTimeOut );
|
|
configASSERT( pxTicksToWait );
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
/* Minor optimisation. The tick count cannot change in this block. */
|
|
const TickType_t xConstTickCount = xTickCount;
|
|
const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;
|
|
|
|
#if ( INCLUDE_xTaskAbortDelay == 1 )
|
|
if( pxCurrentTCB->ucDelayAborted != ( uint8_t ) pdFALSE )
|
|
{
|
|
/* The delay was aborted, which is not the same as a time out,
|
|
* but has the same result. */
|
|
pxCurrentTCB->ucDelayAborted = pdFALSE;
|
|
xReturn = pdTRUE;
|
|
}
|
|
else
|
|
#endif
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
if( *pxTicksToWait == portMAX_DELAY )
|
|
{
|
|
/* If INCLUDE_vTaskSuspend is set to 1 and the block time
|
|
* specified is the maximum block time then the task should block
|
|
* indefinitely, and therefore never time out. */
|
|
xReturn = pdFALSE;
|
|
}
|
|
else
|
|
#endif
|
|
|
|
if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
|
|
{
|
|
/* The tick count is greater than the time at which
|
|
* vTaskSetTimeout() was called, but has also overflowed since
|
|
* vTaskSetTimeOut() was called. It must have wrapped all the way
|
|
* around and gone past again. This passed since vTaskSetTimeout()
|
|
* was called. */
|
|
xReturn = pdTRUE;
|
|
*pxTicksToWait = ( TickType_t ) 0;
|
|
}
|
|
else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
|
|
{
|
|
/* Not a genuine timeout. Adjust parameters for time remaining. */
|
|
*pxTicksToWait -= xElapsedTime;
|
|
vTaskInternalSetTimeOutState( pxTimeOut );
|
|
xReturn = pdFALSE;
|
|
}
|
|
else
|
|
{
|
|
*pxTicksToWait = ( TickType_t ) 0;
|
|
xReturn = pdTRUE;
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
return xReturn;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void vTaskMissedYield( void )
|
|
{
|
|
/* Must be called from within a critical section. */
|
|
xYieldPendings[ portGET_CORE_ID() ] = pdTRUE;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
|
|
|
UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
|
|
{
|
|
UBaseType_t uxReturn;
|
|
TCB_t const * pxTCB;
|
|
|
|
if( xTask != NULL )
|
|
{
|
|
pxTCB = xTask;
|
|
uxReturn = pxTCB->uxTaskNumber;
|
|
}
|
|
else
|
|
{
|
|
uxReturn = 0U;
|
|
}
|
|
|
|
return uxReturn;
|
|
}
|
|
|
|
#endif /* configUSE_TRACE_FACILITY */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
|
|
|
void vTaskSetTaskNumber( TaskHandle_t xTask,
|
|
const UBaseType_t uxHandle )
|
|
{
|
|
TCB_t * pxTCB;
|
|
|
|
if( xTask != NULL )
|
|
{
|
|
pxTCB = xTask;
|
|
pxTCB->uxTaskNumber = uxHandle;
|
|
}
|
|
}
|
|
|
|
#endif /* configUSE_TRACE_FACILITY */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*
|
|
* -----------------------------------------------------------
|
|
* The MinimalIdle task.
|
|
* ----------------------------------------------------------
|
|
*
|
|
* The minimal idle task is used for all the additional cores in a SMP
|
|
* system. There must be only 1 idle task and the rest are minimal idle
|
|
* tasks.
|
|
*
|
|
* The portTASK_FUNCTION() macro is used to allow port/compiler specific
|
|
* language extensions. The equivalent prototype for this function is:
|
|
*
|
|
* void prvMinimalIdleTask( void *pvParameters );
|
|
*/
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
static portTASK_FUNCTION( prvMinimalIdleTask, pvParameters )
|
|
{
|
|
( void ) pvParameters;
|
|
|
|
taskYIELD();
|
|
|
|
while( INFINITE_LOOP() )
|
|
{
|
|
#if ( configUSE_PREEMPTION == 0 )
|
|
{
|
|
/* If we are not using preemption we keep forcing a task switch to
|
|
* see if any other task has become available. If we are using
|
|
* preemption we don't need to do this as any task becoming available
|
|
* will automatically get the processor anyway. */
|
|
taskYIELD();
|
|
}
|
|
#endif /* configUSE_PREEMPTION */
|
|
|
|
#if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
|
|
{
|
|
/* When using preemption tasks of equal priority will be
|
|
* timesliced. If a task that is sharing the idle priority is ready
|
|
* to run then the idle task should yield before the end of the
|
|
* timeslice.
|
|
*
|
|
* A critical region is not required here as we are just reading from
|
|
* the list, and an occasional incorrect value will not matter. If
|
|
* the ready list at the idle priority contains one more task than the
|
|
* number of idle tasks, which is equal to the configured numbers of cores
|
|
* then a task other than the idle task is ready to execute. */
|
|
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES )
|
|
{
|
|
taskYIELD();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
|
|
|
|
#if ( configUSE_MINIMAL_IDLE_HOOK == 1 )
|
|
{
|
|
/* Call the user defined function from within the idle task. This
|
|
* allows the application designer to add background functionality
|
|
* without the overhead of a separate task.
|
|
*
|
|
* This hook is intended to manage core activity such as disabling cores that go idle.
|
|
*
|
|
* NOTE: vApplicationMinimalIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
|
|
* CALL A FUNCTION THAT MIGHT BLOCK. */
|
|
vApplicationMinimalIdleHook();
|
|
}
|
|
#endif /* configUSE_MINIMAL_IDLE_HOOK */
|
|
}
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
|
|
/*
|
|
* -----------------------------------------------------------
|
|
* The Idle task.
|
|
* ----------------------------------------------------------
|
|
*
|
|
* The portTASK_FUNCTION() macro is used to allow port/compiler specific
|
|
* language extensions. The equivalent prototype for this function is:
|
|
*
|
|
* void prvIdleTask( void *pvParameters );
|
|
*
|
|
*/
|
|
|
|
static portTASK_FUNCTION( prvIdleTask, pvParameters )
|
|
{
|
|
/* Stop warnings. */
|
|
( void ) pvParameters;
|
|
|
|
/** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
|
|
* SCHEDULER IS STARTED. **/
|
|
|
|
/* In case a task that has a secure context deletes itself, in which case
|
|
* the idle task is responsible for deleting the task's secure context, if
|
|
* any. */
|
|
portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE );
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
{
|
|
/* SMP all cores start up in the idle task. This initial yield gets the application
|
|
* tasks started. */
|
|
taskYIELD();
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
|
|
while( INFINITE_LOOP() )
|
|
{
|
|
/* See if any tasks have deleted themselves - if so then the idle task
|
|
* is responsible for freeing the deleted task's TCB and stack. */
|
|
prvCheckTasksWaitingTermination();
|
|
|
|
#if ( configUSE_PREEMPTION == 0 )
|
|
{
|
|
/* If we are not using preemption we keep forcing a task switch to
|
|
* see if any other task has become available. If we are using
|
|
* preemption we don't need to do this as any task becoming available
|
|
* will automatically get the processor anyway. */
|
|
taskYIELD();
|
|
}
|
|
#endif /* configUSE_PREEMPTION */
|
|
|
|
#if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
|
|
{
|
|
/* When using preemption tasks of equal priority will be
|
|
* timesliced. If a task that is sharing the idle priority is ready
|
|
* to run then the idle task should yield before the end of the
|
|
* timeslice.
|
|
*
|
|
* A critical region is not required here as we are just reading from
|
|
* the list, and an occasional incorrect value will not matter. If
|
|
* the ready list at the idle priority contains one more task than the
|
|
* number of idle tasks, which is equal to the configured numbers of cores
|
|
* then a task other than the idle task is ready to execute. */
|
|
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES )
|
|
{
|
|
taskYIELD();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
|
|
|
|
#if ( configUSE_IDLE_HOOK == 1 )
|
|
{
|
|
/* Call the user defined function from within the idle task. */
|
|
vApplicationIdleHook();
|
|
}
|
|
#endif /* configUSE_IDLE_HOOK */
|
|
|
|
/* This conditional compilation should use inequality to 0, not equality
|
|
* to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
|
|
* user defined low power mode implementations require
|
|
* configUSE_TICKLESS_IDLE to be set to a value other than 1. */
|
|
#if ( configUSE_TICKLESS_IDLE != 0 )
|
|
{
|
|
TickType_t xExpectedIdleTime;
|
|
|
|
/* It is not desirable to suspend then resume the scheduler on
|
|
* each iteration of the idle task. Therefore, a preliminary
|
|
* test of the expected idle time is performed without the
|
|
* scheduler suspended. The result here is not necessarily
|
|
* valid. */
|
|
xExpectedIdleTime = prvGetExpectedIdleTime();
|
|
|
|
if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
|
|
{
|
|
vTaskSuspendAll();
|
|
{
|
|
/* Now the scheduler is suspended, the expected idle
|
|
* time can be sampled again, and this time its value can
|
|
* be used. */
|
|
configASSERT( xNextTaskUnblockTime >= xTickCount );
|
|
xExpectedIdleTime = prvGetExpectedIdleTime();
|
|
|
|
/* Define the following macro to set xExpectedIdleTime to 0
|
|
* if the application does not want
|
|
* portSUPPRESS_TICKS_AND_SLEEP() to be called. */
|
|
configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime );
|
|
|
|
if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
|
|
{
|
|
traceLOW_POWER_IDLE_BEGIN();
|
|
portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
|
|
traceLOW_POWER_IDLE_END();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
( void ) xTaskResumeAll();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#endif /* configUSE_TICKLESS_IDLE */
|
|
|
|
#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_MINIMAL_IDLE_HOOK == 1 ) )
|
|
{
|
|
/* Call the user defined function from within the idle task. This
|
|
* allows the application designer to add background functionality
|
|
* without the overhead of a separate task.
|
|
*
|
|
* This hook is intended to manage core activity such as disabling cores that go idle.
|
|
*
|
|
* NOTE: vApplicationMinimalIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
|
|
* CALL A FUNCTION THAT MIGHT BLOCK. */
|
|
vApplicationMinimalIdleHook();
|
|
}
|
|
#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_MINIMAL_IDLE_HOOK == 1 ) ) */
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TICKLESS_IDLE != 0 )
|
|
|
|
eSleepModeStatus eTaskConfirmSleepModeStatus( void )
|
|
{
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
/* The idle task exists in addition to the application tasks. */
|
|
const UBaseType_t uxNonApplicationTasks = 1;
|
|
#endif /* INCLUDE_vTaskSuspend */
|
|
|
|
eSleepModeStatus eReturn = eStandardSleep;
|
|
|
|
/* This function must be called from a critical section. */
|
|
|
|
if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
|
|
{
|
|
/* A task was made ready while the scheduler was suspended. */
|
|
eReturn = eAbortSleep;
|
|
}
|
|
else if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE )
|
|
{
|
|
/* A yield was pended while the scheduler was suspended. */
|
|
eReturn = eAbortSleep;
|
|
}
|
|
else if( xPendedTicks != 0 )
|
|
{
|
|
/* A tick interrupt has already occurred but was held pending
|
|
* because the scheduler is suspended. */
|
|
eReturn = eAbortSleep;
|
|
}
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
else if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
|
|
{
|
|
/* If all the tasks are in the suspended list (which might mean they
|
|
* have an infinite block time rather than actually being suspended)
|
|
* then it is safe to turn all clocks off and just wait for external
|
|
* interrupts. */
|
|
eReturn = eNoTasksWaitingTimeout;
|
|
}
|
|
#endif /* INCLUDE_vTaskSuspend */
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
return eReturn;
|
|
}
|
|
|
|
#endif /* configUSE_TICKLESS_IDLE */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
|
|
|
|
void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
|
|
BaseType_t xIndex,
|
|
void * pvValue )
|
|
{
|
|
TCB_t * pxTCB;
|
|
|
|
if( ( xIndex >= 0 ) &&
|
|
( xIndex < ( BaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS ) )
|
|
{
|
|
pxTCB = prvGetTCBFromHandle( xTaskToSet );
|
|
configASSERT( pxTCB != NULL );
|
|
pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
|
|
}
|
|
}
|
|
|
|
#endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
|
|
|
|
void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
|
|
BaseType_t xIndex )
|
|
{
|
|
void * pvReturn = NULL;
|
|
TCB_t * pxTCB;
|
|
|
|
if( ( xIndex >= 0 ) &&
|
|
( xIndex < ( BaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS ) )
|
|
{
|
|
pxTCB = prvGetTCBFromHandle( xTaskToQuery );
|
|
pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ];
|
|
}
|
|
else
|
|
{
|
|
pvReturn = NULL;
|
|
}
|
|
|
|
return pvReturn;
|
|
}
|
|
|
|
#endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( portUSING_MPU_WRAPPERS == 1 )
|
|
|
|
void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify,
|
|
const MemoryRegion_t * const pxRegions )
|
|
{
|
|
TCB_t * pxTCB;
|
|
|
|
/* If null is passed in here then we are modifying the MPU settings of
|
|
* the calling task. */
|
|
pxTCB = prvGetTCBFromHandle( xTaskToModify );
|
|
|
|
vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), pxRegions, NULL, 0 );
|
|
}
|
|
|
|
#endif /* portUSING_MPU_WRAPPERS */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static void prvInitialiseTaskLists( void )
|
|
{
|
|
UBaseType_t uxPriority;
|
|
|
|
for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
|
|
{
|
|
vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
|
|
}
|
|
|
|
vListInitialise( &xDelayedTaskList1 );
|
|
vListInitialise( &xDelayedTaskList2 );
|
|
vListInitialise( &xPendingReadyList );
|
|
|
|
#if ( INCLUDE_vTaskDelete == 1 )
|
|
{
|
|
vListInitialise( &xTasksWaitingTermination );
|
|
}
|
|
#endif /* INCLUDE_vTaskDelete */
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
{
|
|
vListInitialise( &xSuspendedTaskList );
|
|
}
|
|
#endif /* INCLUDE_vTaskSuspend */
|
|
|
|
/* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
|
|
* using list2. */
|
|
pxDelayedTaskList = &xDelayedTaskList1;
|
|
pxOverflowDelayedTaskList = &xDelayedTaskList2;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static void prvCheckTasksWaitingTermination( void )
|
|
{
|
|
/** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
|
|
|
|
#if ( INCLUDE_vTaskDelete == 1 )
|
|
{
|
|
TCB_t * pxTCB;
|
|
|
|
/* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL()
|
|
* being called too often in the idle task. */
|
|
while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
|
|
{
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
taskENTER_CRITICAL();
|
|
{
|
|
{
|
|
pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); /*lint !e9079 void * is used as this macro is used with timers too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
|
|
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
|
|
--uxCurrentNumberOfTasks;
|
|
--uxDeletedTasksWaitingCleanUp;
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
prvDeleteTCB( pxTCB );
|
|
}
|
|
#else /* #if( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
pxTCB = NULL;
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
/* For SMP, multiple idles can be running simultaneously
|
|
* and we need to check that other idles did not cleanup while we were
|
|
* waiting to enter the critical section. */
|
|
if( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
|
|
{
|
|
pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); /*lint !e9079 void * is used as this macro is used with timers too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
|
|
|
|
if( pxTCB->xTaskRunState == taskTASK_NOT_RUNNING )
|
|
{
|
|
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
|
|
--uxCurrentNumberOfTasks;
|
|
--uxDeletedTasksWaitingCleanUp;
|
|
}
|
|
else
|
|
{
|
|
/* The TCB to be deleted still has not yet been switched out
|
|
* by the scheduler, so we will just exit this loop early and
|
|
* try again next time. */
|
|
taskEXIT_CRITICAL();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
if( pxTCB != NULL )
|
|
{
|
|
prvDeleteTCB( pxTCB );
|
|
}
|
|
}
|
|
#endif /* #if( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
}
|
|
#endif /* INCLUDE_vTaskDelete */
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
|
|
|
void vTaskGetInfo( TaskHandle_t xTask,
|
|
TaskStatus_t * pxTaskStatus,
|
|
BaseType_t xGetFreeStackSpace,
|
|
eTaskState eState )
|
|
{
|
|
TCB_t * pxTCB;
|
|
|
|
/* xTask is NULL then get the state of the calling task. */
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
|
|
pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB;
|
|
pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName[ 0 ] );
|
|
pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority;
|
|
pxTaskStatus->pxStackBase = pxTCB->pxStack;
|
|
#if ( ( portSTACK_GROWTH > 0 ) && ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
|
|
pxTaskStatus->pxTopOfStack = pxTCB->pxTopOfStack;
|
|
pxTaskStatus->pxEndOfStack = pxTCB->pxEndOfStack;
|
|
#endif
|
|
pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;
|
|
|
|
#if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
|
{
|
|
pxTaskStatus->uxCoreAffinityMask = pxTCB->uxCoreAffinityMask;
|
|
}
|
|
#endif
|
|
|
|
#if ( configUSE_MUTEXES == 1 )
|
|
{
|
|
pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
|
|
}
|
|
#else
|
|
{
|
|
pxTaskStatus->uxBasePriority = 0;
|
|
}
|
|
#endif
|
|
|
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
{
|
|
pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;
|
|
}
|
|
#else
|
|
{
|
|
pxTaskStatus->ulRunTimeCounter = ( configRUN_TIME_COUNTER_TYPE ) 0;
|
|
}
|
|
#endif
|
|
|
|
/* Obtaining the task state is a little fiddly, so is only done if the
|
|
* value of eState passed into this function is eInvalid - otherwise the
|
|
* state is just set to whatever is passed in. */
|
|
if( eState != eInvalid )
|
|
{
|
|
if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
|
|
{
|
|
pxTaskStatus->eCurrentState = eRunning;
|
|
}
|
|
else
|
|
{
|
|
pxTaskStatus->eCurrentState = eState;
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
{
|
|
/* If the task is in the suspended list then there is a
|
|
* chance it is actually just blocked indefinitely - so really
|
|
* it should be reported as being in the Blocked state. */
|
|
if( eState == eSuspended )
|
|
{
|
|
vTaskSuspendAll();
|
|
{
|
|
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
|
|
{
|
|
pxTaskStatus->eCurrentState = eBlocked;
|
|
}
|
|
}
|
|
( void ) xTaskResumeAll();
|
|
}
|
|
}
|
|
#endif /* INCLUDE_vTaskSuspend */
|
|
|
|
/* Tasks can be in pending ready list and other state list at the
|
|
* same time. These tasks are in ready state no matter what state
|
|
* list the task is in. */
|
|
taskENTER_CRITICAL();
|
|
{
|
|
if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdFALSE )
|
|
{
|
|
pxTaskStatus->eCurrentState = eReady;
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pxTaskStatus->eCurrentState = eTaskGetState( pxTCB );
|
|
}
|
|
|
|
/* Obtaining the stack space takes some time, so the xGetFreeStackSpace
|
|
* parameter is provided to allow it to be skipped. */
|
|
if( xGetFreeStackSpace != pdFALSE )
|
|
{
|
|
#if ( portSTACK_GROWTH > 0 )
|
|
{
|
|
pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );
|
|
}
|
|
#else
|
|
{
|
|
pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
pxTaskStatus->usStackHighWaterMark = 0;
|
|
}
|
|
}
|
|
|
|
#endif /* configUSE_TRACE_FACILITY */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
|
|
|
static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
|
|
List_t * pxList,
|
|
eTaskState eState )
|
|
{
|
|
configLIST_VOLATILE TCB_t * pxNextTCB;
|
|
configLIST_VOLATILE TCB_t * pxFirstTCB;
|
|
UBaseType_t uxTask = 0;
|
|
|
|
if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
|
|
{
|
|
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
|
|
|
|
/* Populate an TaskStatus_t structure within the
|
|
* pxTaskStatusArray array for each task that is referenced from
|
|
* pxList. See the definition of TaskStatus_t in task.h for the
|
|
* meaning of each TaskStatus_t structure member. */
|
|
do
|
|
{
|
|
listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
|
|
vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
|
|
uxTask++;
|
|
} while( pxNextTCB != pxFirstTCB );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
return uxTask;
|
|
}
|
|
|
|
#endif /* configUSE_TRACE_FACILITY */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
|
|
|
|
static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
|
|
{
|
|
uint32_t ulCount = 0U;
|
|
|
|
while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
|
|
{
|
|
pucStackByte -= portSTACK_GROWTH;
|
|
ulCount++;
|
|
}
|
|
|
|
ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
|
|
|
|
return ( configSTACK_DEPTH_TYPE ) ulCount;
|
|
}
|
|
|
|
#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 )
|
|
|
|
/* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the
|
|
* same except for their return type. Using configSTACK_DEPTH_TYPE allows the
|
|
* user to determine the return type. It gets around the problem of the value
|
|
* overflowing on 8-bit types without breaking backward compatibility for
|
|
* applications that expect an 8-bit return type. */
|
|
configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask )
|
|
{
|
|
TCB_t * pxTCB;
|
|
uint8_t * pucEndOfStack;
|
|
configSTACK_DEPTH_TYPE uxReturn;
|
|
|
|
/* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are
|
|
* the same except for their return type. Using configSTACK_DEPTH_TYPE
|
|
* allows the user to determine the return type. It gets around the
|
|
* problem of the value overflowing on 8-bit types without breaking
|
|
* backward compatibility for applications that expect an 8-bit return
|
|
* type. */
|
|
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
|
|
#if portSTACK_GROWTH < 0
|
|
{
|
|
pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
|
|
}
|
|
#else
|
|
{
|
|
pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
|
|
}
|
|
#endif
|
|
|
|
uxReturn = prvTaskCheckFreeStackSpace( pucEndOfStack );
|
|
|
|
return uxReturn;
|
|
}
|
|
|
|
#endif /* INCLUDE_uxTaskGetStackHighWaterMark2 */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
|
|
|
|
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
|
|
{
|
|
TCB_t * pxTCB;
|
|
uint8_t * pucEndOfStack;
|
|
UBaseType_t uxReturn;
|
|
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
|
|
#if portSTACK_GROWTH < 0
|
|
{
|
|
pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
|
|
}
|
|
#else
|
|
{
|
|
pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
|
|
}
|
|
#endif
|
|
|
|
uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
|
|
|
|
return uxReturn;
|
|
}
|
|
|
|
#endif /* INCLUDE_uxTaskGetStackHighWaterMark */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( INCLUDE_vTaskDelete == 1 )
|
|
|
|
static void prvDeleteTCB( TCB_t * pxTCB )
|
|
{
|
|
/* This call is required specifically for the TriCore port. It must be
|
|
* above the vPortFree() calls. The call is also used by ports/demos that
|
|
* want to allocate and clean RAM statically. */
|
|
portCLEAN_UP_TCB( pxTCB );
|
|
|
|
#if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
|
|
{
|
|
/* Free up the memory allocated for the task's TLS Block. */
|
|
configDEINIT_TLS_BLOCK( pxTCB->xTLSBlock );
|
|
}
|
|
#endif
|
|
|
|
#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
|
|
{
|
|
/* The task can only have been allocated dynamically - free both
|
|
* the stack and TCB. */
|
|
vPortFreeStack( pxTCB->pxStack );
|
|
vPortFree( pxTCB );
|
|
}
|
|
#elif ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
|
|
{
|
|
/* The task could have been allocated statically or dynamically, so
|
|
* check what was statically allocated before trying to free the
|
|
* memory. */
|
|
if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )
|
|
{
|
|
/* Both the stack and TCB were allocated dynamically, so both
|
|
* must be freed. */
|
|
vPortFreeStack( pxTCB->pxStack );
|
|
vPortFree( pxTCB );
|
|
}
|
|
else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
|
|
{
|
|
/* Only the stack was statically allocated, so the TCB is the
|
|
* only memory that must be freed. */
|
|
vPortFree( pxTCB );
|
|
}
|
|
else
|
|
{
|
|
/* Neither the stack nor the TCB were allocated dynamically, so
|
|
* nothing needs to be freed. */
|
|
configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB );
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
|
}
|
|
|
|
#endif /* INCLUDE_vTaskDelete */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static void prvResetNextTaskUnblockTime( void )
|
|
{
|
|
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
|
|
{
|
|
/* The new current delayed list is empty. Set xNextTaskUnblockTime to
|
|
* the maximum possible value so it is extremely unlikely that the
|
|
* if( xTickCount >= xNextTaskUnblockTime ) test will pass until
|
|
* there is an item in the delayed list. */
|
|
xNextTaskUnblockTime = portMAX_DELAY;
|
|
}
|
|
else
|
|
{
|
|
/* The new current delayed list is not empty, get the value of
|
|
* the item at the head of the delayed list. This is the time at
|
|
* which the task at the head of the delayed list should be removed
|
|
* from the Blocked state. */
|
|
xNextTaskUnblockTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxDelayedTaskList );
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) || ( configNUMBER_OF_CORES > 1 )
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
TaskHandle_t xTaskGetCurrentTaskHandle( void )
|
|
{
|
|
TaskHandle_t xReturn;
|
|
|
|
/* A critical section is not required as this is not called from
|
|
* an interrupt and the current TCB will always be the same for any
|
|
* individual execution thread. */
|
|
xReturn = pxCurrentTCB;
|
|
|
|
return xReturn;
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
TaskHandle_t xTaskGetCurrentTaskHandle( void )
|
|
{
|
|
TaskHandle_t xReturn;
|
|
UBaseType_t uxSavedInterruptStatus;
|
|
|
|
uxSavedInterruptStatus = portSET_INTERRUPT_MASK();
|
|
{
|
|
xReturn = pxCurrentTCBs[ portGET_CORE_ID() ];
|
|
}
|
|
portCLEAR_INTERRUPT_MASK( uxSavedInterruptStatus );
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
TaskHandle_t xTaskGetCurrentTaskHandleCPU( BaseType_t xCoreID )
|
|
{
|
|
TaskHandle_t xReturn = NULL;
|
|
|
|
if( taskVALID_CORE_ID( xCoreID ) != pdFALSE )
|
|
{
|
|
xReturn = pxCurrentTCBs[ xCoreID ];
|
|
}
|
|
|
|
return xReturn;
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
|
|
#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
|
|
|
BaseType_t xTaskGetSchedulerState( void )
|
|
{
|
|
BaseType_t xReturn;
|
|
|
|
if( xSchedulerRunning == pdFALSE )
|
|
{
|
|
xReturn = taskSCHEDULER_NOT_STARTED;
|
|
}
|
|
else
|
|
{
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
taskENTER_CRITICAL();
|
|
#endif
|
|
{
|
|
if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
|
|
{
|
|
xReturn = taskSCHEDULER_RUNNING;
|
|
}
|
|
else
|
|
{
|
|
xReturn = taskSCHEDULER_SUSPENDED;
|
|
}
|
|
}
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
taskEXIT_CRITICAL();
|
|
#endif
|
|
}
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_MUTEXES == 1 )
|
|
|
|
BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
|
|
{
|
|
TCB_t * const pxMutexHolderTCB = pxMutexHolder;
|
|
BaseType_t xReturn = pdFALSE;
|
|
|
|
/* If the mutex was given back by an interrupt while the queue was
|
|
* locked then the mutex holder might now be NULL. _RB_ Is this still
|
|
* needed as interrupts can no longer use mutexes? */
|
|
if( pxMutexHolder != NULL )
|
|
{
|
|
/* If the holder of the mutex has a priority below the priority of
|
|
* the task attempting to obtain the mutex then it will temporarily
|
|
* inherit the priority of the task attempting to obtain the mutex. */
|
|
if( pxMutexHolderTCB->uxPriority < pxCurrentTCB->uxPriority )
|
|
{
|
|
/* Adjust the mutex holder state to account for its new
|
|
* priority. Only reset the event list item value if the value is
|
|
* not being used for anything else. */
|
|
if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
|
|
{
|
|
listSET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* If the task being modified is in the ready state it will need
|
|
* to be moved into a new list. */
|
|
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE )
|
|
{
|
|
if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
|
{
|
|
/* It is known that the task is in its ready list so
|
|
* there is no need to check again and the port level
|
|
* reset macro can be called directly. */
|
|
portRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority, uxTopReadyPriority );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* Inherit the priority before being moved into the new list. */
|
|
pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
|
|
prvAddTaskToReadyList( pxMutexHolderTCB );
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
{
|
|
/* The priority of the task is raised. Yield for this task
|
|
* if it is not running. */
|
|
if( taskTASK_IS_RUNNING( pxMutexHolderTCB ) != pdTRUE )
|
|
{
|
|
prvYieldForTask( pxMutexHolderTCB );
|
|
}
|
|
}
|
|
#endif /* if ( configNUMBER_OF_CORES > 1 ) */
|
|
}
|
|
else
|
|
{
|
|
/* Just inherit the priority. */
|
|
pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
|
|
}
|
|
|
|
traceTASK_PRIORITY_INHERIT( pxMutexHolderTCB, pxCurrentTCB->uxPriority );
|
|
|
|
/* Inheritance occurred. */
|
|
xReturn = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB->uxPriority )
|
|
{
|
|
/* The base priority of the mutex holder is lower than the
|
|
* priority of the task attempting to take the mutex, but the
|
|
* current priority of the mutex holder is not lower than the
|
|
* priority of the task attempting to take the mutex.
|
|
* Therefore the mutex holder must have already inherited a
|
|
* priority, but inheritance would have occurred if that had
|
|
* not been the case. */
|
|
xReturn = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* configUSE_MUTEXES */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_MUTEXES == 1 )
|
|
|
|
BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
|
|
{
|
|
TCB_t * const pxTCB = pxMutexHolder;
|
|
BaseType_t xReturn = pdFALSE;
|
|
|
|
if( pxMutexHolder != NULL )
|
|
{
|
|
/* A task can only have an inherited priority if it holds the mutex.
|
|
* If the mutex is held by a task then it cannot be given from an
|
|
* interrupt, and if a mutex is given by the holding task then it must
|
|
* be the running state task. */
|
|
configASSERT( pxTCB == pxCurrentTCB );
|
|
configASSERT( pxTCB->uxMutexesHeld );
|
|
( pxTCB->uxMutexesHeld )--;
|
|
|
|
/* Has the holder of the mutex inherited the priority of another
|
|
* task? */
|
|
if( pxTCB->uxPriority != pxTCB->uxBasePriority )
|
|
{
|
|
/* Only disinherit if no other mutexes are held. */
|
|
if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
|
|
{
|
|
/* A task can only have an inherited priority if it holds
|
|
* the mutex. If the mutex is held by a task then it cannot be
|
|
* given from an interrupt, and if a mutex is given by the
|
|
* holding task then it must be the running state task. Remove
|
|
* the holding task from the ready list. */
|
|
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
|
{
|
|
portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* Disinherit the priority before adding the task into the
|
|
* new ready list. */
|
|
traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
|
|
pxTCB->uxPriority = pxTCB->uxBasePriority;
|
|
|
|
/* Reset the event list item value. It cannot be in use for
|
|
* any other purpose if this task is running, and it must be
|
|
* running to give back the mutex. */
|
|
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
prvAddTaskToReadyList( pxTCB );
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
{
|
|
/* The priority of the task is dropped. Yield the core on
|
|
* which the task is running. */
|
|
if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
|
|
{
|
|
prvYieldCore( pxTCB->xTaskRunState );
|
|
}
|
|
}
|
|
#endif /* if ( configNUMBER_OF_CORES > 1 ) */
|
|
|
|
/* Return true to indicate that a context switch is required.
|
|
* This is only actually required in the corner case whereby
|
|
* multiple mutexes were held and the mutexes were given back
|
|
* in an order different to that in which they were taken.
|
|
* If a context switch did not occur when the first mutex was
|
|
* returned, even if a task was waiting on it, then a context
|
|
* switch should occur when the last mutex is returned whether
|
|
* a task is waiting on it or not. */
|
|
xReturn = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* configUSE_MUTEXES */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_MUTEXES == 1 )
|
|
|
|
void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder,
|
|
UBaseType_t uxHighestPriorityWaitingTask )
|
|
{
|
|
TCB_t * const pxTCB = pxMutexHolder;
|
|
UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse;
|
|
const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1;
|
|
|
|
if( pxMutexHolder != NULL )
|
|
{
|
|
/* If pxMutexHolder is not NULL then the holder must hold at least
|
|
* one mutex. */
|
|
configASSERT( pxTCB->uxMutexesHeld );
|
|
|
|
/* Determine the priority to which the priority of the task that
|
|
* holds the mutex should be set. This will be the greater of the
|
|
* holding task's base priority and the priority of the highest
|
|
* priority task that is waiting to obtain the mutex. */
|
|
if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask )
|
|
{
|
|
uxPriorityToUse = uxHighestPriorityWaitingTask;
|
|
}
|
|
else
|
|
{
|
|
uxPriorityToUse = pxTCB->uxBasePriority;
|
|
}
|
|
|
|
/* Does the priority need to change? */
|
|
if( pxTCB->uxPriority != uxPriorityToUse )
|
|
{
|
|
/* Only disinherit if no other mutexes are held. This is a
|
|
* simplification in the priority inheritance implementation. If
|
|
* the task that holds the mutex is also holding other mutexes then
|
|
* the other mutexes may have caused the priority inheritance. */
|
|
if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld )
|
|
{
|
|
/* If a task has timed out because it already holds the
|
|
* mutex it was trying to obtain then it cannot of inherited
|
|
* its own priority. */
|
|
configASSERT( pxTCB != pxCurrentTCB );
|
|
|
|
/* Disinherit the priority, remembering the previous
|
|
* priority to facilitate determining the subject task's
|
|
* state. */
|
|
traceTASK_PRIORITY_DISINHERIT( pxTCB, uxPriorityToUse );
|
|
uxPriorityUsedOnEntry = pxTCB->uxPriority;
|
|
pxTCB->uxPriority = uxPriorityToUse;
|
|
|
|
/* Only reset the event list item value if the value is not
|
|
* being used for anything else. */
|
|
if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
|
|
{
|
|
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* If the running task is not the task that holds the mutex
|
|
* then the task that holds the mutex could be in either the
|
|
* Ready, Blocked or Suspended states. Only remove the task
|
|
* from its current state list if it is in the Ready state as
|
|
* the task's priority is going to change and there is one
|
|
* Ready list per priority. */
|
|
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
|
|
{
|
|
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
|
{
|
|
/* It is known that the task is in its ready list so
|
|
* there is no need to check again and the port level
|
|
* reset macro can be called directly. */
|
|
portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
prvAddTaskToReadyList( pxTCB );
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
{
|
|
/* The priority of the task is dropped. Yield the core on
|
|
* which the task is running. */
|
|
if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
|
|
{
|
|
prvYieldCore( pxTCB->xTaskRunState );
|
|
}
|
|
}
|
|
#endif /* if ( configNUMBER_OF_CORES > 1 ) */
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
#endif /* configUSE_MUTEXES */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
|
|
/* If not in a critical section then yield immediately.
|
|
* Otherwise set xYieldPendings to true to wait to
|
|
* yield until exiting the critical section.
|
|
*/
|
|
void vTaskYieldWithinAPI( void )
|
|
{
|
|
if( portGET_CRITICAL_NESTING_COUNT() == 0U )
|
|
{
|
|
portYIELD();
|
|
}
|
|
else
|
|
{
|
|
xYieldPendings[ portGET_CORE_ID() ] = pdTRUE;
|
|
}
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
|
|
|
|
void vTaskEnterCritical( void )
|
|
{
|
|
portDISABLE_INTERRUPTS();
|
|
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
( pxCurrentTCB->uxCriticalNesting )++;
|
|
|
|
/* 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( pxCurrentTCB->uxCriticalNesting == 1 )
|
|
{
|
|
portASSERT_IF_IN_ISR();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
#endif /* #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
|
|
void vTaskEnterCritical( void )
|
|
{
|
|
portDISABLE_INTERRUPTS();
|
|
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
if( portGET_CRITICAL_NESTING_COUNT() == 0U )
|
|
{
|
|
portGET_TASK_LOCK();
|
|
portGET_ISR_LOCK();
|
|
}
|
|
|
|
portINCREMENT_CRITICAL_NESTING_COUNT();
|
|
|
|
/* 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( portGET_CRITICAL_NESTING_COUNT() == 1U )
|
|
{
|
|
portASSERT_IF_IN_ISR();
|
|
|
|
if( uxSchedulerSuspended == 0U )
|
|
{
|
|
/* The only time there would be a problem is if this is called
|
|
* before a context switch and vTaskExitCritical() is called
|
|
* after pxCurrentTCB changes. Therefore this should not be
|
|
* used within vTaskSwitchContext(). */
|
|
prvCheckForRunStateChange();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
|
|
UBaseType_t vTaskEnterCriticalFromISR( void )
|
|
{
|
|
UBaseType_t uxSavedInterruptStatus = 0;
|
|
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
|
|
|
if( portGET_CRITICAL_NESTING_COUNT() == 0U )
|
|
{
|
|
portGET_ISR_LOCK();
|
|
}
|
|
|
|
portINCREMENT_CRITICAL_NESTING_COUNT();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
return uxSavedInterruptStatus;
|
|
}
|
|
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
|
|
|
|
void vTaskExitCritical( void )
|
|
{
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
/* If pxCurrentTCB->uxCriticalNesting is zero then this function
|
|
* does not match a previous call to vTaskEnterCritical(). */
|
|
configASSERT( pxCurrentTCB->uxCriticalNesting > 0U );
|
|
|
|
/* This function should not be called in ISR. Use vTaskExitCriticalFromISR
|
|
* to exit critical section from ISR. */
|
|
portASSERT_IF_IN_ISR();
|
|
|
|
if( pxCurrentTCB->uxCriticalNesting > 0U )
|
|
{
|
|
( pxCurrentTCB->uxCriticalNesting )--;
|
|
|
|
if( pxCurrentTCB->uxCriticalNesting == 0U )
|
|
{
|
|
portENABLE_INTERRUPTS();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
#endif /* #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
|
|
void vTaskExitCritical( void )
|
|
{
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
/* If critical nesting count is zero then this function
|
|
* does not match a previous call to vTaskEnterCritical(). */
|
|
configASSERT( portGET_CRITICAL_NESTING_COUNT() > 0U );
|
|
|
|
/* This function should not be called in ISR. Use vTaskExitCriticalFromISR
|
|
* to exit critical section from ISR. */
|
|
portASSERT_IF_IN_ISR();
|
|
|
|
if( portGET_CRITICAL_NESTING_COUNT() > 0U )
|
|
{
|
|
portDECREMENT_CRITICAL_NESTING_COUNT();
|
|
|
|
if( portGET_CRITICAL_NESTING_COUNT() == 0U )
|
|
{
|
|
BaseType_t xYieldCurrentTask;
|
|
|
|
/* Get the xYieldPending stats inside the critical section. */
|
|
xYieldCurrentTask = xYieldPendings[ portGET_CORE_ID() ];
|
|
|
|
portRELEASE_ISR_LOCK();
|
|
portRELEASE_TASK_LOCK();
|
|
portENABLE_INTERRUPTS();
|
|
|
|
/* When a task yields in a critical section it just sets
|
|
* xYieldPending to true. So now that we have exited the
|
|
* critical section check if xYieldPending is true, and
|
|
* if so yield. */
|
|
if( xYieldCurrentTask != pdFALSE )
|
|
{
|
|
portYIELD();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configNUMBER_OF_CORES > 1 )
|
|
|
|
void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus )
|
|
{
|
|
if( xSchedulerRunning != pdFALSE )
|
|
{
|
|
/* If critical nesting count is zero then this function
|
|
* does not match a previous call to vTaskEnterCritical(). */
|
|
configASSERT( portGET_CRITICAL_NESTING_COUNT() > 0U );
|
|
|
|
if( portGET_CRITICAL_NESTING_COUNT() > 0U )
|
|
{
|
|
portDECREMENT_CRITICAL_NESTING_COUNT();
|
|
|
|
if( portGET_CRITICAL_NESTING_COUNT() == 0U )
|
|
{
|
|
portRELEASE_ISR_LOCK();
|
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
|
|
|
|
static char * prvWriteNameToBuffer( char * pcBuffer,
|
|
const char * pcTaskName )
|
|
{
|
|
size_t x;
|
|
|
|
/* Start by copying the entire string. */
|
|
( void ) strcpy( pcBuffer, pcTaskName );
|
|
|
|
/* Pad the end of the string with spaces to ensure columns line up when
|
|
* printed out. */
|
|
for( x = strlen( pcBuffer ); x < ( size_t ) ( ( size_t ) configMAX_TASK_NAME_LEN - 1U ); x++ )
|
|
{
|
|
pcBuffer[ x ] = ' ';
|
|
}
|
|
|
|
/* Terminate. */
|
|
pcBuffer[ x ] = ( char ) 0x00;
|
|
|
|
/* Return the new end of string. */
|
|
return &( pcBuffer[ x ] );
|
|
}
|
|
|
|
#endif /* ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
|
|
|
|
void vTaskList( char * pcWriteBuffer )
|
|
{
|
|
TaskStatus_t * pxTaskStatusArray;
|
|
UBaseType_t uxArraySize, x;
|
|
char cStatus;
|
|
|
|
/*
|
|
* PLEASE NOTE:
|
|
*
|
|
* This function is provided for convenience only, and is used by many
|
|
* of the demo applications. Do not consider it to be part of the
|
|
* scheduler.
|
|
*
|
|
* vTaskList() calls uxTaskGetSystemState(), then formats part of the
|
|
* uxTaskGetSystemState() output into a human readable table that
|
|
* displays task: names, states, priority, stack usage and task number.
|
|
* Stack usage specified as the number of unused StackType_t words stack can hold
|
|
* on top of stack - not the number of bytes.
|
|
*
|
|
* vTaskList() has a dependency on the sprintf() C library function that
|
|
* might bloat the code size, use a lot of stack, and provide different
|
|
* results on different platforms. An alternative, tiny, third party,
|
|
* and limited functionality implementation of sprintf() is provided in
|
|
* many of the FreeRTOS/Demo sub-directories in a file called
|
|
* printf-stdarg.c (note printf-stdarg.c does not provide a full
|
|
* snprintf() implementation!).
|
|
*
|
|
* It is recommended that production systems call uxTaskGetSystemState()
|
|
* directly to get access to raw stats data, rather than indirectly
|
|
* through a call to vTaskList().
|
|
*/
|
|
|
|
|
|
/* Make sure the write buffer does not contain a string. */
|
|
*pcWriteBuffer = ( char ) 0x00;
|
|
|
|
/* Take a snapshot of the number of tasks in case it changes while this
|
|
* function is executing. */
|
|
uxArraySize = uxCurrentNumberOfTasks;
|
|
|
|
/* Allocate an array index for each task. NOTE! if
|
|
* configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
|
|
* equate to NULL. */
|
|
pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */
|
|
|
|
if( pxTaskStatusArray != NULL )
|
|
{
|
|
/* Generate the (binary) data. */
|
|
uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
|
|
|
|
/* Create a human readable table from the binary data. */
|
|
for( x = 0; x < uxArraySize; x++ )
|
|
{
|
|
switch( pxTaskStatusArray[ x ].eCurrentState )
|
|
{
|
|
case eRunning:
|
|
cStatus = tskRUNNING_CHAR;
|
|
break;
|
|
|
|
case eReady:
|
|
cStatus = tskREADY_CHAR;
|
|
break;
|
|
|
|
case eBlocked:
|
|
cStatus = tskBLOCKED_CHAR;
|
|
break;
|
|
|
|
case eSuspended:
|
|
cStatus = tskSUSPENDED_CHAR;
|
|
break;
|
|
|
|
case eDeleted:
|
|
cStatus = tskDELETED_CHAR;
|
|
break;
|
|
|
|
case eInvalid: /* Fall through. */
|
|
default: /* Should not get here, but it is included
|
|
* to prevent static checking errors. */
|
|
cStatus = ( char ) 0x00;
|
|
break;
|
|
}
|
|
|
|
/* Write the task name to the string, padding with spaces so it
|
|
* can be printed in tabular form more easily. */
|
|
pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
|
|
|
|
/* Write the rest of the string. */
|
|
sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
|
|
pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */
|
|
}
|
|
|
|
/* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
|
|
* is 0 then vPortFree() will be #defined to nothing. */
|
|
vPortFree( pxTaskStatusArray );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
|
|
/*----------------------------------------------------------*/
|
|
|
|
#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configUSE_TRACE_FACILITY == 1 ) )
|
|
|
|
void vTaskGetRunTimeStats( char * pcWriteBuffer )
|
|
{
|
|
TaskStatus_t * pxTaskStatusArray;
|
|
UBaseType_t uxArraySize, x;
|
|
configRUN_TIME_COUNTER_TYPE ulTotalTime, ulStatsAsPercentage;
|
|
|
|
/*
|
|
* PLEASE NOTE:
|
|
*
|
|
* This function is provided for convenience only, and is used by many
|
|
* of the demo applications. Do not consider it to be part of the
|
|
* scheduler.
|
|
*
|
|
* vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
|
|
* of the uxTaskGetSystemState() output into a human readable table that
|
|
* displays the amount of time each task has spent in the Running state
|
|
* in both absolute and percentage terms.
|
|
*
|
|
* vTaskGetRunTimeStats() has a dependency on the sprintf() C library
|
|
* function that might bloat the code size, use a lot of stack, and
|
|
* provide different results on different platforms. An alternative,
|
|
* tiny, third party, and limited functionality implementation of
|
|
* sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
|
|
* a file called printf-stdarg.c (note printf-stdarg.c does not provide
|
|
* a full snprintf() implementation!).
|
|
*
|
|
* It is recommended that production systems call uxTaskGetSystemState()
|
|
* directly to get access to raw stats data, rather than indirectly
|
|
* through a call to vTaskGetRunTimeStats().
|
|
*/
|
|
|
|
/* Make sure the write buffer does not contain a string. */
|
|
*pcWriteBuffer = ( char ) 0x00;
|
|
|
|
/* Take a snapshot of the number of tasks in case it changes while this
|
|
* function is executing. */
|
|
uxArraySize = uxCurrentNumberOfTasks;
|
|
|
|
/* Allocate an array index for each task. NOTE! If
|
|
* configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
|
|
* equate to NULL. */
|
|
pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */
|
|
|
|
if( pxTaskStatusArray != NULL )
|
|
{
|
|
/* Generate the (binary) data. */
|
|
uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
|
|
|
|
/* For percentage calculations. */
|
|
ulTotalTime /= 100UL;
|
|
|
|
/* Avoid divide by zero errors. */
|
|
if( ulTotalTime > 0UL )
|
|
{
|
|
/* Create a human readable table from the binary data. */
|
|
for( x = 0; x < uxArraySize; x++ )
|
|
{
|
|
/* What percentage of the total run time has the task used?
|
|
* This will always be rounded down to the nearest integer.
|
|
* ulTotalRunTime has already been divided by 100. */
|
|
ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
|
|
|
|
/* Write the task name to the string, padding with
|
|
* spaces so it can be printed in tabular form more
|
|
* easily. */
|
|
pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
|
|
|
|
if( ulStatsAsPercentage > 0UL )
|
|
{
|
|
#ifdef portLU_PRINTF_SPECIFIER_REQUIRED
|
|
{
|
|
sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
|
|
}
|
|
#else
|
|
{
|
|
/* sizeof( int ) == sizeof( long ) so a smaller
|
|
* printf() library can be used. */
|
|
sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
/* If the percentage is zero here then the task has
|
|
* consumed less than 1% of the total run time. */
|
|
#ifdef portLU_PRINTF_SPECIFIER_REQUIRED
|
|
{
|
|
sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter );
|
|
}
|
|
#else
|
|
{
|
|
/* sizeof( int ) == sizeof( long ) so a smaller
|
|
* printf() library can be used. */
|
|
sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
|
|
}
|
|
#endif
|
|
}
|
|
|
|
pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
/* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
|
|
* is 0 then vPortFree() will be #defined to nothing. */
|
|
vPortFree( pxTaskStatusArray );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
TickType_t uxTaskResetEventItemValue( void )
|
|
{
|
|
TickType_t uxReturn;
|
|
|
|
uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
|
|
|
|
/* Reset the event list item to its normal value - so it can be used with
|
|
* queues and semaphores. */
|
|
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
|
|
return uxReturn;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_MUTEXES == 1 )
|
|
|
|
TaskHandle_t pvTaskIncrementMutexHeldCount( void )
|
|
{
|
|
TCB_t * pxTCB;
|
|
|
|
pxTCB = pxCurrentTCB;
|
|
|
|
/* If xSemaphoreCreateMutex() is called before any tasks have been created
|
|
* then pxCurrentTCB will be NULL. */
|
|
if( pxTCB != NULL )
|
|
{
|
|
( pxTCB->uxMutexesHeld )++;
|
|
}
|
|
|
|
return pxTCB;
|
|
}
|
|
|
|
#endif /* configUSE_MUTEXES */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
|
|
|
|
uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn,
|
|
BaseType_t xClearCountOnExit,
|
|
TickType_t xTicksToWait )
|
|
{
|
|
uint32_t ulReturn;
|
|
|
|
configASSERT( uxIndexToWaitOn < configTASK_NOTIFICATION_ARRAY_ENTRIES );
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
/* Only block if the notification count is not already non-zero. */
|
|
if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] == 0UL )
|
|
{
|
|
/* Mark this task as waiting for a notification. */
|
|
pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION;
|
|
|
|
if( xTicksToWait > ( TickType_t ) 0 )
|
|
{
|
|
prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
|
|
traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWaitOn );
|
|
|
|
/* All ports are written to allow a yield in a critical
|
|
* section (some will yield immediately, others wait until the
|
|
* critical section exits) - but it is not something that
|
|
* application code should ever do. */
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
portYIELD_WITHIN_API();
|
|
}
|
|
#else
|
|
{
|
|
vTaskYieldWithinAPI();
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
traceTASK_NOTIFY_TAKE( uxIndexToWaitOn );
|
|
ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ];
|
|
|
|
if( ulReturn != 0UL )
|
|
{
|
|
if( xClearCountOnExit != pdFALSE )
|
|
{
|
|
pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] = 0UL;
|
|
}
|
|
else
|
|
{
|
|
pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] = ulReturn - ( uint32_t ) 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskNOT_WAITING_NOTIFICATION;
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
return ulReturn;
|
|
}
|
|
|
|
#endif /* configUSE_TASK_NOTIFICATIONS */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
|
|
|
|
BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn,
|
|
uint32_t ulBitsToClearOnEntry,
|
|
uint32_t ulBitsToClearOnExit,
|
|
uint32_t * pulNotificationValue,
|
|
TickType_t xTicksToWait )
|
|
{
|
|
BaseType_t xReturn;
|
|
|
|
configASSERT( uxIndexToWaitOn < configTASK_NOTIFICATION_ARRAY_ENTRIES );
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
/* Only block if a notification is not already pending. */
|
|
if( pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] != taskNOTIFICATION_RECEIVED )
|
|
{
|
|
/* Clear bits in the task's notification value as bits may get
|
|
* set by the notifying task or interrupt. This can be used to
|
|
* clear the value to zero. */
|
|
pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] &= ~ulBitsToClearOnEntry;
|
|
|
|
/* Mark this task as waiting for a notification. */
|
|
pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION;
|
|
|
|
if( xTicksToWait > ( TickType_t ) 0 )
|
|
{
|
|
prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
|
|
traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWaitOn );
|
|
|
|
/* All ports are written to allow a yield in a critical
|
|
* section (some will yield immediately, others wait until the
|
|
* critical section exits) - but it is not something that
|
|
* application code should ever do. */
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
portYIELD_WITHIN_API();
|
|
}
|
|
#else
|
|
{
|
|
vTaskYieldWithinAPI();
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
traceTASK_NOTIFY_WAIT( uxIndexToWaitOn );
|
|
|
|
if( pulNotificationValue != NULL )
|
|
{
|
|
/* Output the current notification value, which may or may not
|
|
* have changed. */
|
|
*pulNotificationValue = pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ];
|
|
}
|
|
|
|
/* If ucNotifyValue is set then either the task never entered the
|
|
* blocked state (because a notification was already pending) or the
|
|
* task unblocked because of a notification. Otherwise the task
|
|
* unblocked because of a timeout. */
|
|
if( pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] != taskNOTIFICATION_RECEIVED )
|
|
{
|
|
/* A notification was not received. */
|
|
xReturn = pdFALSE;
|
|
}
|
|
else
|
|
{
|
|
/* A notification was already pending or a notification was
|
|
* received while the task was waiting. */
|
|
pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] &= ~ulBitsToClearOnExit;
|
|
xReturn = pdTRUE;
|
|
}
|
|
|
|
pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskNOT_WAITING_NOTIFICATION;
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* configUSE_TASK_NOTIFICATIONS */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
|
|
|
|
BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
|
|
UBaseType_t uxIndexToNotify,
|
|
uint32_t ulValue,
|
|
eNotifyAction eAction,
|
|
uint32_t * pulPreviousNotificationValue )
|
|
{
|
|
TCB_t * pxTCB;
|
|
BaseType_t xReturn = pdPASS;
|
|
uint8_t ucOriginalNotifyState;
|
|
|
|
configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
|
|
configASSERT( xTaskToNotify );
|
|
pxTCB = xTaskToNotify;
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
if( pulPreviousNotificationValue != NULL )
|
|
{
|
|
*pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
|
|
}
|
|
|
|
ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
|
|
|
|
pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
|
|
|
|
switch( eAction )
|
|
{
|
|
case eSetBits:
|
|
pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
|
|
break;
|
|
|
|
case eIncrement:
|
|
( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
|
|
break;
|
|
|
|
case eSetValueWithOverwrite:
|
|
pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
|
|
break;
|
|
|
|
case eSetValueWithoutOverwrite:
|
|
|
|
if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
|
|
{
|
|
pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
|
|
}
|
|
else
|
|
{
|
|
/* The value could not be written to the task. */
|
|
xReturn = pdFAIL;
|
|
}
|
|
|
|
break;
|
|
|
|
case eNoAction:
|
|
|
|
/* The task is being notified without its notify value being
|
|
* updated. */
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Should not get here if all enums are handled.
|
|
* Artificially force an assert by testing a value the
|
|
* compiler can't assume is const. */
|
|
configASSERT( xTickCount == ( TickType_t ) 0 );
|
|
|
|
break;
|
|
}
|
|
|
|
traceTASK_NOTIFY( uxIndexToNotify );
|
|
|
|
/* If the task is in the blocked state specifically to wait for a
|
|
* notification then unblock it now. */
|
|
if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
|
|
{
|
|
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
|
|
prvAddTaskToReadyList( pxTCB );
|
|
|
|
/* The task should not have been on an event list. */
|
|
configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
|
|
|
|
#if ( configUSE_TICKLESS_IDLE != 0 )
|
|
{
|
|
/* If a task is blocked waiting for a notification then
|
|
* xNextTaskUnblockTime might be set to the blocked task's time
|
|
* out time. If the task is unblocked for a reason other than
|
|
* a timeout xNextTaskUnblockTime is normally left unchanged,
|
|
* because it will automatically get reset to a new value when
|
|
* the tick count equals xNextTaskUnblockTime. However if
|
|
* tickless idling is used it might be more important to enter
|
|
* sleep mode at the earliest possible time - so reset
|
|
* xNextTaskUnblockTime here to ensure it is updated at the
|
|
* earliest possible time. */
|
|
prvResetNextTaskUnblockTime();
|
|
}
|
|
#endif
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
|
|
{
|
|
/* The notified task has a priority above the currently
|
|
* executing task so a yield is required. */
|
|
taskYIELD_IF_USING_PREEMPTION();
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
{
|
|
prvYieldForTask( pxTCB );
|
|
}
|
|
#endif
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* configUSE_TASK_NOTIFICATIONS */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
|
|
|
|
BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
|
|
UBaseType_t uxIndexToNotify,
|
|
uint32_t ulValue,
|
|
eNotifyAction eAction,
|
|
uint32_t * pulPreviousNotificationValue,
|
|
BaseType_t * pxHigherPriorityTaskWoken )
|
|
{
|
|
TCB_t * pxTCB;
|
|
uint8_t ucOriginalNotifyState;
|
|
BaseType_t xReturn = pdPASS;
|
|
UBaseType_t uxSavedInterruptStatus;
|
|
|
|
configASSERT( xTaskToNotify );
|
|
configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
|
|
|
|
/* RTOS ports that support interrupt nesting have the concept of a
|
|
* maximum system call (or maximum API call) interrupt priority.
|
|
* Interrupts that are above the maximum system call priority are keep
|
|
* permanently enabled, even when the RTOS kernel is in a critical section,
|
|
* but cannot make any calls to FreeRTOS API functions. If configASSERT()
|
|
* is defined in FreeRTOSConfig.h then
|
|
* portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
|
|
* failure if a FreeRTOS API function is called from an interrupt that has
|
|
* been assigned a priority above the configured maximum system call
|
|
* priority. Only FreeRTOS functions that end in FromISR can be called
|
|
* from interrupts that have been assigned a priority at or (logically)
|
|
* below the maximum system call interrupt priority. FreeRTOS maintains a
|
|
* separate interrupt safe API to ensure interrupt entry is as fast and as
|
|
* simple as possible. More information (albeit Cortex-M specific) is
|
|
* provided on the following link:
|
|
* https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
|
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
|
|
|
|
pxTCB = xTaskToNotify;
|
|
|
|
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
|
|
{
|
|
if( pulPreviousNotificationValue != NULL )
|
|
{
|
|
*pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
|
|
}
|
|
|
|
ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
|
|
pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
|
|
|
|
switch( eAction )
|
|
{
|
|
case eSetBits:
|
|
pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
|
|
break;
|
|
|
|
case eIncrement:
|
|
( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
|
|
break;
|
|
|
|
case eSetValueWithOverwrite:
|
|
pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
|
|
break;
|
|
|
|
case eSetValueWithoutOverwrite:
|
|
|
|
if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
|
|
{
|
|
pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
|
|
}
|
|
else
|
|
{
|
|
/* The value could not be written to the task. */
|
|
xReturn = pdFAIL;
|
|
}
|
|
|
|
break;
|
|
|
|
case eNoAction:
|
|
|
|
/* The task is being notified without its notify value being
|
|
* updated. */
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Should not get here if all enums are handled.
|
|
* Artificially force an assert by testing a value the
|
|
* compiler can't assume is const. */
|
|
configASSERT( xTickCount == ( TickType_t ) 0 );
|
|
break;
|
|
}
|
|
|
|
traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify );
|
|
|
|
/* If the task is in the blocked state specifically to wait for a
|
|
* notification then unblock it now. */
|
|
if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
|
|
{
|
|
/* The task should not have been on an event list. */
|
|
configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
|
|
|
|
if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
|
|
{
|
|
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
|
|
prvAddTaskToReadyList( pxTCB );
|
|
}
|
|
else
|
|
{
|
|
/* The delayed and ready lists cannot be accessed, so hold
|
|
* this task pending until the scheduler is resumed. */
|
|
listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
|
|
}
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
|
|
{
|
|
/* The notified task has a priority above the currently
|
|
* executing task so a yield is required. */
|
|
if( pxHigherPriorityTaskWoken != NULL )
|
|
{
|
|
*pxHigherPriorityTaskWoken = pdTRUE;
|
|
}
|
|
|
|
/* Mark that a yield is pending in case the user is not
|
|
* using the "xHigherPriorityTaskWoken" parameter to an ISR
|
|
* safe FreeRTOS function. */
|
|
xYieldPendings[ 0 ] = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
{
|
|
prvYieldForTask( pxTCB );
|
|
|
|
if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE )
|
|
{
|
|
if( pxHigherPriorityTaskWoken != NULL )
|
|
{
|
|
*pxHigherPriorityTaskWoken = pdTRUE;
|
|
}
|
|
}
|
|
}
|
|
#endif /* if ( configUSE_PREEMPTION == 1 ) */
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* configUSE_TASK_NOTIFICATIONS */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
|
|
|
|
void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
|
|
UBaseType_t uxIndexToNotify,
|
|
BaseType_t * pxHigherPriorityTaskWoken )
|
|
{
|
|
TCB_t * pxTCB;
|
|
uint8_t ucOriginalNotifyState;
|
|
UBaseType_t uxSavedInterruptStatus;
|
|
|
|
configASSERT( xTaskToNotify );
|
|
configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
|
|
|
|
/* RTOS ports that support interrupt nesting have the concept of a
|
|
* maximum system call (or maximum API call) interrupt priority.
|
|
* Interrupts that are above the maximum system call priority are keep
|
|
* permanently enabled, even when the RTOS kernel is in a critical section,
|
|
* but cannot make any calls to FreeRTOS API functions. If configASSERT()
|
|
* is defined in FreeRTOSConfig.h then
|
|
* portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
|
|
* failure if a FreeRTOS API function is called from an interrupt that has
|
|
* been assigned a priority above the configured maximum system call
|
|
* priority. Only FreeRTOS functions that end in FromISR can be called
|
|
* from interrupts that have been assigned a priority at or (logically)
|
|
* below the maximum system call interrupt priority. FreeRTOS maintains a
|
|
* separate interrupt safe API to ensure interrupt entry is as fast and as
|
|
* simple as possible. More information (albeit Cortex-M specific) is
|
|
* provided on the following link:
|
|
* https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
|
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
|
|
|
|
pxTCB = xTaskToNotify;
|
|
|
|
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
|
|
{
|
|
ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
|
|
pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
|
|
|
|
/* 'Giving' is equivalent to incrementing a count in a counting
|
|
* semaphore. */
|
|
( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
|
|
|
|
traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify );
|
|
|
|
/* If the task is in the blocked state specifically to wait for a
|
|
* notification then unblock it now. */
|
|
if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
|
|
{
|
|
/* The task should not have been on an event list. */
|
|
configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
|
|
|
|
if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
|
|
{
|
|
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
|
|
prvAddTaskToReadyList( pxTCB );
|
|
}
|
|
else
|
|
{
|
|
/* The delayed and ready lists cannot be accessed, so hold
|
|
* this task pending until the scheduler is resumed. */
|
|
listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
|
|
}
|
|
|
|
#if ( configNUMBER_OF_CORES == 1 )
|
|
{
|
|
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
|
|
{
|
|
/* The notified task has a priority above the currently
|
|
* executing task so a yield is required. */
|
|
if( pxHigherPriorityTaskWoken != NULL )
|
|
{
|
|
*pxHigherPriorityTaskWoken = pdTRUE;
|
|
}
|
|
|
|
/* Mark that a yield is pending in case the user is not
|
|
* using the "xHigherPriorityTaskWoken" parameter in an ISR
|
|
* safe FreeRTOS function. */
|
|
xYieldPendings[ 0 ] = pdTRUE;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
{
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
{
|
|
prvYieldForTask( pxTCB );
|
|
|
|
if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE )
|
|
{
|
|
if( pxHigherPriorityTaskWoken != NULL )
|
|
{
|
|
*pxHigherPriorityTaskWoken = pdTRUE;
|
|
}
|
|
}
|
|
}
|
|
#endif /* #if ( configUSE_PREEMPTION == 1 ) */
|
|
}
|
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
|
|
}
|
|
|
|
#endif /* configUSE_TASK_NOTIFICATIONS */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
|
|
|
|
BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask,
|
|
UBaseType_t uxIndexToClear )
|
|
{
|
|
TCB_t * pxTCB;
|
|
BaseType_t xReturn;
|
|
|
|
configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES );
|
|
|
|
/* If null is passed in here then it is the calling task that is having
|
|
* its notification state cleared. */
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
if( pxTCB->ucNotifyState[ uxIndexToClear ] == taskNOTIFICATION_RECEIVED )
|
|
{
|
|
pxTCB->ucNotifyState[ uxIndexToClear ] = taskNOT_WAITING_NOTIFICATION;
|
|
xReturn = pdPASS;
|
|
}
|
|
else
|
|
{
|
|
xReturn = pdFAIL;
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
return xReturn;
|
|
}
|
|
|
|
#endif /* configUSE_TASK_NOTIFICATIONS */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
|
|
|
|
uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
|
|
UBaseType_t uxIndexToClear,
|
|
uint32_t ulBitsToClear )
|
|
{
|
|
TCB_t * pxTCB;
|
|
uint32_t ulReturn;
|
|
|
|
/* If null is passed in here then it is the calling task that is having
|
|
* its notification state cleared. */
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
|
|
taskENTER_CRITICAL();
|
|
{
|
|
/* Return the notification as it was before the bits were cleared,
|
|
* then clear the bit mask. */
|
|
ulReturn = pxTCB->ulNotifiedValue[ uxIndexToClear ];
|
|
pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear;
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
return ulReturn;
|
|
}
|
|
|
|
#endif /* configUSE_TASK_NOTIFICATIONS */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
|
|
configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask )
|
|
{
|
|
return xTask->ulRunTimeCounter;
|
|
}
|
|
|
|
#endif
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
|
|
configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t xTask )
|
|
{
|
|
configRUN_TIME_COUNTER_TYPE ulTotalTime, ulReturn;
|
|
|
|
ulTotalTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
|
|
|
|
/* For percentage calculations. */
|
|
ulTotalTime /= ( configRUN_TIME_COUNTER_TYPE ) 100;
|
|
|
|
/* Avoid divide by zero errors. */
|
|
if( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 )
|
|
{
|
|
ulReturn = xTask->ulRunTimeCounter / ulTotalTime;
|
|
}
|
|
else
|
|
{
|
|
ulReturn = 0;
|
|
}
|
|
|
|
return ulReturn;
|
|
}
|
|
|
|
#endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
|
|
|
|
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void )
|
|
{
|
|
configRUN_TIME_COUNTER_TYPE ulReturn = 0;
|
|
BaseType_t i;
|
|
|
|
for( i = 0; i < ( BaseType_t ) configNUMBER_OF_CORES; i++ )
|
|
{
|
|
ulReturn += xIdleTaskHandles[ i ]->ulRunTimeCounter;
|
|
}
|
|
|
|
return ulReturn;
|
|
}
|
|
|
|
#endif /* if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
|
|
|
|
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void )
|
|
{
|
|
configRUN_TIME_COUNTER_TYPE ulTotalTime, ulReturn;
|
|
configRUN_TIME_COUNTER_TYPE ulRunTimeCounter = 0;
|
|
BaseType_t i;
|
|
|
|
ulTotalTime = portGET_RUN_TIME_COUNTER_VALUE() * configNUMBER_OF_CORES;
|
|
|
|
/* For percentage calculations. */
|
|
ulTotalTime /= ( configRUN_TIME_COUNTER_TYPE ) 100;
|
|
|
|
/* Avoid divide by zero errors. */
|
|
if( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 )
|
|
{
|
|
for( i = 0; i < ( BaseType_t ) configNUMBER_OF_CORES; i++ )
|
|
{
|
|
ulRunTimeCounter += xIdleTaskHandles[ i ]->ulRunTimeCounter;
|
|
}
|
|
|
|
ulReturn = ulRunTimeCounter / ulTotalTime;
|
|
}
|
|
else
|
|
{
|
|
ulReturn = 0;
|
|
}
|
|
|
|
return ulReturn;
|
|
}
|
|
|
|
#endif /* if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
|
|
const BaseType_t xCanBlockIndefinitely )
|
|
{
|
|
TickType_t xTimeToWake;
|
|
const TickType_t xConstTickCount = xTickCount;
|
|
|
|
#if ( INCLUDE_xTaskAbortDelay == 1 )
|
|
{
|
|
/* About to enter a delayed list, so ensure the ucDelayAborted flag is
|
|
* reset to pdFALSE so it can be detected as having been set to pdTRUE
|
|
* when the task leaves the Blocked state. */
|
|
pxCurrentTCB->ucDelayAborted = pdFALSE;
|
|
}
|
|
#endif
|
|
|
|
/* Remove the task from the ready list before adding it to the blocked list
|
|
* as the same list item is used for both lists. */
|
|
if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
|
{
|
|
/* The current task must be in a ready list, so there is no need to
|
|
* check, and the port reset macro can be called directly. */
|
|
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); /*lint !e931 pxCurrentTCB cannot change as it is the calling task. pxCurrentTCB->uxPriority and uxTopReadyPriority cannot change as called with scheduler suspended or in a critical section. */
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
{
|
|
if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
|
|
{
|
|
/* Add the task to the suspended task list instead of a delayed task
|
|
* list to ensure it is not woken by a timing event. It will block
|
|
* indefinitely. */
|
|
listINSERT_END( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
|
|
}
|
|
else
|
|
{
|
|
/* Calculate the time at which the task should be woken if the event
|
|
* does not occur. This may overflow but this doesn't matter, the
|
|
* kernel will manage it correctly. */
|
|
xTimeToWake = xConstTickCount + xTicksToWait;
|
|
|
|
/* The list item will be inserted in wake time order. */
|
|
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
|
|
|
|
if( xTimeToWake < xConstTickCount )
|
|
{
|
|
/* Wake time has overflowed. Place this item in the overflow
|
|
* list. */
|
|
vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
|
|
}
|
|
else
|
|
{
|
|
/* The wake time has not overflowed, so the current block list
|
|
* is used. */
|
|
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
|
|
|
|
/* If the task entering the blocked state was placed at the
|
|
* head of the list of blocked tasks then xNextTaskUnblockTime
|
|
* needs to be updated too. */
|
|
if( xTimeToWake < xNextTaskUnblockTime )
|
|
{
|
|
xNextTaskUnblockTime = xTimeToWake;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#else /* INCLUDE_vTaskSuspend */
|
|
{
|
|
/* Calculate the time at which the task should be woken if the event
|
|
* does not occur. This may overflow but this doesn't matter, the kernel
|
|
* will manage it correctly. */
|
|
xTimeToWake = xConstTickCount + xTicksToWait;
|
|
|
|
/* The list item will be inserted in wake time order. */
|
|
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
|
|
|
|
if( xTimeToWake < xConstTickCount )
|
|
{
|
|
/* Wake time has overflowed. Place this item in the overflow list. */
|
|
vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
|
|
}
|
|
else
|
|
{
|
|
/* The wake time has not overflowed, so the current block list is used. */
|
|
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
|
|
|
|
/* If the task entering the blocked state was placed at the head of the
|
|
* list of blocked tasks then xNextTaskUnblockTime needs to be updated
|
|
* too. */
|
|
if( xTimeToWake < xNextTaskUnblockTime )
|
|
{
|
|
xNextTaskUnblockTime = xTimeToWake;
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
/* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
|
|
( void ) xCanBlockIndefinitely;
|
|
}
|
|
#endif /* INCLUDE_vTaskSuspend */
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#if ( portUSING_MPU_WRAPPERS == 1 )
|
|
|
|
xMPU_SETTINGS * xTaskGetMPUSettings( TaskHandle_t xTask )
|
|
{
|
|
TCB_t * pxTCB;
|
|
|
|
pxTCB = prvGetTCBFromHandle( xTask );
|
|
|
|
return &( pxTCB->xMPUSettings );
|
|
}
|
|
|
|
#endif /* portUSING_MPU_WRAPPERS */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* Code below here allows additional code to be inserted into this source file,
|
|
* especially where access to file scope functions and data is needed (for example
|
|
* when performing module tests). */
|
|
|
|
#ifdef FREERTOS_MODULE_TEST
|
|
#include "tasks_test_access_functions.h"
|
|
#endif
|
|
|
|
|
|
#if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 )
|
|
|
|
#include "freertos_tasks_c_additions.h"
|
|
|
|
#ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
|
|
static void freertos_tasks_c_additions_init( void )
|
|
{
|
|
FREERTOS_TASKS_C_ADDITIONS_INIT();
|
|
}
|
|
#endif
|
|
|
|
#endif /* if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) */
|