From 7582e0cbb1edab989fc34c31ac05d577253552e6 Mon Sep 17 00:00:00 2001 From: Soren Ptak Date: Thu, 31 Aug 2023 14:42:06 -0700 Subject: [PATCH] Swap to the clang-formatting directory for now. Update the files to be smaller for the tests --- .github/workflows/formattingTests.yml | 484 +- .github/workflows/test.yml | 10 +- .../.clang-format | 0 clang-formatting/action.yml | 170 + .../filesWithCRLFEndings/cgc_error.h | 92 +- .../filesWithCRLFEndings/crlf-file.c | 81 + .../filesWithCRLFEndings/out.txt | 92 +- .../goodFileInHere.c | 100 + .../filesWithFormattingErrors/test.c | 0 .../filesWithTrailingWhitespace/myFile.log | 0 .../filesWithTrailingWhitespace/test.c | 0 .../errorFileInDirectory.h | 49 + .../include/fileWithErrorInclude/goodHeader.h | 48 + .../include/fileWithErrorInclude/goodTask.h | 48 + .../goodFiles/include/formatErrorTest.h | 49 + .../goodFiles/include/headerFile.h | 48 + .../goodFiles/source/README.md | 0 .../goodFiles/source/core_mqtt.c | 0 .../errorFileInDirectory.c | 0 .../source/fileWithErrorSource/goodTest.c | 0 .../goodFiles/source/formatErrorTest.c | 0 clang-formatting/goodFiles/source/tasks.c | 100 + clang-formatting/goodFiles/source/test.c | 100 + formatting/action.yml | 202 +- formatting/filesWithCRLFEndings/main-blinky.c | 193 - .../fileFormattedWithClangFormatV16.c | 6151 ----------------- .../goodFileInHere.c | 6151 ----------------- formatting/getFiles | 118 - .../errorFileInDirectory.h | 3761 ---------- .../include/fileWithErrorInclude/goodTask.h | 3761 ---------- .../goodFiles/include/formatErrorTest.h | 3761 ---------- formatting/goodFiles/include/task.h | 3761 ---------- formatting/goodFiles/source/core_mqtt.c | 3515 ---------- formatting/goodFiles/source/tasks.c | 6151 ----------------- formatting/uncrustify.cfg | 160 + 35 files changed, 1131 insertions(+), 38025 deletions(-) rename {formatting => clang-formatting}/.clang-format (100%) create mode 100644 clang-formatting/action.yml rename {formatting => clang-formatting}/filesWithCRLFEndings/cgc_error.h (97%) create mode 100644 clang-formatting/filesWithCRLFEndings/crlf-file.c rename {formatting => clang-formatting}/filesWithCRLFEndings/out.txt (97%) create mode 100644 clang-formatting/filesWithFormattingErrors/goodFileInHere.c rename {formatting => clang-formatting}/filesWithFormattingErrors/test.c (100%) rename {formatting => clang-formatting}/filesWithTrailingWhitespace/myFile.log (100%) rename {formatting => clang-formatting}/filesWithTrailingWhitespace/test.c (100%) create mode 100644 clang-formatting/goodFiles/include/fileWithErrorInclude/errorFileInDirectory.h create mode 100644 clang-formatting/goodFiles/include/fileWithErrorInclude/goodHeader.h create mode 100644 clang-formatting/goodFiles/include/fileWithErrorInclude/goodTask.h create mode 100644 clang-formatting/goodFiles/include/formatErrorTest.h create mode 100644 clang-formatting/goodFiles/include/headerFile.h rename {formatting => clang-formatting}/goodFiles/source/README.md (100%) rename formatting/goodFiles/source/fileWithErrorSource/goodTest.c => clang-formatting/goodFiles/source/core_mqtt.c (100%) rename {formatting => clang-formatting}/goodFiles/source/fileWithErrorSource/errorFileInDirectory.c (100%) rename formatting/goodFiles/source/test.c => clang-formatting/goodFiles/source/fileWithErrorSource/goodTest.c (100%) rename {formatting => clang-formatting}/goodFiles/source/formatErrorTest.c (100%) create mode 100644 clang-formatting/goodFiles/source/tasks.c create mode 100644 clang-formatting/goodFiles/source/test.c delete mode 100644 formatting/filesWithCRLFEndings/main-blinky.c delete mode 100644 formatting/filesWithFormattingErrors/fileFormattedWithClangFormatV16.c delete mode 100644 formatting/filesWithFormattingErrors/goodFileInHere.c delete mode 100755 formatting/getFiles delete mode 100644 formatting/goodFiles/include/fileWithErrorInclude/errorFileInDirectory.h delete mode 100644 formatting/goodFiles/include/fileWithErrorInclude/goodTask.h delete mode 100644 formatting/goodFiles/include/formatErrorTest.h delete mode 100644 formatting/goodFiles/include/task.h delete mode 100644 formatting/goodFiles/source/core_mqtt.c delete mode 100644 formatting/goodFiles/source/tasks.c create mode 100644 formatting/uncrustify.cfg diff --git a/.github/workflows/formattingTests.yml b/.github/workflows/formattingTests.yml index 45508400..4683cadc 100644 --- a/.github/workflows/formattingTests.yml +++ b/.github/workflows/formattingTests.yml @@ -4,7 +4,7 @@ on: push: branches: ["**"] pull_request: - branches: [main] + branches: [main,v2] workflow_dispatch: env: @@ -15,430 +15,6 @@ env: bashEnd: \033[0m jobs: - - get-files-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - env: - stepName: "Install Dependencies" - name: ${{ env.stepName }} - shell: bash - working-directory: formatting - run: | - # ${{ env.stepName }} - echo "::group::${{ env.stepName }}" - echo "$(pwd)" >> $GITHUB_PATH - - sudo apt install fd-find - fdfind --version - - exitStatus=$? - echo "::endgroup::" - if [ $exitStatus -eq 0 ]; then - echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}" - exit 1 - fi - - - env: - stepName: "Functional | Success | getFiles() No Arguments" - name: ${{ env.stepName }} - shell: bash - working-directory: formatting - run: | - # ${{ env.stepName }} - echo "::group::${{ env.stepName }}" - allFiles=$(grep -sril "copyright.*amazon" --include="*.c" --include="*.h") - files=$(getFiles) - echo -e "${{ env.bashInfo }} allFiles:\n$allFiles ${{ env.bashEnd }}" - echo -e "${{ env.bashInfo }} files:\n$files ${{ env.bashEnd }}" - exitStatus=0 - - # Loop through all the files we found using grep - for file in ${allFiles[@]} ; do - echo -e "${{ env.bashInfo }} Checking File: $file ${{ env.bashEnd }}" - # Check if they're in the flattened version of getFiles() search - if ! [[ $files == *"$file"* ]]; then - echo -e "${{ env.bashFail }} Get Files did not find file: $file ${{ env.bashEnd }}" - exitStatus=1 - fi - done - - echo "::endgroup::" - if [ $exitStatus -eq 0 ]; then - echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}" - exit 1 - fi - - - env: - stepName: "Functional | Success | getFiles() Exclude Single File" - name: ${{ env.stepName }} - shell: bash - working-directory: formatting - run: | - # ${{ env.stepName }} - echo "::group::${{ env.stepName }}" - files=$(getFiles --exclude-files="test.c") - echo -e "${{ env.bashInfo }} files:\n$files ${{ env.bashEnd }}" - exitStatus=0 - - if [[ "$files" == *"test.c"* ]]; then - echo -e "${{ env.bashFail }} Get Files Found a file it should have skipped: test.c ${{ env.bashEnd }}" - exitStatus=1 - elif [[ "$files" != *"tasks.c"* ]]; then - echo -e "${{ env.bashFail }} Get Files Did not find a file it should have: tasks.c ${{ env.bashEnd }}" - exitStatus=1 - fi - - echo "::endgroup::" - if [ $exitStatus -eq 0 ]; then - echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}" - exit 1 - fi - - - env: - stepName: "Functional | Success | getFiles() Exclude Single Directory" - name: ${{ env.stepName }} - shell: bash - working-directory: formatting - run: | - # ${{ env.stepName }} - echo "::group::${{ env.stepName }}" - files=$(getFiles --exclude-dirs="goodFiles") - echo -e "${{ env.bashInfo }} files:\n$files ${{ env.bashEnd }}" - exitStatus=0 - - if [[ "$files" == *"goodFiles"* ]]; then - echo -e "${{ env.bashFail }} Get Files Found a directory it should have skipped: goodFiles ${{ env.bashEnd }}" - exitStatus=1 - fi - - echo "::endgroup::" - if [ $exitStatus -eq 0 ]; then - echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}" - exit 1 - fi - - - env: - stepName: "Functional | Success | getFiles() Exclude Single Directory and File" - name: ${{ env.stepName }} - shell: bash - working-directory: formatting - run: | - # ${{ env.stepName }} - echo "::group::${{ env.stepName }}" - files=$(getFiles --exclude-dirs="goodFiles" --exclude-files="test.c") - echo -e "${{ env.bashInfo }} files:\n$files ${{ env.bashInfo }}" - exitStatus=0 - if [[ "$files" == *"test.c"* ]]; then - echo -e "${{ env.bashFail }} Get Files Found a directory it should have skipped: goodFiles ${{ env.bashEnd }}" - exitStatus=1 - fi - echo "::endgroup::" - if [ $exitStatus -eq 0 ]; then - echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}" - exit 1 - fi - - - env: - stepName: "Functional | Success | getFiles() Include Extra Type" - name: ${{ env.stepName }} - shell: bash - working-directory: formatting - run: | - # ${{ env.stepName }} - echo "::group::${{ env.stepName }}" - - files=$(getFiles --include-extensions="md") - echo -e "${{ env.bashInfo }} files:\n$files ${{ env.bashEnd }}" - - exitStatus=0 - if [[ "$files" != *"README.md"* ]]; then - echo -e "${{ env.bashFail }} Get Files Found a directory it should have skipped: goodFiles ${{ env.bashEnd }}" - exitStatus=1 - fi - - echo "::endgroup::" - if [ $exitStatus -eq 0 ]; then - echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}" - exit 1 - fi - - - env: - stepName: "Functional | Success | getFiles() Exclude Two Directories and Two Files" - name: ${{ env.stepName }} - shell: bash - working-directory: formatting - run: | - # ${{ env.stepName }} - echo "::group::${{ env.stepName }}" - files="" - files=$(getFiles --exclude-dirs="filesWithCRLFEndings,include" --exclude-files="fileFormattedWithClangFormatV16.c,badFile.c") - - echo -e "${{ env.bashInfo }} files:\n"$files" ${{ env.bashEnd }}" - exitStatus=0 - if [[ "$files" == *"fileFormattedWithClangFormatV16.c"* ]]; then - echo -e "${{ env.bashFail }} Get Files Found a File it should have skipped: fileFormattedWithClangFormatV16.c ${{ env.bashEnd }}" - exitStatus=1 - fi - - if [[ "$files" == *"badFile.c"* ]]; then - echo -e "${{ env.bashFail }} Get Files Found a File it should have skipped: badFile.c ${{ env.bashEnd }}" - exitStatus=1 - fi - - if [[ "$files" == *"filesWithCRLFEndings"* ]]; then - echo -e "${{ env.bashFail }} Get Files Found a directory it should have skipped: filesWithCRLFEndings ${{ env.bashEnd }}" - exitStatus=1 - fi - - if [[ "$files" == *"include"* ]]; then - echo -e "${{ env.bashFail }} Get Files Found a directory it should have skipped: include ${{ env.bashEnd }}" - exitStatus=1 - fi - - echo "::endgroup::" - if [ $exitStatus -eq 0 ]; then - echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}" - exit 1 - fi - - uncrustify-formatting-success-cases: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v3 - - - env: - stepName: "Functional | Success | Exclude All Error Dirs" - name: ${{ env.stepName }} - id: exclude-dirs-with-errors - uses: ./uncrustify-formatting - with: - path: uncrustify-formatting - exclude-dirs: "filesWithFormattingErrors,filesWithCRLFEndings,filesWithTrailingWhitespace" - exclude-files: "badFile.c" - - - env: - stepName: "Functional | Success | Exclude Files" - name: ${{ env.stepName }} - id: exclude-files-with-errors - uses: ./uncrustify-formatting - with: - path: uncrustify-formatting - exclude-dirs: ",,," - exclude-files: "badFile.c,cgc_error.h,main-blinky.c,test.c" - - - env: - stepName: "Functional | Success | Exclude File and Exclude Dirs" - name: ${{ env.stepName }} - id: exclude-single-dir-multiple-files - uses: ./uncrustify-formatting - with: - path: uncrustify-formatting - exclude-dirs: "goodFiles" - exclude-files: "cgc_error.h,main-blinky.c,test.c" - - - env: - stepName: "Functional | Success | Exclude Files and Exclude Dirs" - name: ${{ env.stepName }} - id: exclude-two-files-two-dirs - uses: ./uncrustify-formatting - with: - path: uncrustify-formatting - exclude-dirs: "filesWithFormattingErrors,filesWithTrailingWhitespace" - exclude-files: "test.c,cgc_error.h,main-blinky.c,badFile.c" - - uncrustify-formatting-error-cases: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v3 - - env: - stepName: "Functional | Failure | Whitespace, CRLF, and Format Failure" - name: ${{ env.stepName }} - id: all-format-errors - continue-on-error: true - uses: ./uncrustify-formatting - with: - path: uncrustify-formatting - - - env: - stepName: "Functional | Failure | CRLF and Formatting Error" - name: ${{ env.stepName }} - id: crlf-and-format-error - continue-on-error: true - uses: ./uncrustify-formatting - with: - path: uncrustify-formatting - exclude-dirs: "filesWithTrailingWhitespace" - - - env: - stepName: "Functional | Failure | CRLF and Whitespace Error" - name: ${{ env.stepName }} - id: crlf-and-whitespace-error - continue-on-error: true - uses: ./uncrustify-formatting - with: - path: uncrustify-formatting - exclude-dirs: "filesWithFormattingErrors" - - - env: - stepName: "Functional | Failure | CRLF Error" - name: ${{ env.stepName }} - id: crlf-error - continue-on-error: true - uses: ./uncrustify-formatting - with: - path: uncrustify-formatting - exclude-dirs: "filesWithFormattingErrors,filesWithTrailingWhitespace" - exclude-files: "badFile.c" - - - env: - stepName: "Functional | Failure | Formatting and Whitespace Error" - name: ${{ env.stepName }} - id: formatting-and-whitespace-error - continue-on-error: true - uses: ./uncrustify-formatting - with: - path: uncrustify-formatting - exclude-dirs: "filesWithCRLFEndings" - - - env: - stepName: "Functional | Failure | Formatting Error" - name: ${{ env.stepName }} - id: formatting-error - continue-on-error: true - uses: ./uncrustify-formatting - with: - path: uncrustify-formatting - exclude-dirs: "filesWithTrailingWhitespace,filesWithCRLFEndings" - - - env: - stepName: "Functional | Failure | Whitespace Error" - name: ${{ env.stepName }} - id: whitespace-error - continue-on-error: true - uses: ./uncrustify-formatting - with: - path: uncrustify-formatting - exclude-dirs: "filesWithFormattingErrors,filesWithCRLFEndings" - - - env: - stepName: "API | Failure | Exclude Dirs Error" - name: ${{ env.stepName }} - id: error-in-exclude-dirs - continue-on-error: true - uses: ./uncrustify-formatting - with: - path: uncrustify-formatting - exclude-dirs: "filesWithFormattingErrors, filesWithCRLFEndings" - - - env: - stepName: "API | Failure | Exclude Files Error" - name: ${{ env.stepName }} - id: error-in-exclude-files - continue-on-error: true - uses: ./uncrustify-formatting - with: - path: uncrustify-formatting - exclude-files: "filesWithFormattingErrors, filesWithCRLFEndings" - - - env: - stepName: "API | Failure | Exclude Option Errors" - name: ${{ env.stepName }} - id: error-in-both - continue-on-error: true - uses: ./uncrustify-formatting - with: - path: uncrustify-formatting - exclude-files: "filesWithFormattingErrors, filesWithCRLFEndings" - exclude-dirs: "filesWithFormattingErrors, - filesWithCRLFEndings" - - - env: - stepName: Check Failure Test Cases - name: ${{ env.stepName }} - id: check-failure-test-cases - shell: bash - run: | - # ${{ env.stepName }} - exitStatus=0 - if [ "${{ steps.all-format-errors.outcome}}" = "failure" ]; then - echo -e "${{ env.bashPass }} Functional | Failure | Whitespace, CRLF, and Format Failure | Had Expected "failure" ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} Functional | Failure | Whitespace, CRLF, and Format Failure | Had Unexpected "success" ${{ env.bashEnd }}" - exitStatus=1 - fi - if [ "${{ steps.crlf-and-format-error.outcome}}" = "failure" ]; then - echo -e "${{ env.bashPass }} Functional | Failure | CRLF and Formatting Error | Had Expected "failure" ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} Functional | Failure | CRLF and Formatting Error | Had Unexpected "success" ${{ env.bashEnd }}" - exitStatus=1 - fi - if [ "${{ steps.crlf-and-whitespace-error.outcome}}" = "failure" ]; then - echo -e "${{ env.bashPass }} Functional | Failure | CRLF and Whitespace Error | Had Expected "failure" ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} Functional | Failure | CRLF and Whitespace Error | Had Unexpected "success" ${{ env.bashEnd }}" - exitStatus=1 - fi - if [ "${{ steps.crlf-error.outcome}}" = "failure" ]; then - echo -e "${{ env.bashPass }} Functional | Failure | CRLF Error | Had Expected "failure" ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} Functional | Failure | CRLF Error | Had Unexpected "success" ${{ env.bashEnd }}" - exitStatus=1 - fi - if [ "${{ steps.formatting-and-whitespace-error.outcome}}" = "failure" ]; then - echo -e "${{ env.bashPass }} Functional | Failure | Formatting and Whitespace Error | Had Expected "failure" ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} Functional | Failure | Formatting and Whitespace Error | Had Unexpected "success" ${{ env.bashEnd }}" - exitStatus=1 - fi - if [ "${{ steps.formatting-error.outcome}}" = "failure" ]; then - echo -e "${{ env.bashPass }} Functional | Failure | Formatting Error | Had Expected "failure" ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} Functional | Failure | Formatting Error | Had Unexpected "success" ${{ env.bashEnd }}" - exitStatus=1 - fi - if [ "${{ steps.whitespace-error.outcome}}" = "failure" ]; then - echo -e "${{ env.bashPass }} Functional | Failure | Whitespace Error | Had Expected "failure" ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} Functional | Failure | Whitespace Error | Had Unexpected "success" ${{ env.bashEnd }}" - exitStatus=1 - fi - if [ "${{ steps.error-in-exclude-dirs.outcome}}" = "failure" ]; then - echo -e "${{ env.bashPass }} API | Failure | Exclude Dirs Error | Had Expected "failure" ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} API | Failure | Exclude Dirs Error | Had Unexpected "success" ${{ env.bashEnd }}" - exitStatus=1 - fi - if [ "${{ steps.error-in-exclude-files.outcome}}" = "failure" ]; then - echo -e "${{ env.bashPass }} API | Failure | Exclude Files Error | Had Expected "failure" ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} API | Failure | Exclude Files Error | Had Unexpected "success" ${{ env.bashEnd }}" - exitStatus=1 - fi - if [ "${{ steps.error-in-both.outcome}}" = "failure" ]; then - echo -e "${{ env.bashPass }} API | Failure | Exclude Option Errors | Had Expected "failure" ${{ env.bashEnd }}" - else - echo -e "${{ env.bashFail }} API | Failure | Exclude Option Errors | Had Unexpected "success" ${{ env.bashEnd }}" - exitStatus=1 - fi - exit $exitStatus - clang-formatting-success-cases: runs-on: ubuntu-latest steps: @@ -448,9 +24,9 @@ jobs: stepName: "Functional | Success | Exclude Files and Dirs" name: ${{ env.stepName }} id: exclude-dirs-with-errors - uses: ./formatting + uses: ./clang-formatting with: - path: formatting/goodFiles + path: clang-formatting/goodFiles exclude-dirs: "fileWithErrorInclude, fileWithErrorSource" exclude-files: "formatErrorTest.h, formatErrorTest.c" @@ -458,14 +34,14 @@ jobs: stepName: "Functional | Success | Exclude Just Files" name: ${{ env.stepName }} id: exclude-files-with-errors - uses: ./formatting + uses: ./clang-formatting with: - path: formatting/goodFiles + path: clang-formatting/goodFiles exclude-dirs: ",,," exclude-files: "formatErrorTest.h, formatErrorTest.c, errorFileInDirectory.h, errorFileInDirectory.c" - name: Remove Error Files at Top Directory - working-directory: formatting/goodFiles + working-directory: clang-formatting/goodFiles shell: bash run: | # Remove Error Files at Top Directory @@ -477,9 +53,9 @@ jobs: stepName: "Functional | Success | Exclude Just Error Dirs" name: ${{ env.stepName }} id: exclude-two-files-two-dirs - uses: ./formatting + uses: ./clang-formatting with: - path: formatting/goodFiles + path: clang-formatting/goodFiles exclude-dirs: "fileWithErrorInclude,fileWithErrorSource" clang-formatting-error-cases: @@ -491,9 +67,9 @@ jobs: name: ${{ env.stepName }} id: all-format-errors continue-on-error: true - uses: ./formatting + uses: ./clang-formatting with: - path: formatting + path: clang-formatting - name: Reset Files shell: bash @@ -504,9 +80,9 @@ jobs: name: ${{ env.stepName }} id: crlf-and-format-error continue-on-error: true - uses: ./formatting + uses: ./clang-formatting with: - path: formatting + path: clang-formatting exclude-dirs: "filesWithTrailingWhitespace" - name: Reset Files @@ -518,9 +94,9 @@ jobs: name: ${{ env.stepName }} id: crlf-and-whitespace-error continue-on-error: true - uses: ./formatting + uses: ./clang-formatting with: - path: formatting + path: clang-formatting exclude-dirs: "filesWithFormattingErrors" - name: Reset Files @@ -532,9 +108,9 @@ jobs: name: ${{ env.stepName }} id: crlf-and-whitespace-non-c-error continue-on-error: true - uses: ./formatting + uses: ./clang-formatting with: - path: formatting + path: clang-formatting exclude-dirs: "filesWithFormattingErrors" exclude-files: "test.c, main-blinky.c, cgc_error.h" @@ -547,9 +123,9 @@ jobs: name: ${{ env.stepName }} id: crlf-error continue-on-error: true - uses: ./formatting + uses: ./clang-formatting with: - path: formatting + path: clang-formatting exclude-dirs: "filesWithFormattingErrors,filesWithTrailingWhitespace" exclude-files: "badFile.c" @@ -562,9 +138,9 @@ jobs: name: ${{ env.stepName }} id: formatting-and-whitespace-error continue-on-error: true - uses: ./formatting + uses: ./clang-formatting with: - path: formatting + path: clang-formatting exclude-dirs: "filesWithCRLFEndings" - name: Reset Files @@ -576,9 +152,9 @@ jobs: name: ${{ env.stepName }} id: formatting-error continue-on-error: true - uses: ./formatting + uses: ./clang-formatting with: - path: formatting + path: clang-formatting exclude-dirs: "filesWithTrailingWhitespace,filesWithCRLFEndings" - name: Reset Files @@ -590,9 +166,9 @@ jobs: name: ${{ env.stepName }} id: whitespace-error continue-on-error: true - uses: ./formatting + uses: ./clang-formatting with: - path: formatting + path: clang-formatting exclude-dirs: "filesWithFormattingErrors,filesWithCRLFEndings" - name: Reset Files @@ -604,9 +180,9 @@ jobs: name: ${{ env.stepName }} id: error-in-exclude-dirs continue-on-error: true - uses: ./formatting + uses: ./clang-formatting with: - path: formatting + path: clang-formatting exclude-dirs: "filesWithFormattingErrors, filesWithCRLFEndings" - name: Reset Files @@ -618,9 +194,9 @@ jobs: name: ${{ env.stepName }} id: error-in-exclude-files continue-on-error: true - uses: ./formatting + uses: ./clang-formatting with: - path: formatting + path: clang-formatting exclude-files: "filesWithFormattingErrors, filesWithCRLFEndings" - name: Reset Files @@ -632,9 +208,9 @@ jobs: name: ${{ env.stepName }} id: error-in-both continue-on-error: true - uses: ./formatting + uses: ./clang-formatting with: - path: formatting + path: clang-formatting exclude-files: "filesWithFormattingErrors, filesWithCRLFEndings" exclude-dirs: "filesWithFormattingErrors, filesWithCRLFEndings" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 28b749b1..7100e866 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,8 +11,8 @@ jobs: test-format-check: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + - uses: actions/checkout@v3 with: repository: FreeRTOS/coreMQTT ref: main @@ -109,7 +109,7 @@ jobs: exe-path: executable-monitor/test.out success-line: "SLEEPING FOR 6 SECONDS" timeout-seconds: 20 - + - name: Functional Test | Success Case | No Retries, No Success Line, Exit Code id: test-executable-monitor-action-no-retry-attempts-exit-code uses: ./executable-monitor @@ -125,7 +125,7 @@ jobs: exe-path: executable-monitor/test.out success-line: "SLEEPING FOR 6 SECONDS" retry-attempts: 2 - + - name: API Test | Success Case | Retries, No Success Line, Exit Code, Use Default Timeout id: test-executable-monitor-action-no-success-line-no-timeout uses: ./executable-monitor @@ -353,7 +353,7 @@ jobs: repository: FreeRTOS/FreeRTOS ref: '202107.00' path: FreeRTOS - submodules: recursive + submodules: recursive - name: Test manifest verifier uses: ./manifest-verifier with: diff --git a/formatting/.clang-format b/clang-formatting/.clang-format similarity index 100% rename from formatting/.clang-format rename to clang-formatting/.clang-format diff --git a/clang-formatting/action.yml b/clang-formatting/action.yml new file mode 100644 index 00000000..c9367ec4 --- /dev/null +++ b/clang-formatting/action.yml @@ -0,0 +1,170 @@ +name: 'formatting' +description: 'CI formatting check' +inputs: + path: + description: 'Path to repository folder to run formatting check for. ' + required: false + default: ./ + exclude-files: + description: 'List of comma-separated files to exclude from the formatting check. Eg file1, file2' + required: false + default: '' + exclude-dirs: + description: 'List of comma-separated directories to exclude from the formatting check. Eg docs, build' + required: false + default: '' + include-extensions: + description: 'List of comma-separated extensions to add to the formatting check. Eg md, dox' + required: false + default: '' + +runs: + using: "composite" + steps: + - env: + # At time of writing, you can't add a global environment + # to an action file so stuck with this. If this gets changed + # Please move this + bashPass: \033[32;1mPASSED - + bashInfo: \033[33;1mINFO - + bashFail: \033[31;1mFAILED - + bashEnd: \033[0m + stepName: Install Clang Format + name: ${{ env.stepName }} + shell: bash + run: | + # ${{ env.stepName }} + echo -e "::group::${{ env.stepName }}" + sudo apt-get install clang-format fd-find dos2unix + echo "$GITHUB_ACTION_PATH" >> $GITHUB_PATH + export PATH="$PATH:$GITHUB_ACTION_PATH" + + fdfind --version + fdInstalled=$? + + clang-format --version + clangFormatInstalled=$? + + echo -e "::endgroup::" + if [ $clangFormatInstalled -eq 1 ] || [ $fdInstalled -eq 1 ]; then + echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}" + exit 1 + else + echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}" + exit 0 + fi + + - env: + bashPass: \033[32;1mPASSED - + bashInfo: \033[33;1mINFO - + bashFail: \033[31;1mFAILED - + bashEnd: \033[0m + stepName: Check Format of Files + name: ${{ env.stepName }} + id: action-formatting-check + if: ${{ steps.validate-inputs.outcome}} = "success" + working-directory: ${{ inputs.path }} + shell: bash + run: | + # ${{ env.stepName }} + echo -e "${{ env.bashInfo }} Using clang-format version "$(clang-format --version)" ${{ env.bashEnd }}" + echo -e "::group::Clang Format Code Files" + exitCode=0 + export PATH="$PATH:$GITHUB_ACTION_PATH" + + # TODO: These checks should really only run against modified files on PRS + # Where when the commit to the actual repo happens, then we should trigger the job + # Against all of the files in the repo. Nice inbetween to keep checks fast for PRs, + # But maintain that we don't have a change in the Repo that suddenly causes an issue + + # Parse the optional inputs + args="" + + # fd-find uses -E to exclude a file or directory + if [ -n "${{ inputs.exclude-dirs }}" ]; then + dirs=" -E " + dirs+="${{ inputs.exclude-dirs }}" + dirs="${dirs//,/ -E }" + args+=" ${dirs}" + fi + + # fd-find uses -E to exclude a file or directory + if [ -n "${{ inputs.exclude-files }}" ]; then + files=" -E " + files+="${{ inputs.exclude-files }}" + files="${files//,/ -E }" + args+=" ${files}" + fi + + # fd-find uses -e to include a file extension + if [ -n "${{ inputs.include-file-types }}" ]; then + file_types=" -e " + file_types+="${{ inputs.include-file-types }}" + file_types="${file_types//,/ -e }" + args+=" ${file_types}" + fi + + # Get all .c and .h files, as well as any other requested file types. + # Then run clang-format with the common config file. + echo -e "${{ env.bashInfo }} Running: fdfind -e c -e h ${args} --exec clang-format -i ${{ env.bashEnd }}" + echo -e "::group::${{ env.bashInfo }} Check Formatting with Clang-Format ${{ env.bashEnd }}" + fdfind -e c -e h ${args} --exec fdfind -e c -e h ${args} --exec clang-format -i + echo -e "::endgroup::" + + echo -e "::group::Check for Trailing Whitespace" + # These checks will be captured in the git diff + # Replace all trailing whitespace, exclude photo files + fdfind --type=file -E '*.png' -E '*.jpg' -E '*.svg' ${args} . --exec sed -Ei 's/[[:blank:]]+$//' + echo -e "::endgroup::" + + echo -e "::group::Check for CRLF Line Endings" + # Replace all line endings with LF ones instead of CRLF + fdfind --type=file ${args} . --exec dos2unix + echo -e "::endgroup::" + + # Run a git diff to print the differences if any exist, return an error code if there are any + # Wrap in a set+e and set -e so we can keep running after the error + echo -e "::group::${{ env.bashInfo }} Format Difference ${{ env.bashEnd }}" + set +e + git diff --exit-code --color=always + exitCode=$? + set -e + echo -e "::endgroup::" + + if [ $exitCode -eq 0 ]; then + echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}" + else + # I am intentionally doing this a second time here. + # Using tee will mask the exit code of the diff + # And we don't want the colour to be added to the patch + # Put it in what the 'default' path will be for the upload step + git diff > formattingChanges.patch + echo -e "${{ env.bashFail }} List of files with formatting errors: ${{ env.bashEnd }}" + echo -e "${{ env.bashFail }} "$(git diff --name-only)" ${{ env.bashEnd }} " + echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}" + fi + exit $exitCode + + - name: Upload Formatting Git Patch + if: failure() && ( steps.action-formatting-check.outcome == 'failure' ) + id: upload-formatting-patch + uses: actions/upload-artifact@v3 + with: + name: formattingChanges + path: ${{ inputs.path }}/formattingChanges.patch + retention-days: 7 + + - env: + stepName: Formatting Git Patch Info + bashPass: \033[32;1m + bashInfo: \033[33;1m + bashFail: \033[31;1m + bashEnd: \033[0 + if: failure() && ( steps.upload-formatting-patch.outcome == 'success' ) + shell: bash + run: | + # ${{ env.stepName }} + echo -e "${{ env.bashInfo }} A git patch of the formatting issues has been attached to this workflow ${{ env.bashEnd }}" + echo -e "${{ env.bashInfo }} This can be accessed by returning to the bottom of the summary page of the workflow run ${{ env.bashEnd }}" + echo -e "${{ env.bashInfo }} At the bottom of the page will be a formattingChanges.patch file that you can download ${{ env.bashEnd }}" + echo -e "${{ env.bashInfo }} Copy this patch to your repository and apply it using 'git apply formattingChanges.patch' ${{ env.bashEnd }}" diff --git a/formatting/filesWithCRLFEndings/cgc_error.h b/clang-formatting/filesWithCRLFEndings/cgc_error.h similarity index 97% rename from formatting/filesWithCRLFEndings/cgc_error.h rename to clang-formatting/filesWithCRLFEndings/cgc_error.h index eb2f3481..5ff56b66 100644 --- a/formatting/filesWithCRLFEndings/cgc_error.h +++ b/clang-formatting/filesWithCRLFEndings/cgc_error.h @@ -1,47 +1,47 @@ -#ifndef CGC_ERROR_H_ -#define CGC_ERROR_H_ - -/* Error checking macros for the clock selction and clock enable defines */ - -#if ( (CLK_SOURCE != CLK_SOURCE_LOCO) && \ - (CLK_SOURCE != CLK_SOURCE_HOCO) && \ - (CLK_SOURCE != CLK_SOURCE_MAIN) && \ - (CLK_SOURCE != CLK_SOURCE_SUB) && \ - (CLK_SOURCE != CLK_SOURCE_PLL) ) - #error "No CLK_SOURCE specified. Please specify a valid CLK_SOURCE"; -#endif - - -#if (CLK_SOURCE == CLK_SOURCE_HOCO) && (ENABLE_HOCO == 0) - #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" -#endif - -#if (CLK_SOURCE == CLK_SOURCE_MAIN) && (ENABLE_MAIN == 0) - #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" -#endif - -#if (CLK_SOURCE == CLK_SOURCE_SUB) && (ENABLE_SUB == 0) - #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" -#endif - -#if (CLK_SOURCE == CLK_SOURCE_PLL) && (ENABLE_PLL == 0) - #error "PLL has been specified as the CLK_SOURCE but ENABLE_PLL is (0). Please set to (1) in file cgc.h" -#endif - -#if ( FCLK_FREQUENCY > 50000000L ) - #error "FCLK_FREQUENCY Error: Please enter a valid divider value" -#endif - -#if ( ICLK_FREQUENCY > 100000000L ) - #error "ICLK_FREQUENCY Error: Please enter a valid divider value" -#endif - -#if ( BCLK_FREQUENCY > 100000000L ) - #error "BCLK_FREQUENCY Error: Please enter a valid divider value" -#endif - -#if ( PCLKB_FREQUENCY > 50000000L ) - #error "PCLKB_FREQUENCY Error: Please enter a valid divider value" -#endif - +#ifndef CGC_ERROR_H_ +#define CGC_ERROR_H_ + +/* Error checking macros for the clock selction and clock enable defines */ + +#if ( (CLK_SOURCE != CLK_SOURCE_LOCO) && \ + (CLK_SOURCE != CLK_SOURCE_HOCO) && \ + (CLK_SOURCE != CLK_SOURCE_MAIN) && \ + (CLK_SOURCE != CLK_SOURCE_SUB) && \ + (CLK_SOURCE != CLK_SOURCE_PLL) ) + #error "No CLK_SOURCE specified. Please specify a valid CLK_SOURCE"; +#endif + + +#if (CLK_SOURCE == CLK_SOURCE_HOCO) && (ENABLE_HOCO == 0) + #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if (CLK_SOURCE == CLK_SOURCE_MAIN) && (ENABLE_MAIN == 0) + #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if (CLK_SOURCE == CLK_SOURCE_SUB) && (ENABLE_SUB == 0) + #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if (CLK_SOURCE == CLK_SOURCE_PLL) && (ENABLE_PLL == 0) + #error "PLL has been specified as the CLK_SOURCE but ENABLE_PLL is (0). Please set to (1) in file cgc.h" +#endif + +#if ( FCLK_FREQUENCY > 50000000L ) + #error "FCLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if ( ICLK_FREQUENCY > 100000000L ) + #error "ICLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if ( BCLK_FREQUENCY > 100000000L ) + #error "BCLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if ( PCLKB_FREQUENCY > 50000000L ) + #error "PCLKB_FREQUENCY Error: Please enter a valid divider value" +#endif + #endif \ No newline at end of file diff --git a/clang-formatting/filesWithCRLFEndings/crlf-file.c b/clang-formatting/filesWithCRLFEndings/crlf-file.c new file mode 100644 index 00000000..abff5628 --- /dev/null +++ b/clang-formatting/filesWithCRLFEndings/crlf-file.c @@ -0,0 +1,81 @@ +/* +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 + * + */ + +static void prvQueueSendTask( void *pvParameters ) +{ +TickType_t xNextWakeTime; +const unsigned long ulValueToSend = 100UL; + + /* Check the task parameter is as expected. */ + configASSERT( ( ( unsigned long ) pvParameters ) == mainQUEUE_SEND_PARAMETER ); + + /* Initialise xNextWakeTime - this only needs to be done once. */ + xNextWakeTime = xTaskGetTickCount(); + + for( ;; ) + { + /* Place this task in the blocked state until it is time to run again. + The block time is specified in ticks, the constant used converts ticks + to ms. While in the Blocked state this task will not consume any CPU + time. */ + vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS ); + + /* Send to the queue - causing the queue receive task to unblock and + toggle the LED. 0 is used as the block time so the sending operation + will not block - it shouldn't need to block as the queue should always + be empty at this point in the code. */ + xQueueSend( xQueue, &ulValueToSend, 0U ); + } +} +/*-----------------------------------------------------------*/ + +static void prvQueueReceiveTask( void *pvParameters ) +{ +unsigned long ulReceivedValue; + + /* Check the task parameter is as expected. */ + configASSERT( ( ( unsigned long ) pvParameters ) == mainQUEUE_RECEIVE_PARAMETER ); + + for( ;; ) + { + /* Wait until something arrives in the queue - this task will block + indefinitely provided INCLUDE_vTaskSuspend is set to 1 in + FreeRTOSConfig.h. */ + xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY ); + + /* To get here something must have been received from the queue, but + is it the expected value? If it is, toggle the LED. */ + if( ulReceivedValue == 100UL ) + { + /* Toggle the LED. */ + port_pin_toggle_output_level( LED_0_PIN ); + ulReceivedValue = 0U; + } + } +} +/*-----------------------------------------------------------*/ + diff --git a/formatting/filesWithCRLFEndings/out.txt b/clang-formatting/filesWithCRLFEndings/out.txt similarity index 97% rename from formatting/filesWithCRLFEndings/out.txt rename to clang-formatting/filesWithCRLFEndings/out.txt index 42336909..f5355427 100644 --- a/formatting/filesWithCRLFEndings/out.txt +++ b/clang-formatting/filesWithCRLFEndings/out.txt @@ -1,47 +1,47 @@ -#ifndef CGC_ERROR_H_ -#define CGC_ERROR_H_ - -/* Error checking macros for the clock selction and clock enable defines */ - -#if ( (CLK_SOURCE != CLK_SOURCE_LOCO) && \ - (CLK_SOURCE != CLK_SOURCE_HOCO) && \ - (CLK_SOURCE != CLK_SOURCE_MAIN) && \ - (CLK_SOURCE != CLK_SOURCE_SUB) && \ - (CLK_SOURCE != CLK_SOURCE_PLL) ) - #error "No CLK_SOURCE specified. Please specify a valid CLK_SOURCE"; -#endif - - -#if (CLK_SOURCE == CLK_SOURCE_HOCO) && (ENABLE_HOCO == 0) - #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" -#endif - -#if (CLK_SOURCE == CLK_SOURCE_MAIN) && (ENABLE_MAIN == 0) - #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" -#endif - -#if (CLK_SOURCE == CLK_SOURCE_SUB) && (ENABLE_SUB == 0) - #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" -#endif - -#if (CLK_SOURCE == CLK_SOURCE_PLL) && (ENABLE_PLL == 0) - #error "PLL has been specified as the CLK_SOURCE but ENABLE_PLL is (0). Please set to (1) in file cgc.h" -#endif - -#if ( FCLK_FREQUENCY > 50000000L ) - #error "FCLK_FREQUENCY Error: Please enter a valid divider value" -#endif - -#if ( ICLK_FREQUENCY > 100000000L ) - #error "ICLK_FREQUENCY Error: Please enter a valid divider value" -#endif - -#if ( BCLK_FREQUENCY > 100000000L ) - #error "BCLK_FREQUENCY Error: Please enter a valid divider value" -#endif - -#if ( PCLKB_FREQUENCY > 50000000L ) - #error "PCLKB_FREQUENCY Error: Please enter a valid divider value" -#endif - +#ifndef CGC_ERROR_H_ +#define CGC_ERROR_H_ + +/* Error checking macros for the clock selction and clock enable defines */ + +#if ( (CLK_SOURCE != CLK_SOURCE_LOCO) && \ + (CLK_SOURCE != CLK_SOURCE_HOCO) && \ + (CLK_SOURCE != CLK_SOURCE_MAIN) && \ + (CLK_SOURCE != CLK_SOURCE_SUB) && \ + (CLK_SOURCE != CLK_SOURCE_PLL) ) + #error "No CLK_SOURCE specified. Please specify a valid CLK_SOURCE"; +#endif + + +#if (CLK_SOURCE == CLK_SOURCE_HOCO) && (ENABLE_HOCO == 0) + #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if (CLK_SOURCE == CLK_SOURCE_MAIN) && (ENABLE_MAIN == 0) + #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if (CLK_SOURCE == CLK_SOURCE_SUB) && (ENABLE_SUB == 0) + #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if (CLK_SOURCE == CLK_SOURCE_PLL) && (ENABLE_PLL == 0) + #error "PLL has been specified as the CLK_SOURCE but ENABLE_PLL is (0). Please set to (1) in file cgc.h" +#endif + +#if ( FCLK_FREQUENCY > 50000000L ) + #error "FCLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if ( ICLK_FREQUENCY > 100000000L ) + #error "ICLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if ( BCLK_FREQUENCY > 100000000L ) + #error "BCLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if ( PCLKB_FREQUENCY > 50000000L ) + #error "PCLKB_FREQUENCY Error: Please enter a valid divider value" +#endif + #endif \ No newline at end of file diff --git a/clang-formatting/filesWithFormattingErrors/goodFileInHere.c b/clang-formatting/filesWithFormattingErrors/goodFileInHere.c new file mode 100644 index 00000000..ef4e2fc8 --- /dev/null +++ b/clang-formatting/filesWithFormattingErrors/goodFileInHere.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include + +typedef struct DateAndTime +{ + uint64_t hour; + uint64_t minutes; + uint64_t seconds; + uint64_t msec; +} DateAndTime; + +#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || \ + defined( __NT__ ) || defined( WIN64 ) || defined( __WIN64 ) + #include +/* Remove the warning about implicit sleep even with windows.h included */ +extern void sleep( int miliseconds ); +void getTime( struct DateAndTime * currentTime ) +{ + SYSTEMTIME st, lt; + + GetLocalTime( < ); + currentTime->hour = lt.wHour; + currentTime->minutes = lt.wMinute; + currentTime->seconds = lt.wSecond; + currentTime->msec = lt.wMilliseconds; +} +#else /* if defined( WIN32 ) || defined ( _WIN32 ) || defined( __WIN32__ ) \ + || defined( __NT__ ) || defined( WIN64 ) || defined( __WIN64 ) */ + #include + #include +void getTime( struct DateAndTime * currentTime ) +{ + struct timeval tv; + struct tm * tm; + + gettimeofday( &tv, NULL ); + tm = localtime( &tv.tv_sec ); + currentTime->hour = tm->tm_hour; + currentTime->minutes = tm->tm_min; + currentTime->seconds = tm->tm_sec; + currentTime->msec = ( int ) ( tv.tv_usec / 1000 ); +} +#endif /* if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || \ + defined( __NT__ ) || defined( WIN64 ) || defined( __WIN64 ) */ + +int main( int argc, char ** argv ) +{ + DateAndTime currentTime = { 0 }; + int32_t loop = 0; + int32_t totalLoops = 5U; + int32_t exitCode = 0; + + if( argc == 1 ) + { + printf( "This is a basic test application .\n" ); + printf( + "It prints the date and time and then sleeps for loopCount * 3\n" ); + printf( "This program takes in two inputs, a loop count and an exit " + "code\n" ); + printf( "By default it will run %d loops and exit with exit status " + "%d\n", + totalLoops, + exitCode ); + } + + if( argc == 2 ) + { + totalLoops = atoi( argv[ 1 ] ); + printf( "Will run for requested %d loops\n", totalLoops ); + } + + if( argc == 3 ) + { + exitCode = atoi( argv[ 2 ] ); + printf( "Will exit with supplied exit code %d\n", exitCode ); + } + + setvbuf( stdout, NULL, _IONBF, 0 ); + + for( int i = 1U; i < totalLoops; i++ ) + { + getTime( ¤tTime ); + printf( "%02llu:%02llu:%02llu.%03llu TEST APPLICATION SLEEPING FOR %d " + "SECONDS\n", + currentTime.hour, + currentTime.minutes, + currentTime.seconds, + currentTime.msec, + i * 3U ); + sleep( i * 3U ); + } + +#ifdef EXIT_WITH_MINUTES + exitCode = currentTime.minutes; +#endif + printf( "EXITING TEST APPLICATION WITH EXIT CODE = %d\n", exitCode ); + return exitCode; +} diff --git a/formatting/filesWithFormattingErrors/test.c b/clang-formatting/filesWithFormattingErrors/test.c similarity index 100% rename from formatting/filesWithFormattingErrors/test.c rename to clang-formatting/filesWithFormattingErrors/test.c diff --git a/formatting/filesWithTrailingWhitespace/myFile.log b/clang-formatting/filesWithTrailingWhitespace/myFile.log similarity index 100% rename from formatting/filesWithTrailingWhitespace/myFile.log rename to clang-formatting/filesWithTrailingWhitespace/myFile.log diff --git a/formatting/filesWithTrailingWhitespace/test.c b/clang-formatting/filesWithTrailingWhitespace/test.c similarity index 100% rename from formatting/filesWithTrailingWhitespace/test.c rename to clang-formatting/filesWithTrailingWhitespace/test.c diff --git a/clang-formatting/goodFiles/include/fileWithErrorInclude/errorFileInDirectory.h b/clang-formatting/goodFiles/include/fileWithErrorInclude/errorFileInDirectory.h new file mode 100644 index 00000000..e19ad502 --- /dev/null +++ b/clang-formatting/goodFiles/include/fileWithErrorInclude/errorFileInDirectory.h @@ -0,0 +1,49 @@ +#ifndef CGC_ERROR_H_ +#define CGC_ERROR_H_ + + + + + +#include +#include + +/* Error checking macros for the clock selction and clock enable defines */ + +#if( ( CLK_SOURCE != CLK_SOURCE_LOCO ) && ( CLK_SOURCE != CLK_SOURCE_HOCO ) && \ + ( CLK_SOURCE != CLK_SOURCE_MAIN ) && ( CLK_SOURCE != CLK_SOURCE_SUB ) && \ + ( CLK_SOURCE != CLK_SOURCE_PLL ) ) + #error "No CLK_SOURCE specified. Please specify a valid CLK_SOURCE"; +#endif + +#if( CLK_SOURCE == CLK_SOURCE_HOCO ) && ( ENABLE_HOCO == 0 ) + #error "HOCO has been specified as the CLK_SOURCE but dsafa ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_MAIN ) && ( ENABLE_MAIN == 0 ) + #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_SUB ) && ( ENABLE_SUB == 0 ) + #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_PLL ) && ( ENABLE_PLL == 0 ) + #error "PLL has been specified as the CLK_SOURCE but ENABLE_PLL is (0). Please set to (1) in file cgc.h and I am supppppppppppppppperrrrrrrrr long" +#endif + +#if( FCLK_FREQUENCY > 50000000L ) + #error "FCLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if( ICLK_FREQUENCY > 100000000L ) + #error "ICLK_FREQUENCY Error: Please enter a valid divider value" +#endif +#if( BCLK_FREQUENCY > 100000000L ) + #error "BCLK_FREQUENCY Error: Please enter a valid divider value" +#endif +#if( PCLKB_FREQUENCY > 50000000L ) + #error "PCLKB_FREQUENCY Error: Please enter a valid divider value" +#endif + +#endif \ No newline at end of file diff --git a/clang-formatting/goodFiles/include/fileWithErrorInclude/goodHeader.h b/clang-formatting/goodFiles/include/fileWithErrorInclude/goodHeader.h new file mode 100644 index 00000000..ddd3e44e --- /dev/null +++ b/clang-formatting/goodFiles/include/fileWithErrorInclude/goodHeader.h @@ -0,0 +1,48 @@ +#ifndef CGC_ERROR_H_ +#define CGC_ERROR_H_ + +/* Error checking macros for the clock selction and clock enable defines */ + +#if( ( CLK_SOURCE != CLK_SOURCE_LOCO ) && ( CLK_SOURCE != CLK_SOURCE_HOCO ) && \ + ( CLK_SOURCE != CLK_SOURCE_MAIN ) && ( CLK_SOURCE != CLK_SOURCE_SUB ) && \ + ( CLK_SOURCE != CLK_SOURCE_PLL ) ) + #error "No CLK_SOURCE specified. Please specify a valid CLK_SOURCE"; +#endif + +#if( CLK_SOURCE == CLK_SOURCE_HOCO ) && ( ENABLE_HOCO == 0 ) + #error \ + "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_MAIN ) && ( ENABLE_MAIN == 0 ) + #error \ + "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_SUB ) && ( ENABLE_SUB == 0 ) + #error \ + "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_PLL ) && ( ENABLE_PLL == 0 ) + #error \ + "PLL has been specified as the CLK_SOURCE but ENABLE_PLL is (0). Please set to (1) in file cgc.h" +#endif + +#if( FCLK_FREQUENCY > 50000000L ) + #error "FCLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if( ICLK_FREQUENCY > 100000000L ) + #error "ICLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if( BCLK_FREQUENCY > 100000000L ) + #error "BCLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if( PCLKB_FREQUENCY > 50000000L ) + #error "PCLKB_FREQUENCY Error: Please enter a valid divider value" +#endif + +#endif \ No newline at end of file diff --git a/clang-formatting/goodFiles/include/fileWithErrorInclude/goodTask.h b/clang-formatting/goodFiles/include/fileWithErrorInclude/goodTask.h new file mode 100644 index 00000000..ddd3e44e --- /dev/null +++ b/clang-formatting/goodFiles/include/fileWithErrorInclude/goodTask.h @@ -0,0 +1,48 @@ +#ifndef CGC_ERROR_H_ +#define CGC_ERROR_H_ + +/* Error checking macros for the clock selction and clock enable defines */ + +#if( ( CLK_SOURCE != CLK_SOURCE_LOCO ) && ( CLK_SOURCE != CLK_SOURCE_HOCO ) && \ + ( CLK_SOURCE != CLK_SOURCE_MAIN ) && ( CLK_SOURCE != CLK_SOURCE_SUB ) && \ + ( CLK_SOURCE != CLK_SOURCE_PLL ) ) + #error "No CLK_SOURCE specified. Please specify a valid CLK_SOURCE"; +#endif + +#if( CLK_SOURCE == CLK_SOURCE_HOCO ) && ( ENABLE_HOCO == 0 ) + #error \ + "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_MAIN ) && ( ENABLE_MAIN == 0 ) + #error \ + "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_SUB ) && ( ENABLE_SUB == 0 ) + #error \ + "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_PLL ) && ( ENABLE_PLL == 0 ) + #error \ + "PLL has been specified as the CLK_SOURCE but ENABLE_PLL is (0). Please set to (1) in file cgc.h" +#endif + +#if( FCLK_FREQUENCY > 50000000L ) + #error "FCLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if( ICLK_FREQUENCY > 100000000L ) + #error "ICLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if( BCLK_FREQUENCY > 100000000L ) + #error "BCLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if( PCLKB_FREQUENCY > 50000000L ) + #error "PCLKB_FREQUENCY Error: Please enter a valid divider value" +#endif + +#endif \ No newline at end of file diff --git a/clang-formatting/goodFiles/include/formatErrorTest.h b/clang-formatting/goodFiles/include/formatErrorTest.h new file mode 100644 index 00000000..e19ad502 --- /dev/null +++ b/clang-formatting/goodFiles/include/formatErrorTest.h @@ -0,0 +1,49 @@ +#ifndef CGC_ERROR_H_ +#define CGC_ERROR_H_ + + + + + +#include +#include + +/* Error checking macros for the clock selction and clock enable defines */ + +#if( ( CLK_SOURCE != CLK_SOURCE_LOCO ) && ( CLK_SOURCE != CLK_SOURCE_HOCO ) && \ + ( CLK_SOURCE != CLK_SOURCE_MAIN ) && ( CLK_SOURCE != CLK_SOURCE_SUB ) && \ + ( CLK_SOURCE != CLK_SOURCE_PLL ) ) + #error "No CLK_SOURCE specified. Please specify a valid CLK_SOURCE"; +#endif + +#if( CLK_SOURCE == CLK_SOURCE_HOCO ) && ( ENABLE_HOCO == 0 ) + #error "HOCO has been specified as the CLK_SOURCE but dsafa ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_MAIN ) && ( ENABLE_MAIN == 0 ) + #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_SUB ) && ( ENABLE_SUB == 0 ) + #error "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_PLL ) && ( ENABLE_PLL == 0 ) + #error "PLL has been specified as the CLK_SOURCE but ENABLE_PLL is (0). Please set to (1) in file cgc.h and I am supppppppppppppppperrrrrrrrr long" +#endif + +#if( FCLK_FREQUENCY > 50000000L ) + #error "FCLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if( ICLK_FREQUENCY > 100000000L ) + #error "ICLK_FREQUENCY Error: Please enter a valid divider value" +#endif +#if( BCLK_FREQUENCY > 100000000L ) + #error "BCLK_FREQUENCY Error: Please enter a valid divider value" +#endif +#if( PCLKB_FREQUENCY > 50000000L ) + #error "PCLKB_FREQUENCY Error: Please enter a valid divider value" +#endif + +#endif \ No newline at end of file diff --git a/clang-formatting/goodFiles/include/headerFile.h b/clang-formatting/goodFiles/include/headerFile.h new file mode 100644 index 00000000..ddd3e44e --- /dev/null +++ b/clang-formatting/goodFiles/include/headerFile.h @@ -0,0 +1,48 @@ +#ifndef CGC_ERROR_H_ +#define CGC_ERROR_H_ + +/* Error checking macros for the clock selction and clock enable defines */ + +#if( ( CLK_SOURCE != CLK_SOURCE_LOCO ) && ( CLK_SOURCE != CLK_SOURCE_HOCO ) && \ + ( CLK_SOURCE != CLK_SOURCE_MAIN ) && ( CLK_SOURCE != CLK_SOURCE_SUB ) && \ + ( CLK_SOURCE != CLK_SOURCE_PLL ) ) + #error "No CLK_SOURCE specified. Please specify a valid CLK_SOURCE"; +#endif + +#if( CLK_SOURCE == CLK_SOURCE_HOCO ) && ( ENABLE_HOCO == 0 ) + #error \ + "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_MAIN ) && ( ENABLE_MAIN == 0 ) + #error \ + "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_SUB ) && ( ENABLE_SUB == 0 ) + #error \ + "HOCO has been specified as the CLK_SOURCE but ENABLE_HOCO is (0). Please set to (1) in file cgc.h" +#endif + +#if( CLK_SOURCE == CLK_SOURCE_PLL ) && ( ENABLE_PLL == 0 ) + #error \ + "PLL has been specified as the CLK_SOURCE but ENABLE_PLL is (0). Please set to (1) in file cgc.h" +#endif + +#if( FCLK_FREQUENCY > 50000000L ) + #error "FCLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if( ICLK_FREQUENCY > 100000000L ) + #error "ICLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if( BCLK_FREQUENCY > 100000000L ) + #error "BCLK_FREQUENCY Error: Please enter a valid divider value" +#endif + +#if( PCLKB_FREQUENCY > 50000000L ) + #error "PCLKB_FREQUENCY Error: Please enter a valid divider value" +#endif + +#endif \ No newline at end of file diff --git a/formatting/goodFiles/source/README.md b/clang-formatting/goodFiles/source/README.md similarity index 100% rename from formatting/goodFiles/source/README.md rename to clang-formatting/goodFiles/source/README.md diff --git a/formatting/goodFiles/source/fileWithErrorSource/goodTest.c b/clang-formatting/goodFiles/source/core_mqtt.c similarity index 100% rename from formatting/goodFiles/source/fileWithErrorSource/goodTest.c rename to clang-formatting/goodFiles/source/core_mqtt.c diff --git a/formatting/goodFiles/source/fileWithErrorSource/errorFileInDirectory.c b/clang-formatting/goodFiles/source/fileWithErrorSource/errorFileInDirectory.c similarity index 100% rename from formatting/goodFiles/source/fileWithErrorSource/errorFileInDirectory.c rename to clang-formatting/goodFiles/source/fileWithErrorSource/errorFileInDirectory.c diff --git a/formatting/goodFiles/source/test.c b/clang-formatting/goodFiles/source/fileWithErrorSource/goodTest.c similarity index 100% rename from formatting/goodFiles/source/test.c rename to clang-formatting/goodFiles/source/fileWithErrorSource/goodTest.c diff --git a/formatting/goodFiles/source/formatErrorTest.c b/clang-formatting/goodFiles/source/formatErrorTest.c similarity index 100% rename from formatting/goodFiles/source/formatErrorTest.c rename to clang-formatting/goodFiles/source/formatErrorTest.c diff --git a/clang-formatting/goodFiles/source/tasks.c b/clang-formatting/goodFiles/source/tasks.c new file mode 100644 index 00000000..26665c49 --- /dev/null +++ b/clang-formatting/goodFiles/source/tasks.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include + +typedef struct DateAndTime +{ + uint64_t hour; + uint64_t minutes; + uint64_t seconds; + uint64_t msec; +} DateAndTime; + +#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || \ + defined( __NT__ ) || defined( WIN64 ) || defined( __WIN64 ) + #include +/* Remove the warning about implicit sleep even with windows.h included */ +extern void sleep( int miliseconds ); +void getTime( struct DateAndTime * currentTime ) +{ + SYSTEMTIME st, lt; + + GetLocalTime( < ); + currentTime->hour = lt.wHour; + currentTime->minutes = lt.wMinute; + currentTime->seconds = lt.wSecond; + currentTime->msec = lt.wMilliseconds; +} +#else /* if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || \ + defined( __NT__ ) || defined( WIN64 ) || defined( __WIN64 ) */ + #include + #include +void getTime( struct DateAndTime * currentTime ) +{ + struct timeval tv; + struct tm * tm; + + gettimeofday( &tv, NULL ); + tm = localtime( &tv.tv_sec ); + currentTime->hour = tm->tm_hour; + currentTime->minutes = tm->tm_min; + currentTime->seconds = tm->tm_sec; + currentTime->msec = ( int ) ( tv.tv_usec / 1000 ); +} +#endif /* if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || \ + defined( __NT__ ) || defined( WIN64 ) || defined( __WIN64 ) */ + +int main( int argc, char ** argv ) +{ + DateAndTime currentTime = { 0 }; + int32_t loop = 0; + int32_t totalLoops = 5U; + int32_t exitCode = 0; + + if( argc == 1 ) + { + printf( "This is a basic test application.\n" ); + printf( + "It prints the date and time and then sleeps for loopCount * 3\n" ); + printf( "This program takes in two inputs, a loop count and an exit " + "code\n" ); + printf( "By default it will run %d loops and exit with exit status " + "%d\n", + totalLoops, + exitCode ); + } + + if( argc == 2 ) + { + totalLoops = atoi( argv[ 1 ] ); + printf( "Will run for requested %d loops\n", totalLoops ); + } + + if( argc == 3 ) + { + exitCode = atoi( argv[ 2 ] ); + printf( "Will exit with supplied exit code %d\n", exitCode ); + } + + setvbuf( stdout, NULL, _IONBF, 0 ); + + for( int i = 1U; i < totalLoops; i++ ) + { + getTime( ¤tTime ); + printf( "%02llu:%02llu:%02llu.%03llu TEST APPLICATION SLEEPING FOR %d " + "SECONDS\n", + currentTime.hour, + currentTime.minutes, + currentTime.seconds, + currentTime.msec, + i * 3U ); + sleep( i * 3U ); + } + +#ifdef EXIT_WITH_MINUTES + exitCode = currentTime.minutes; +#endif + printf( "EXITING TEST APPLICATION WITH EXIT CODE = %d\n", exitCode ); + return exitCode; +} diff --git a/clang-formatting/goodFiles/source/test.c b/clang-formatting/goodFiles/source/test.c new file mode 100644 index 00000000..26665c49 --- /dev/null +++ b/clang-formatting/goodFiles/source/test.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include + +typedef struct DateAndTime +{ + uint64_t hour; + uint64_t minutes; + uint64_t seconds; + uint64_t msec; +} DateAndTime; + +#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || \ + defined( __NT__ ) || defined( WIN64 ) || defined( __WIN64 ) + #include +/* Remove the warning about implicit sleep even with windows.h included */ +extern void sleep( int miliseconds ); +void getTime( struct DateAndTime * currentTime ) +{ + SYSTEMTIME st, lt; + + GetLocalTime( < ); + currentTime->hour = lt.wHour; + currentTime->minutes = lt.wMinute; + currentTime->seconds = lt.wSecond; + currentTime->msec = lt.wMilliseconds; +} +#else /* if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || \ + defined( __NT__ ) || defined( WIN64 ) || defined( __WIN64 ) */ + #include + #include +void getTime( struct DateAndTime * currentTime ) +{ + struct timeval tv; + struct tm * tm; + + gettimeofday( &tv, NULL ); + tm = localtime( &tv.tv_sec ); + currentTime->hour = tm->tm_hour; + currentTime->minutes = tm->tm_min; + currentTime->seconds = tm->tm_sec; + currentTime->msec = ( int ) ( tv.tv_usec / 1000 ); +} +#endif /* if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || \ + defined( __NT__ ) || defined( WIN64 ) || defined( __WIN64 ) */ + +int main( int argc, char ** argv ) +{ + DateAndTime currentTime = { 0 }; + int32_t loop = 0; + int32_t totalLoops = 5U; + int32_t exitCode = 0; + + if( argc == 1 ) + { + printf( "This is a basic test application.\n" ); + printf( + "It prints the date and time and then sleeps for loopCount * 3\n" ); + printf( "This program takes in two inputs, a loop count and an exit " + "code\n" ); + printf( "By default it will run %d loops and exit with exit status " + "%d\n", + totalLoops, + exitCode ); + } + + if( argc == 2 ) + { + totalLoops = atoi( argv[ 1 ] ); + printf( "Will run for requested %d loops\n", totalLoops ); + } + + if( argc == 3 ) + { + exitCode = atoi( argv[ 2 ] ); + printf( "Will exit with supplied exit code %d\n", exitCode ); + } + + setvbuf( stdout, NULL, _IONBF, 0 ); + + for( int i = 1U; i < totalLoops; i++ ) + { + getTime( ¤tTime ); + printf( "%02llu:%02llu:%02llu.%03llu TEST APPLICATION SLEEPING FOR %d " + "SECONDS\n", + currentTime.hour, + currentTime.minutes, + currentTime.seconds, + currentTime.msec, + i * 3U ); + sleep( i * 3U ); + } + +#ifdef EXIT_WITH_MINUTES + exitCode = currentTime.minutes; +#endif + printf( "EXITING TEST APPLICATION WITH EXIT CODE = %d\n", exitCode ); + return exitCode; +} diff --git a/formatting/action.yml b/formatting/action.yml index 08573f76..8ac71180 100644 --- a/formatting/action.yml +++ b/formatting/action.yml @@ -2,178 +2,78 @@ name: 'formatting' description: 'CI formatting check' inputs: path: - description: 'Path to repository folder to run formatting check for. ' + description: 'Path to repository folder to run formatting check for.' required: false default: ./ exclude-files: - description: 'List of comma-separated files to exclude from the formatting check. Eg file1, file2' + description: 'List of comma-separated files to exclude from trailing whitespace check. Eg file1,file2' required: false default: '' exclude-dirs: - description: 'List of comma-separated directories to exclude from the formatting check. Eg docs, build' + description: 'List of comma-separated directories to exclude from trailing whitespace formatting check. Eg docs,build' required: false default: '' - include-extensions: - description: 'List of comma-separated extensions to add to the formatting check. Eg md, dox' - required: false - default: '' - runs: using: "composite" - steps: - - env: - # At time of writing, you can't add a global environment - # to an action file so stuck with this. If this gets changed - # Please move this - bashPass: \033[32;1mPASSED - - bashInfo: \033[33;1mINFO - - bashFail: \033[31;1mFAILED - - bashEnd: \033[0m - stepName: Install Clang Format - name: ${{ env.stepName }} + steps: + - name: Install Uncrustify + run: | + : # Install Uncrustify + echo "::group::Install Uncrustify" + sudo apt-get install uncrustify + echo "::endgroup::" shell: bash + - name: Run Uncrustify + working-directory: ${{ inputs.path }} run: | - # ${{ env.stepName }} - echo "::group::${{ env.stepName }}" - sudo apt-get install clang-format fd-find dos2unix - echo "$GITHUB_ACTION_PATH" >> $GITHUB_PATH - export PATH="$PATH:$GITHUB_ACTION_PATH" - - fdfind --version - fdInstalled=$? - - clang-format --version - clangFormatInstalled=$? - - getFiles --help - getFilesAdded=$? - + : # Uncrustify on C files while ignoring symlinks. + : # Make a collapsible section in the log to run uncrustify + echo "::group::Uncrustify Check" + : # GitHub automtically use "set -e" which causes scripts to fail on the first exit code + : # This would mean the first time a file fails the check that we exit without formatting all files. + set +e + : # Format all the files using the common config file. + find . -iname "*.[ch]" | xargs uncrustify --no-backup --replace --if-changed -c $GITHUB_ACTION_PATH/uncrustify.cfg -l C echo "::endgroup::" - if [ $getFilesAdded -eq 1 ] || [ $clangFormatInstalled -eq 1 ] || [ $fdInstalled -eq 1 ]; then - echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}" - exit 1 - else - echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}" + : # Run a git diff to print the differences if any exist, return an error code if there are any + git diff --exit-code + if [ "$?" = "0" ]; then + echo -e "\033[32;3mUncrustify check passed\033[0m" exit 0 + else + echo -e "\033[32;31mFormatting check (using Uncrustify) failed...\033[0m" + : # If there is an error, set this flag high again so the exit 1 fails the run + set -e + exit 1 fi - - - env: - stepName: Validate Inputs - bashPass: \033[32;1mPASSED - - bashInfo: \033[33;1mINFO - - bashFail: \033[31;1mFAILED - - bashEnd: \033[0m - name: ${{ env.stepName }} - id: validate-inputs shell: bash + - name: Check For Trailing Whitespace + working-directory: ${{ inputs.path }} run: | - # ${{ env.stepName }} - # Check exclude dirs for possible input issues - if [[ "${{ inputs.exclude-dirs }}" = *"\n"* ]]; then - echo -e "${{ env.bashFail }} YOU HAVE NEWLINE IN YOUR EXCLUDE-DIRS. ${{ env.bashEnd }}" - exitStatus=1 + : # Trailing Whitespace Check + set +e + grep --exclude={README.md,${{ inputs.exclude-files }}} --exclude-dir={${{ inputs.exclude-dirs }},'.git'} -rnI -e "[[:blank:]]$" . + if [ "$?" = "0" ]; then + set -e + echo -e "\033[32;31mFiles have trailing whitespace.\033[0m" + exit 1 + else + echo -e "\033[32;3mTrailing whitespace check passed\033[0m" + exit 0 fi - - - env: - bashPass: \033[32;1mPASSED - - bashInfo: \033[33;1mINFO - - bashFail: \033[31;1mFAILED - - bashEnd: \033[0m - stepName: Check Format of Files - name: ${{ env.stepName }} - id: action-formatting-check - if: ${{ steps.validate-inputs.outcome}} = "success" - working-directory: ${{ inputs.path }} shell: bash + - name: Check for CRLF + working-directory: ${{ inputs.path }} run: | - # ${{ env.stepName }} - echo -e "${{ env.bashInfo }} Using clang-format version "$(clang-format --version)" ${{ env.bashEnd }}" - echo "::group::${{ env.stepName }}" - exitCode=0 - export PATH="$PATH:$GITHUB_ACTION_PATH" - - # TODO: These checks should really only run against modified files on PRS - # Where when the commit to the actual repo happens, then we should trigger the job - # Against all of the files in the repo. Nice inbetween to keep checks fast for PRs, - # But maintain that we don't have a change in the Repo that suddenly causes an issue - files=$(getFiles --exclude-files="${{inputs.exclude-files}}" --exclude-dir="${{inputs.exclude-dirs}}" ) - if ! [ $? -eq 0 ]; then - echo -e "${{ env.bashFail }} Error calling getFiles() ${{ env.bashEnd }}" - echo -e "$fileOut" - exit 1 - fi - - # Loop over the files that matched the above conditions - for file in ${files[@]}; do - - # set +e so we don't exit on the first file with an error - # Doing it here instead of over the whole loop incase there - # Is an error that gets raised in the loop (somehow) - set +e - - # Pipe the output of the command to a variable - # This way we can print the command only if it fails - fileOut=$(clang-format -i --verbose --style=file $file) - - # Re-enable failing or error - set -e - - done - - - # These checks will be captured in the git diff - - # Replace all trailing whitespace - fdfind --type=file . --exec sed -Ei 's/[[:blank:]]+$//' - - # Replace all line endings with LF ones instead of CRLF - fdfind --type=file . --exec dos2unix - - echo "::endgroup::" - # Run a git diff to print the differences if any exist, return an error code if there are any - - echo "::group::File Difference" + : # Check for CRLF Line Ending set +e - git diff --exit-code --color=always - exitCode=$? - set -e - echo "::endgroup::" - - if [ $exitCode -eq 0 ]; then - echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}" + find . -path ./.git -prune -o -exec file {} + | grep "CRLF" + if [ "$?" = "0" ]; then + set -e + echo -e "\033[32;31mFiles have CRLF line endings.\033[0m" + exit 1 else - # I am intentionally doing this a second time here. - # Using tee will mask the exit code of the diff - # And we don't want the colour to be added to the patch - # Put it in what the 'default' path will be for the upload step - git diff > formattingChanges.patch - echo -e "${{ env.bashFail }} List of files with formatting errors: ${{ env.bashEnd }}" - echo -e "${{ env.bashFail }} "$(git diff --name-only)" ${{ env.bashEnd }} " - echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}" + echo -e "\033[32;3mLine ending check passed\033[0m" + exit 0 fi - exit $exitCode - - - name: Upload Formatting Git Patch - if: failure() && ( steps.action-formatting-check.outcome == 'failure' ) - id: upload-formatting-patch - uses: actions/upload-artifact@v3 - with: - name: formattingChanges - path: ${{ inputs.path }}/formattingChanges.patch - retention-days: 7 - - - env: - stepName: Formatting Git Patch Info - bashPass: \033[32;1m - bashInfo: \033[33;1m - bashFail: \033[31;1m - bashEnd: \033[0 - if: failure() && ( steps.upload-formatting-patch.outcome == 'success' ) shell: bash - run: | - # ${{ env.stepName }} - echo -e "${{ env.bashInfo }} A git patch of the formatting issues has been attached to this workflow ${{ env.bashEnd }}" - echo -e "${{ env.bashInfo }} This can be accessed by returning to the bottom of the summary page of the workflow run ${{ env.bashEnd }}" - echo -e "${{ env.bashInfo }} At the bottom of the page will be a formattingChanges.patch file that you can download ${{ env.bashEnd }}" - echo -e "${{ env.bashInfo }} Copy this patch to your repository and apply it using 'git apply formattingChanges.patch' ${{ env.bashEnd }}" - exit 1 diff --git a/formatting/filesWithCRLFEndings/main-blinky.c b/formatting/filesWithCRLFEndings/main-blinky.c deleted file mode 100644 index 0eaca8b0..00000000 --- a/formatting/filesWithCRLFEndings/main-blinky.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * FreeRTOS V202212.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * 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 - * - */ - -/****************************************************************************** - * NOTE 1: This project provides two demo applications. A simple blinky style - * project, and a more comprehensive test and demo application. The - * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select - * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY - * in main.c. This file implements the simply blinky style version. - * - * NOTE 2: This file only contains the source code that is specific to the - * basic demo. Generic functions, such FreeRTOS hook functions, and functions - * required to configure the hardware, are defined in main.c. - ****************************************************************************** - * - * main_blinky() creates one queue, and two tasks. It then starts the - * scheduler. - * - * The Queue Send Task: - * The queue send task is implemented by the prvQueueSendTask() function in - * this file. prvQueueSendTask() sits in a loop that causes it to repeatedly - * block for 200 milliseconds before sending the value 100 to the queue that - * was created within main_blinky(). Once the value is sent, the task loops - * back around to block for another 200 milliseconds. - * - * The Queue Receive Task: - * The queue receive task is implemented by the prvQueueReceiveTask() function - * in this file. prvQueueReceiveTask() sits in a loop where it repeatedly - * blocks on attempts to read data from the queue that was created within - * main_blinky(). When data is received, the task checks the value of the - * data, and if the value equals the expected 100, toggles the LED. The 'block - * time' parameter passed to the queue receive function specifies that the - * task should be held in the Blocked state indefinitely to wait for data to - * be available on the queue. The queue receive task will only leave the - * Blocked state when the queue send task writes to the queue. As the queue - * send task writes to the queue every 200 milliseconds, the queue receive - * task leaves the Blocked state every 200 milliseconds, and therefore toggles - * the LED every 200 milliseconds. - */ - -/* Kernel includes. */ -#include "FreeRTOS.h" -#include "task.h" -#include "queue.h" - -/* Priorities at which the tasks are created. */ -#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) -#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) - -/* The rate at which data is sent to the queue. The 200ms value is converted -to ticks using the portTICK_PERIOD_MS constant. */ -#define mainQUEUE_SEND_FREQUENCY_MS ( 200 / portTICK_PERIOD_MS ) - -/* The number of items the queue can hold. This is 1 as the receive task -will remove items as they are added, meaning the send task should always find -the queue empty. */ -#define mainQUEUE_LENGTH ( 1 ) - -/* Values passed to the two tasks just to check the task parameter -functionality. */ -#define mainQUEUE_SEND_PARAMETER ( 0x1111UL ) -#define mainQUEUE_RECEIVE_PARAMETER ( 0x22UL ) - - -/*-----------------------------------------------------------*/ - -/* - * The tasks as described in the comments at the top of this file. - */ -static void prvQueueReceiveTask( void *pvParameters ); -static void prvQueueSendTask( void *pvParameters ); - -/* - * Called by main() to create the simply blinky style application if - * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1. - */ -void main_blinky( void ); - -/*-----------------------------------------------------------*/ - -/* The queue used by both tasks. */ -static QueueHandle_t xQueue = NULL; - -/*-----------------------------------------------------------*/ - -void main_blinky( void ) -{ - /* Create the queue. */ - xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) ); - - if( xQueue != NULL ) - { - /* Start the two tasks as described in the comments at the top of this - file. */ - xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */ - "Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */ - configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */ - ( void * ) mainQUEUE_RECEIVE_PARAMETER, /* The parameter passed to the task - just to check the functionality. */ - mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */ - NULL ); /* The task handle is not required, so NULL is passed. */ - - xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, ( void * ) mainQUEUE_SEND_PARAMETER, mainQUEUE_SEND_TASK_PRIORITY, NULL ); - - /* Start the tasks and timer running. */ - vTaskStartScheduler(); - } - - /* If all is well, the scheduler will now be running, and the following - line will never be reached. If the following line does execute, then - there was insufficient FreeRTOS heap memory available for the idle and/or - timer tasks to be created. See the memory management section on the - FreeRTOS web site for more details. */ - for( ;; ); -} -/*-----------------------------------------------------------*/ - -static void prvQueueSendTask( void *pvParameters ) -{ -TickType_t xNextWakeTime; -const unsigned long ulValueToSend = 100UL; - - /* Check the task parameter is as expected. */ - configASSERT( ( ( unsigned long ) pvParameters ) == mainQUEUE_SEND_PARAMETER ); - - /* Initialise xNextWakeTime - this only needs to be done once. */ - xNextWakeTime = xTaskGetTickCount(); - - for( ;; ) - { - /* Place this task in the blocked state until it is time to run again. - The block time is specified in ticks, the constant used converts ticks - to ms. While in the Blocked state this task will not consume any CPU - time. */ - vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS ); - - /* Send to the queue - causing the queue receive task to unblock and - toggle the LED. 0 is used as the block time so the sending operation - will not block - it shouldn't need to block as the queue should always - be empty at this point in the code. */ - xQueueSend( xQueue, &ulValueToSend, 0U ); - } -} -/*-----------------------------------------------------------*/ - -static void prvQueueReceiveTask( void *pvParameters ) -{ -unsigned long ulReceivedValue; - - /* Check the task parameter is as expected. */ - configASSERT( ( ( unsigned long ) pvParameters ) == mainQUEUE_RECEIVE_PARAMETER ); - - for( ;; ) - { - /* Wait until something arrives in the queue - this task will block - indefinitely provided INCLUDE_vTaskSuspend is set to 1 in - FreeRTOSConfig.h. */ - xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY ); - - /* To get here something must have been received from the queue, but - is it the expected value? If it is, toggle the LED. */ - if( ulReceivedValue == 100UL ) - { - /* Toggle the LED. */ - port_pin_toggle_output_level( LED_0_PIN ); - ulReceivedValue = 0U; - } - } -} -/*-----------------------------------------------------------*/ - diff --git a/formatting/filesWithFormattingErrors/fileFormattedWithClangFormatV16.c b/formatting/filesWithFormattingErrors/fileFormattedWithClangFormatV16.c deleted file mode 100644 index 3a642c3e..00000000 --- a/formatting/filesWithFormattingErrors/fileFormattedWithClangFormatV16.c +++ /dev/null @@ -1,6151 +0,0 @@ -/* - * FreeRTOS Kernel - * 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 -#include - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining - * all the API functions to use the MPU wrappers. That should only be done when - * task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -/* FreeRTOS includes. */ -#include "FreeRTOS.h" -#include "stack_macros.h" -#include "task.h" -#include "timers.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 -#endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 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 - -/* 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 */ - -/*-----------------------------------------------------------*/ - - #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 */ - -/*-----------------------------------------------------------*/ - -/* 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 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 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 - - 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. */ - 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( ( 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. */ -portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL; - -/* 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 xYieldPending = 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 - xIdleTaskHandle = NULL; /**< Holds the handle of the idle task. The idle - task is 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. */ -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 = 0UL; /**< Holds the value of a timer/counter the last - time a task was switched in. */ -PRIVILEGED_DATA static volatile configRUN_TIME_COUNTER_TYPE - ulTotalRunTime = 0UL; /**< Holds the total amount of execution time as - defined by the run time counter clock. */ - -#endif - -/*lint -restore */ - -/*-----------------------------------------------------------*/ - -/* File private functions. --------------------------------*/ - -/** - * 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. - * - * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific - * language extensions. The equivalent prototype for this function is: - * - * void prvIdleTask( void *pvParameters ); - * - */ -static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ) PRIVILEGED_FUNCTION; - -/* - * 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( 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 ) -{ - 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. */ - 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 ); - 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 ) -{ - 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; - 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 ); - - 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 ) -{ - TCB_t * pxNewTCB; - BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; - - configASSERT( pxTaskDefinition->puxStackBuffer ); - - if( pxTaskDefinition->puxStackBuffer != 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 * ) pvPortMalloc( sizeof( TCB_t ) ); - - if( pxNewTCB != NULL ) - { - 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 ); - - 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 ) -{ - 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 ) - { - 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 ) - { - 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 ); - 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 - -/* 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 */ - - 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(); - } -} -/*-----------------------------------------------------------*/ - -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(); - } -} -/*-----------------------------------------------------------*/ - -#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( pxTCB == pxCurrentTCB ) - { - /* A task is deleting itself. 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. */ - portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending ); - } - else - { - --uxCurrentNumberOfTasks; - traceTASK_DELETE( pxTCB ); - - /* Reset the next expected unblock time in case it referred to - * the task that has just been deleted. */ - prvResetNextTaskUnblockTime(); - } - } - 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 == ( UBaseType_t ) 0U ); - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } -} - -#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 ) ); - configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U ); - - vTaskSuspendAll(); - { - /* Minor optimisation. The tick count cannot change in this - * block. */ - const TickType_t xConstTickCount = xTickCount; - - /* 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 ) - { - portYIELD_WITHIN_API(); - } - 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 ) - { - configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U ); - vTaskSuspendAll(); - { - 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 ) - { - portYIELD_WITHIN_API(); - } - 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( pxTCB == pxCurrentTCB ) - { - /* The task calling this function is querying its own state. */ - eReturn = eRunning; - } - else - { - 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 = 0; x < 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 the task is not in any other state, it must be in the - * Ready (including pending ready) state. */ - eReturn = eReady; - } - } - - 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 uxSavedInterruptState; - - /* 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(); - - uxSavedInterruptState = portSET_INTERRUPT_MASK_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; - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState ); - - 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; - - 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 the calling task. */ - if( uxNewPriority > uxCurrentBasePriority ) - { - 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( pxTCB == pxCurrentTCB ) - { - /* Setting the priority of the running task down means - * there may now be another task of higher priority that - * is ready to execute. */ - 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 - { - mtCOVERAGE_TEST_MARKER(); - } - - if( xYieldRequired != pdFALSE ) - { - taskYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - /* Remove compiler warning about unused variables when the port - * optimised task selection is not being used. */ - ( void ) uxPriorityUsedOnEntry; - } - } - taskEXIT_CRITICAL(); -} - -#endif /* INCLUDE_vTaskPrioritySet */ -/*-----------------------------------------------------------*/ - -#if( INCLUDE_vTaskSuspend == 1 ) - -void vTaskSuspend( TaskHandle_t xTaskToSuspend ) -{ - TCB_t * pxTCB; - - taskENTER_CRITICAL(); - { - /* If null is passed in here then it is the running task that is - * being suspended. */ - pxTCB = prvGetTCBFromHandle( xTaskToSuspend ); - - traceTASK_SUSPEND( pxTCB ); - - /* 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 = 0; x < 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 ) */ - } - 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 == ( UBaseType_t ) 0U ); - 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(); - } -} - -#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 ); - - /* The parameter cannot be NULL as it is impossible to resume the - * currently executing task. */ - if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) ) - { - 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 ); - - /* 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 - { - 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 = portSET_INTERRUPT_MASK_FROM_ISR(); - { - if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) - { - traceTASK_RESUME_FROM_ISR( pxTCB ); - - /* Check the ready lists can be accessed. */ - if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) - { - /* 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. */ - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - ( 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 ) ); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - - return xYieldRequired; -} - -#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 \ - ) ) */ -/*-----------------------------------------------------------*/ - -void vTaskStartScheduler( void ) -{ - BaseType_t xReturn; - -/* 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 ); - xIdleTaskHandle = 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( xIdleTaskHandle != 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. - */ - &xIdleTaskHandle ); /*lint !e961 MISRA exception, - justified as it is not a - redundant explicit cast to - all supported compilers. - */ - } -#endif /* configSUPPORT_STATIC_ALLOCATION */ - -#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 xIdleTaskHandle is not used anywhere else. */ - ( void ) xIdleTaskHandle; - - /* 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 ) -{ - /* 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(); -} -/*----------------------------------------------------------*/ - -#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 uxSchedulerSuspended is zero then this function does not match a - * previous call to vTaskSuspendAll(). */ - configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U ); - - /* 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(); - { - --uxSchedulerSuspended; - - 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 and co-routines 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 the moved task has a priority higher than the current - * task then a yield must be performed. */ - if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) - { - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - - 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. */ - { - TickType_t xPendedCounts = xPendedTicks; /* Non-volatile - copy. */ - - if( xPendedCounts > ( TickType_t ) 0U ) - { - do - { - if( xTaskIncrementTick() != pdFALSE ) - { - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - --xPendedCounts; - } while( xPendedCounts > ( TickType_t ) 0U ); - - xPendedTicks = 0; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - - if( xYieldPending != pdFALSE ) - { -#if( configUSE_PREEMPTION != 0 ) - { - xAlreadyYielded = pdTRUE; - } -#endif - taskYIELD_IF_USING_PREEMPTION(); - } - 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 ) - -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 - and co-routines 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 and co-routines - 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; -} - -#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 ) - -TaskHandle_t xTaskGetIdleTaskHandle( void ) -{ - /* If xTaskGetIdleTaskHandle() is called before the scheduler has been - * started, then xIdleTaskHandle will be NULL. */ - configASSERT( ( xIdleTaskHandle != NULL ) ); - return xIdleTaskHandle; -} - -#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 ) - { - /* 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. */ - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_PREEMPTION */ - } - else - { - xReturn = pdFAIL; - } - } - ( void ) xTaskResumeAll(); - - return xReturn; -} - -#endif /* INCLUDE_xTaskAbortDelay */ -/*----------------------------------------------------------*/ - -BaseType_t xTaskIncrementTick( void ) -{ - TCB_t * pxTCB; - TickType_t xItemValue; - BaseType_t xSwitchRequired = pdFALSE; - - /* 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 ); - - 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 ) - { - /* 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(); - } - } -#endif /* configUSE_PREEMPTION */ - } - } - } - -/* 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( listCURRENT_LIST_LENGTH( - &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > - ( UBaseType_t ) 1 ) - { - xSwitchRequired = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } -#endif /* ( ( 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( xYieldPending != pdFALSE ) - { - xSwitchRequired = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } -#endif /* configUSE_PREEMPTION */ - } - 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 = portSET_INTERRUPT_MASK_FROM_ISR(); - { - xReturn = pxTCB->pxTaskTag; - } - portCLEAR_INTERRUPT_MASK_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 */ -/*-----------------------------------------------------------*/ - -void vTaskSwitchContext( void ) -{ - if( uxSchedulerSuspended != ( UBaseType_t ) 0U ) - { - /* The scheduler is currently suspended - do not allow a context - * switch. */ - xYieldPending = pdTRUE; - } - else - { - xYieldPending = pdFALSE; - traceTASK_SWITCHED_OUT(); - -#if( configGENERATE_RUN_TIME_STATS == 1 ) - { - #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE - portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); - #else - ulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) - 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 > ulTaskSwitchedInTime ) - { - pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - - ulTaskSwitchedInTime ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - ulTaskSwitchedInTime = ulTotalRunTime; - } -#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 and - co-routines 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 - } -} -/*-----------------------------------------------------------*/ - -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( 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. */ - xYieldPending = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - - 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( 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). */ - xYieldPending = pdTRUE; - } -} -/*-----------------------------------------------------------*/ - -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 ) -{ - xYieldPending = 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 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 ); - - for( ;; ) - { - /* 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 more than one - * task then a task other than the idle task is ready to execute. */ - if( listCURRENT_LIST_LENGTH( - &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > - ( UBaseType_t ) 1 ) - { - 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( 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( xYieldPending != 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 < 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 < 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 xRegions ) -{ - 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 ), xRegions, 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 ) - { - taskENTER_CRITICAL(); - { - pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( - &xTasksWaitingTermination ) ); /*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. */ - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); - --uxCurrentNumberOfTasks; - --uxDeletedTasksWaitingCleanUp; - } - taskEXIT_CRITICAL(); - - prvDeleteTCB( pxTCB ); - } - } -#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_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( pxTCB == pxCurrentTCB ) - { - 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( pxCurrentTCB->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 ) ) - -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; -} - -#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( uxSchedulerSuspended == ( UBaseType_t ) 0U ) - { - xReturn = taskSCHEDULER_RUNNING; - } - else - { - xReturn = taskSCHEDULER_SUSPENDED; - } - } - - 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 ); - } - 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 ); - - /* 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 ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } -} - -#endif /* configUSE_MUTEXES */ -/*-----------------------------------------------------------*/ - -#if( portCRITICAL_NESTING_IN_TCB == 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 /* portCRITICAL_NESTING_IN_TCB */ -/*-----------------------------------------------------------*/ - -#if( portCRITICAL_NESTING_IN_TCB == 1 ) - -void vTaskExitCritical( void ) -{ - if( xSchedulerRunning != pdFALSE ) - { - 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 /* portCRITICAL_NESTING_IN_TCB */ -/*-----------------------------------------------------------*/ - -#if( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) - -static char * prvWriteNameToBuffer( char * pcBuffer, const char * pcTaskName ) -{ - size_t x; - - /* Start by copying the entire string. */ - 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 ) ( configMAX_TASK_NAME_LEN - 1 ); - 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 ) -{ - /* If xSemaphoreCreateMutex() is called before any tasks have been created - * then pxCurrentTCB will be NULL. */ - if( pxCurrentTCB != NULL ) - { - ( pxCurrentTCB->uxMutexesHeld )++; - } - - return pxCurrentTCB; -} - -#endif /* configUSE_MUTEXES */ -/*-----------------------------------------------------------*/ - -#if( configUSE_TASK_NOTIFICATIONS == 1 ) - -uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait, - BaseType_t xClearCountOnExit, - TickType_t xTicksToWait ) -{ - uint32_t ulReturn; - - configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES ); - - taskENTER_CRITICAL(); - { - /* Only block if the notification count is not already non-zero. */ - if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL ) - { - /* Mark this task as waiting for a notification. */ - pxCurrentTCB - ->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; - - if( xTicksToWait > ( TickType_t ) 0 ) - { - prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); - traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait ); - - /* 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. */ - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL(); - - taskENTER_CRITICAL(); - { - traceTASK_NOTIFY_TAKE( uxIndexToWait ); - ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ]; - - if( ulReturn != 0UL ) - { - if( xClearCountOnExit != pdFALSE ) - { - pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = 0UL; - } - else - { - pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = ulReturn - - ( uint32_t ) 1; - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - pxCurrentTCB - ->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION; - } - taskEXIT_CRITICAL(); - - return ulReturn; -} - -#endif /* configUSE_TASK_NOTIFICATIONS */ -/*-----------------------------------------------------------*/ - -#if( configUSE_TASK_NOTIFICATIONS == 1 ) - -BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait, - uint32_t ulBitsToClearOnEntry, - uint32_t ulBitsToClearOnExit, - uint32_t * pulNotificationValue, - TickType_t xTicksToWait ) -{ - BaseType_t xReturn; - - configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES ); - - taskENTER_CRITICAL(); - { - /* Only block if a notification is not already pending. */ - if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != - 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[ uxIndexToWait ] &= ~ulBitsToClearOnEntry; - - /* Mark this task as waiting for a notification. */ - pxCurrentTCB - ->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; - - if( xTicksToWait > ( TickType_t ) 0 ) - { - prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); - traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait ); - - /* 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. */ - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL(); - - taskENTER_CRITICAL(); - { - traceTASK_NOTIFY_WAIT( uxIndexToWait ); - - if( pulNotificationValue != NULL ) - { - /* Output the current notification value, which may or may not - * have changed. */ - *pulNotificationValue = pxCurrentTCB - ->ulNotifiedValue[ uxIndexToWait ]; - } - - /* 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[ uxIndexToWait ] != - 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[ uxIndexToWait ] &= ~ulBitsToClearOnExit; - xReturn = pdTRUE; - } - - pxCurrentTCB - ->ucNotifyState[ uxIndexToWait ] = 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( 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 - { - 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 = portSET_INTERRUPT_MASK_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( 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. */ - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - portCLEAR_INTERRUPT_MASK_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 = portSET_INTERRUPT_MASK_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( 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. */ - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - portCLEAR_INTERRUPT_MASK_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 ) - -configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ) -{ - return ulTaskGetRunTimeCounter( xIdleTaskHandle ); -} - -#endif -/*-----------------------------------------------------------*/ - -#if( configGENERATE_RUN_TIME_STATS == 1 ) - -configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ) -{ - return ulTaskGetRunTimePercent( xIdleTaskHandle ); -} - -#endif -/*-----------------------------------------------------------*/ - -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 ) */ diff --git a/formatting/filesWithFormattingErrors/goodFileInHere.c b/formatting/filesWithFormattingErrors/goodFileInHere.c deleted file mode 100644 index 3a642c3e..00000000 --- a/formatting/filesWithFormattingErrors/goodFileInHere.c +++ /dev/null @@ -1,6151 +0,0 @@ -/* - * FreeRTOS Kernel - * 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 -#include - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining - * all the API functions to use the MPU wrappers. That should only be done when - * task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -/* FreeRTOS includes. */ -#include "FreeRTOS.h" -#include "stack_macros.h" -#include "task.h" -#include "timers.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 -#endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 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 - -/* 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 */ - -/*-----------------------------------------------------------*/ - - #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 */ - -/*-----------------------------------------------------------*/ - -/* 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 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 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 - - 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. */ - 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( ( 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. */ -portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL; - -/* 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 xYieldPending = 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 - xIdleTaskHandle = NULL; /**< Holds the handle of the idle task. The idle - task is 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. */ -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 = 0UL; /**< Holds the value of a timer/counter the last - time a task was switched in. */ -PRIVILEGED_DATA static volatile configRUN_TIME_COUNTER_TYPE - ulTotalRunTime = 0UL; /**< Holds the total amount of execution time as - defined by the run time counter clock. */ - -#endif - -/*lint -restore */ - -/*-----------------------------------------------------------*/ - -/* File private functions. --------------------------------*/ - -/** - * 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. - * - * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific - * language extensions. The equivalent prototype for this function is: - * - * void prvIdleTask( void *pvParameters ); - * - */ -static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ) PRIVILEGED_FUNCTION; - -/* - * 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( 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 ) -{ - 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. */ - 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 ); - 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 ) -{ - 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; - 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 ); - - 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 ) -{ - TCB_t * pxNewTCB; - BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; - - configASSERT( pxTaskDefinition->puxStackBuffer ); - - if( pxTaskDefinition->puxStackBuffer != 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 * ) pvPortMalloc( sizeof( TCB_t ) ); - - if( pxNewTCB != NULL ) - { - 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 ); - - 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 ) -{ - 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 ) - { - 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 ) - { - 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 ); - 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 - -/* 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 */ - - 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(); - } -} -/*-----------------------------------------------------------*/ - -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(); - } -} -/*-----------------------------------------------------------*/ - -#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( pxTCB == pxCurrentTCB ) - { - /* A task is deleting itself. 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. */ - portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending ); - } - else - { - --uxCurrentNumberOfTasks; - traceTASK_DELETE( pxTCB ); - - /* Reset the next expected unblock time in case it referred to - * the task that has just been deleted. */ - prvResetNextTaskUnblockTime(); - } - } - 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 == ( UBaseType_t ) 0U ); - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } -} - -#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 ) ); - configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U ); - - vTaskSuspendAll(); - { - /* Minor optimisation. The tick count cannot change in this - * block. */ - const TickType_t xConstTickCount = xTickCount; - - /* 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 ) - { - portYIELD_WITHIN_API(); - } - 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 ) - { - configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U ); - vTaskSuspendAll(); - { - 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 ) - { - portYIELD_WITHIN_API(); - } - 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( pxTCB == pxCurrentTCB ) - { - /* The task calling this function is querying its own state. */ - eReturn = eRunning; - } - else - { - 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 = 0; x < 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 the task is not in any other state, it must be in the - * Ready (including pending ready) state. */ - eReturn = eReady; - } - } - - 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 uxSavedInterruptState; - - /* 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(); - - uxSavedInterruptState = portSET_INTERRUPT_MASK_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; - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState ); - - 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; - - 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 the calling task. */ - if( uxNewPriority > uxCurrentBasePriority ) - { - 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( pxTCB == pxCurrentTCB ) - { - /* Setting the priority of the running task down means - * there may now be another task of higher priority that - * is ready to execute. */ - 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 - { - mtCOVERAGE_TEST_MARKER(); - } - - if( xYieldRequired != pdFALSE ) - { - taskYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - /* Remove compiler warning about unused variables when the port - * optimised task selection is not being used. */ - ( void ) uxPriorityUsedOnEntry; - } - } - taskEXIT_CRITICAL(); -} - -#endif /* INCLUDE_vTaskPrioritySet */ -/*-----------------------------------------------------------*/ - -#if( INCLUDE_vTaskSuspend == 1 ) - -void vTaskSuspend( TaskHandle_t xTaskToSuspend ) -{ - TCB_t * pxTCB; - - taskENTER_CRITICAL(); - { - /* If null is passed in here then it is the running task that is - * being suspended. */ - pxTCB = prvGetTCBFromHandle( xTaskToSuspend ); - - traceTASK_SUSPEND( pxTCB ); - - /* 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 = 0; x < 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 ) */ - } - 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 == ( UBaseType_t ) 0U ); - 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(); - } -} - -#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 ); - - /* The parameter cannot be NULL as it is impossible to resume the - * currently executing task. */ - if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) ) - { - 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 ); - - /* 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 - { - 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 = portSET_INTERRUPT_MASK_FROM_ISR(); - { - if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) - { - traceTASK_RESUME_FROM_ISR( pxTCB ); - - /* Check the ready lists can be accessed. */ - if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) - { - /* 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. */ - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - ( 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 ) ); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - - return xYieldRequired; -} - -#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 \ - ) ) */ -/*-----------------------------------------------------------*/ - -void vTaskStartScheduler( void ) -{ - BaseType_t xReturn; - -/* 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 ); - xIdleTaskHandle = 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( xIdleTaskHandle != 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. - */ - &xIdleTaskHandle ); /*lint !e961 MISRA exception, - justified as it is not a - redundant explicit cast to - all supported compilers. - */ - } -#endif /* configSUPPORT_STATIC_ALLOCATION */ - -#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 xIdleTaskHandle is not used anywhere else. */ - ( void ) xIdleTaskHandle; - - /* 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 ) -{ - /* 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(); -} -/*----------------------------------------------------------*/ - -#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 uxSchedulerSuspended is zero then this function does not match a - * previous call to vTaskSuspendAll(). */ - configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U ); - - /* 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(); - { - --uxSchedulerSuspended; - - 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 and co-routines 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 the moved task has a priority higher than the current - * task then a yield must be performed. */ - if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) - { - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - - 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. */ - { - TickType_t xPendedCounts = xPendedTicks; /* Non-volatile - copy. */ - - if( xPendedCounts > ( TickType_t ) 0U ) - { - do - { - if( xTaskIncrementTick() != pdFALSE ) - { - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - --xPendedCounts; - } while( xPendedCounts > ( TickType_t ) 0U ); - - xPendedTicks = 0; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - - if( xYieldPending != pdFALSE ) - { -#if( configUSE_PREEMPTION != 0 ) - { - xAlreadyYielded = pdTRUE; - } -#endif - taskYIELD_IF_USING_PREEMPTION(); - } - 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 ) - -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 - and co-routines 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 and co-routines - 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; -} - -#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 ) - -TaskHandle_t xTaskGetIdleTaskHandle( void ) -{ - /* If xTaskGetIdleTaskHandle() is called before the scheduler has been - * started, then xIdleTaskHandle will be NULL. */ - configASSERT( ( xIdleTaskHandle != NULL ) ); - return xIdleTaskHandle; -} - -#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 ) - { - /* 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. */ - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_PREEMPTION */ - } - else - { - xReturn = pdFAIL; - } - } - ( void ) xTaskResumeAll(); - - return xReturn; -} - -#endif /* INCLUDE_xTaskAbortDelay */ -/*----------------------------------------------------------*/ - -BaseType_t xTaskIncrementTick( void ) -{ - TCB_t * pxTCB; - TickType_t xItemValue; - BaseType_t xSwitchRequired = pdFALSE; - - /* 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 ); - - 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 ) - { - /* 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(); - } - } -#endif /* configUSE_PREEMPTION */ - } - } - } - -/* 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( listCURRENT_LIST_LENGTH( - &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > - ( UBaseType_t ) 1 ) - { - xSwitchRequired = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } -#endif /* ( ( 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( xYieldPending != pdFALSE ) - { - xSwitchRequired = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } -#endif /* configUSE_PREEMPTION */ - } - 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 = portSET_INTERRUPT_MASK_FROM_ISR(); - { - xReturn = pxTCB->pxTaskTag; - } - portCLEAR_INTERRUPT_MASK_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 */ -/*-----------------------------------------------------------*/ - -void vTaskSwitchContext( void ) -{ - if( uxSchedulerSuspended != ( UBaseType_t ) 0U ) - { - /* The scheduler is currently suspended - do not allow a context - * switch. */ - xYieldPending = pdTRUE; - } - else - { - xYieldPending = pdFALSE; - traceTASK_SWITCHED_OUT(); - -#if( configGENERATE_RUN_TIME_STATS == 1 ) - { - #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE - portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); - #else - ulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) - 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 > ulTaskSwitchedInTime ) - { - pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - - ulTaskSwitchedInTime ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - ulTaskSwitchedInTime = ulTotalRunTime; - } -#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 and - co-routines 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 - } -} -/*-----------------------------------------------------------*/ - -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( 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. */ - xYieldPending = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - - 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( 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). */ - xYieldPending = pdTRUE; - } -} -/*-----------------------------------------------------------*/ - -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 ) -{ - xYieldPending = 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 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 ); - - for( ;; ) - { - /* 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 more than one - * task then a task other than the idle task is ready to execute. */ - if( listCURRENT_LIST_LENGTH( - &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > - ( UBaseType_t ) 1 ) - { - 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( 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( xYieldPending != 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 < 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 < 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 xRegions ) -{ - 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 ), xRegions, 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 ) - { - taskENTER_CRITICAL(); - { - pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( - &xTasksWaitingTermination ) ); /*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. */ - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); - --uxCurrentNumberOfTasks; - --uxDeletedTasksWaitingCleanUp; - } - taskEXIT_CRITICAL(); - - prvDeleteTCB( pxTCB ); - } - } -#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_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( pxTCB == pxCurrentTCB ) - { - 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( pxCurrentTCB->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 ) ) - -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; -} - -#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( uxSchedulerSuspended == ( UBaseType_t ) 0U ) - { - xReturn = taskSCHEDULER_RUNNING; - } - else - { - xReturn = taskSCHEDULER_SUSPENDED; - } - } - - 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 ); - } - 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 ); - - /* 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 ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } -} - -#endif /* configUSE_MUTEXES */ -/*-----------------------------------------------------------*/ - -#if( portCRITICAL_NESTING_IN_TCB == 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 /* portCRITICAL_NESTING_IN_TCB */ -/*-----------------------------------------------------------*/ - -#if( portCRITICAL_NESTING_IN_TCB == 1 ) - -void vTaskExitCritical( void ) -{ - if( xSchedulerRunning != pdFALSE ) - { - 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 /* portCRITICAL_NESTING_IN_TCB */ -/*-----------------------------------------------------------*/ - -#if( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) - -static char * prvWriteNameToBuffer( char * pcBuffer, const char * pcTaskName ) -{ - size_t x; - - /* Start by copying the entire string. */ - 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 ) ( configMAX_TASK_NAME_LEN - 1 ); - 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 ) -{ - /* If xSemaphoreCreateMutex() is called before any tasks have been created - * then pxCurrentTCB will be NULL. */ - if( pxCurrentTCB != NULL ) - { - ( pxCurrentTCB->uxMutexesHeld )++; - } - - return pxCurrentTCB; -} - -#endif /* configUSE_MUTEXES */ -/*-----------------------------------------------------------*/ - -#if( configUSE_TASK_NOTIFICATIONS == 1 ) - -uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait, - BaseType_t xClearCountOnExit, - TickType_t xTicksToWait ) -{ - uint32_t ulReturn; - - configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES ); - - taskENTER_CRITICAL(); - { - /* Only block if the notification count is not already non-zero. */ - if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL ) - { - /* Mark this task as waiting for a notification. */ - pxCurrentTCB - ->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; - - if( xTicksToWait > ( TickType_t ) 0 ) - { - prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); - traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait ); - - /* 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. */ - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL(); - - taskENTER_CRITICAL(); - { - traceTASK_NOTIFY_TAKE( uxIndexToWait ); - ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ]; - - if( ulReturn != 0UL ) - { - if( xClearCountOnExit != pdFALSE ) - { - pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = 0UL; - } - else - { - pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = ulReturn - - ( uint32_t ) 1; - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - pxCurrentTCB - ->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION; - } - taskEXIT_CRITICAL(); - - return ulReturn; -} - -#endif /* configUSE_TASK_NOTIFICATIONS */ -/*-----------------------------------------------------------*/ - -#if( configUSE_TASK_NOTIFICATIONS == 1 ) - -BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait, - uint32_t ulBitsToClearOnEntry, - uint32_t ulBitsToClearOnExit, - uint32_t * pulNotificationValue, - TickType_t xTicksToWait ) -{ - BaseType_t xReturn; - - configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES ); - - taskENTER_CRITICAL(); - { - /* Only block if a notification is not already pending. */ - if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != - 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[ uxIndexToWait ] &= ~ulBitsToClearOnEntry; - - /* Mark this task as waiting for a notification. */ - pxCurrentTCB - ->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; - - if( xTicksToWait > ( TickType_t ) 0 ) - { - prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); - traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait ); - - /* 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. */ - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL(); - - taskENTER_CRITICAL(); - { - traceTASK_NOTIFY_WAIT( uxIndexToWait ); - - if( pulNotificationValue != NULL ) - { - /* Output the current notification value, which may or may not - * have changed. */ - *pulNotificationValue = pxCurrentTCB - ->ulNotifiedValue[ uxIndexToWait ]; - } - - /* 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[ uxIndexToWait ] != - 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[ uxIndexToWait ] &= ~ulBitsToClearOnExit; - xReturn = pdTRUE; - } - - pxCurrentTCB - ->ucNotifyState[ uxIndexToWait ] = 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( 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 - { - 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 = portSET_INTERRUPT_MASK_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( 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. */ - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - portCLEAR_INTERRUPT_MASK_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 = portSET_INTERRUPT_MASK_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( 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. */ - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - portCLEAR_INTERRUPT_MASK_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 ) - -configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ) -{ - return ulTaskGetRunTimeCounter( xIdleTaskHandle ); -} - -#endif -/*-----------------------------------------------------------*/ - -#if( configGENERATE_RUN_TIME_STATS == 1 ) - -configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ) -{ - return ulTaskGetRunTimePercent( xIdleTaskHandle ); -} - -#endif -/*-----------------------------------------------------------*/ - -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 ) */ diff --git a/formatting/getFiles b/formatting/getFiles deleted file mode 100755 index 8b4ff300..00000000 --- a/formatting/getFiles +++ /dev/null @@ -1,118 +0,0 @@ -#!/bin/bash -bashPass="\033[32;1mPASSED -" -bashInfo="\033[33;1mINFO -" -bashFail="\033[31;1mFAILED -" -bashEnd="\033[0m" - -# Check number of arguments -files="" -file="" -excludeDirs="" -excludeFiles="" -includeExtensions="" - -# Make the assumption that Mac users will be using FreeBSD Get Opt -if [[ "$OSTYPE" == "darwin"* ]]; then - while [ $# -gt 0 ]; do - case "$1" in - -ed= | --exclude-dirs=* ) - excludeDirs="-E $(echo "${1#*=}" | sed -E 's/,/ -E /g')" - shift - ;; - -ef= | --exclude-files=* ) - excludeFiles="-E $(echo "${1#*=}" | sed -E 's/,/ -E /g')" - shift - ;; - -ie= | --include-extensions=* ) - includeExtensions="-e $(echo "${1#*=}" | sed -E 's/,/ -e /g')" - shift - ;; - -h | --help ) - echo -e "$bashInfo Find all .c and .h files with the Amazon copyright in them $bashEnd" - echo -e "$bashInfo It exports this to a bash array variable called \"files\" $bashEnd" - echo -e "$bashInfo This script can take in two optional arguments $bashEnd" - echo -e "$bashInfo -ef= | --exclude-files=: A comma seperated list of files to exclude $bashEnd" - echo -e "$bashInfo -ed= | --exclude-dir=: A comma seperated list of directories to exclude $bashEnd" - echo -e "$bashInfo -ie= | --include-extensions=: Any additional exstensions to search for $bashEnd" - exit 0 - ;; - *) - echo "Unknown option: $1" - exit 1 - ;; - esac - done - # For FreeBSD's version of Getopt, which is the default MacOS version, use fd - # By default only grab the c and h files. Only grab the files with amazon copyright - # Need this in a set +/- e so it doesn't exit due to an error on files that fail the grep - set +e - files=$(fd -e c -e h $excludeDirs $excludeFiles $includeExtensions --exec grep -lie "copyright (.*) 20\d\d amazon.com") - set -e - -# Making the assumption that anybody else running this is a gnu getopt user -else - VALID_ARGS=$(getopt -o h,ed:,ef:,if: --long help,exclude-dirs:,exclude-files:,include-extensions: -- "$@") - eval set -- "$VALID_ARGS" - while [ $# -gt 0 ]; do - case "$1" in - ed | --exclude-dirs ) - # $2 Holds the argument passed after --exclude-files or --ed - # Use sed to replace the commas with the exclude flag - if ! [ -z "$2" ]; then - excludeDirs="-E $(echo "$2" | sed -r 's/,/ -E /g' )" - fi - shift 2 - ;; - - ef | --exclude-files ) - # $2 Holds the argument passed after --exclude-files or --ed - # Use sed to replace the commas with the exclude flag - if ! [ -z "$2" ]; then - excludeFiles="-E $( echo "$2" | sed -r 's/,/ -E /g' )" - fi - shift 2 - ;; - - if | --include-extensions ) - # $2 Holds the argument passed after --exclude-files or --ed - # Use sed to replace the commas with the exclude flag - if ! [ -z "$2" ]; then - includeExtensions="-e $( echo "$2" | sed -r 's/,/ -E /g' )" - fi - shift 2 - ;; - - h | --help ) - echo -e "$bashInfo Find all .c and .h files with the Amazon copyright in them $bashEnd" - echo -e "$bashInfo It exports this to a bash array variable called \"files\" $bashEnd" - echo -e "$bashInfo This script can take in two optional arguments $bashEnd" - echo -e "$bashInfo --exclude-files: A comma seperated list of files to exclude $bashEnd" - echo -e "$bashInfo --exclude-dir: A comma seperated list of directories to exclude $bashEnd" - echo -e "$bashInfo --include-extensions: Any additional exstensions to search for $bashEnd" - exit 0 - ;; - -- ) - shift - break - ;; - esac - done - # Make the assumption that gnu getopt means you're going to use fdfind vs fd - # By default only grab the c and h files. Only grab the files with amazon copyright - # Need this in a set +/- e so it doesn't exit due to an error on files that fail the grep - set +e - files=$(fdfind -e c -e h $excludeDirs $excludeFiles $includeExtensions --exec grep -liE "copyright (.*) 20[0-9]{2} amazon.com" ) - set -e -fi - -# For future FreeBSD users: -# By default if you try and capture this output like you see on the github workflows -# By doing something like files=$(getFiles ) it will look like it doesn't work -# This is because on a Mac's default shell this will expand to a single variable -# But on ubuntu's default shell it will expand to an array that can be iterated over -# My recommendation would be to use the raw fd command above. -for file in ${files[@]}; do - if ! [ -z "$file" ]; then - echo "$file" - fi -done diff --git a/formatting/goodFiles/include/fileWithErrorInclude/errorFileInDirectory.h b/formatting/goodFiles/include/fileWithErrorInclude/errorFileInDirectory.h deleted file mode 100644 index 3c540dc7..00000000 --- a/formatting/goodFiles/include/fileWithErrorInclude/errorFileInDirectory.h +++ /dev/null @@ -1,3761 +0,0 @@ -/* - * FreeRTOS Kernel - * 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 - * - */ - -#ifndef INC_TASK_H -#define INC_TASK_H - -#ifndef INC_FREERTOS_H - #error \ - "include FreeRTOS.h must appear in source files before include task.h" -#endif - -#include "list.h" - -/* *INDENT-OFF* */ -#ifdef __cplusplus -extern "C" { -#endif -/* *INDENT-ON* */ - -/*----------------------------------------------------------- - * MACROS AND DEFINITIONS - *----------------------------------------------------------*/ - -/* - * If tskKERNEL_VERSION_NUMBER ends with + it represents the version in - * development after the numbered release. - * - * The tskKERNEL_VERSION_MAJOR, tskKERNEL_VERSION_MINOR, tskKERNEL_VERSION_BUILD - * values will reflect the last released version number. - */ -#define tskKERNEL_VERSION_NUMBER "V10.4.4+" -#define tskKERNEL_VERSION_MAJOR 10 -#define tskKERNEL_VERSION_MINOR 4 -#define tskKERNEL_VERSION_BUILD 4 - -/* MPU region parameters passed in ulParameters - * of MemoryRegion_t struct. */ -#define tskMPU_REGION_READ_ONLY ( 1UL << 0UL ) -#define tskMPU_REGION_READ_WRITE ( 1UL << 1UL ) -#define tskMPU_REGION_EXECUTE_NEVER ( 1UL << 2UL ) -#define tskMPU_REGION_NORMAL_MEMORY ( 1UL << 3UL ) -#define tskMPU_REGION_DEVICE_MEMORY ( 1UL << 4UL ) - -/* MPU region permissions stored in MPU settings to - * authorize access requests. */ -#define tskMPU_READ_PERMISSION ( 1UL << 0UL ) -#define tskMPU_WRITE_PERMISSION ( 1UL << 1UL ) - -/* The direct to task notification feature used to have only a single - * notification per task. Now there is an array of notifications per task that - * is dimensioned by configTASK_NOTIFICATION_ARRAY_ENTRIES. For backward - * compatibility, any use of the original direct to task notification defaults - * to using the first index in the array. */ -#define tskDEFAULT_INDEX_TO_NOTIFY ( 0 ) - -/** - * task. h - * - * Type by which tasks are referenced. For example, a call to xTaskCreate - * returns (via a pointer parameter) an TaskHandle_t variable that can then - * be used as a parameter to vTaskDelete to delete the task. - * - * \defgroup TaskHandle_t TaskHandle_t - * \ingroup Tasks - */ -struct tskTaskControlBlock; /* The old naming convention is used to prevent - breaking kernel aware debuggers. */ -typedef struct tskTaskControlBlock * TaskHandle_t; -typedef const struct tskTaskControlBlock * ConstTaskHandle_t; - -/* - * Defines the prototype to which the application task hook function must - * conform. - */ -typedef BaseType_t ( *TaskHookFunction_t )( void * ); - -/* Task states returned by eTaskGetState. */ -typedef enum -{ - eRunning = 0, /* A task is querying the state of itself, so must be running. - */ - eReady, /* The task being queried is in a ready or pending ready list. */ - eBlocked, /* The task being queried is in the Blocked state. */ - eSuspended, /* The task being queried is in the Suspended state, or is in - the Blocked state with an infinite time out. */ - eDeleted, /* The task being queried has been deleted, but its TCB has not - yet been freed. */ - eInvalid /* Used as an 'invalid state' value. */ -} eTaskState; - -/* Actions that can be performed when vTaskNotify() is called. */ -typedef enum -{ - eNoAction = 0, /* Notify the task without updating its notify value. */ - eSetBits, /* Set bits in the task's notification value. */ - eIncrement, /* Increment the task's notification value. */ - eSetValueWithOverwrite, /* Set the task's notification value to a specific - value even if the previous value has not yet been - read by the task. */ - eSetValueWithoutOverwrite /* Set the task's notification value if the - previous value has been read by the task. */ -} eNotifyAction; - -/* - * Used internally only. - */ -typedef struct xTIME_OUT -{ - BaseType_t xOverflowCount; - TickType_t xTimeOnEntering; -} TimeOut_t; - -/* - * Defines the memory ranges allocated to the task when an MPU is used. - */ -typedef struct xMEMORY_REGION -{ - void * pvBaseAddress; - uint32_t ulLengthInBytes; - uint32_t ulParameters; -} MemoryRegion_t; - -/* - * Parameters required to create an MPU protected task. - */ -typedef struct xTASK_PARAMETERS -{ - TaskFunction_t pvTaskCode; - const char * pcName; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - configSTACK_DEPTH_TYPE usStackDepth; - void * pvParameters; - UBaseType_t uxPriority; - StackType_t * puxStackBuffer; - MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ]; -#if( ( portUSING_MPU_WRAPPERS == 1 ) && \ - ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - StaticTask_t * const pxTaskBuffer; -#endif -} TaskParameters_t; - -/* Used with the uxTaskGetSystemState() function to return the state of each - * task in the system. */ -typedef struct xTASK_STATUS -{ - TaskHandle_t xHandle; /* The handle of the task to which the rest of the - information in the structure relates. */ - const char * pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - UBaseType_t xTaskNumber; /* A number unique to the task. */ - eTaskState eCurrentState; /* The state in which the task existed when the - structure was populated. */ - UBaseType_t uxCurrentPriority; /* The priority at which the task was running - (may be inherited) when the structure was - populated. */ - UBaseType_t uxBasePriority; /* The priority to which the task will return if - the task's current priority has been - inherited to avoid unbounded priority - inversion when obtaining a mutex. Only valid - if configUSE_MUTEXES is defined as 1 in - FreeRTOSConfig.h. */ - configRUN_TIME_COUNTER_TYPE - ulRunTimeCounter; /* The total run time - allocated to the task so - far, as defined by the run - time stats clock. See - https://www.FreeRTOS.org/rtos-run-time-stats.html. - Only valid when - configGENERATE_RUN_TIME_STATS - is defined as 1 in - FreeRTOSConfig.h. */ - StackType_t * pxStackBase; /* Points to the lowest address of the task's - stack area. */ -#if( ( portSTACK_GROWTH > 0 ) && ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) - StackType_t * pxTopOfStack; /* Points to the top address of the task's stack - area. */ - StackType_t * pxEndOfStack; /* Points to the end address of the task's stack - area. */ -#endif - configSTACK_DEPTH_TYPE usStackHighWaterMark; /* The minimum amount of stack - space that has remained for - the task since the task was - created. The closer this - value is to zero the closer - the task has come to - overflowing its stack. */ -#if( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - UBaseType_t uxCoreAffinityMask; /* The core affinity mask for the task */ -#endif -} TaskStatus_t; - -/* Possible return values for eTaskConfirmSleepModeStatus(). */ -typedef enum -{ - eAbortSleep = 0, /* A task has been made ready or a context switch pended - since portSUPPRESS_TICKS_AND_SLEEP() was called - abort - entering a sleep mode. */ - eStandardSleep, /* Enter a sleep mode that will not last any longer than the - expected idle time. */ -#if( INCLUDE_vTaskSuspend == 1 ) - eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe - to enter a sleep mode that can only be exited by - an external interrupt. */ -#endif /* INCLUDE_vTaskSuspend */ -} eSleepModeStatus; - -/** - * Defines the priority used by the idle task. This must not be modified. - * - * \ingroup TaskUtils - */ -#define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U ) - -/** - * Defines affinity to all available cores. - * - * \ingroup TaskUtils - */ -#define tskNO_AFFINITY ( ( UBaseType_t ) -1 ) - -/** - * task. h - * - * Macro for forcing a context switch. - * - * \defgroup taskYIELD taskYIELD - * \ingroup SchedulerControl - */ -#define taskYIELD() portYIELD() - -/** - * task. h - * - * Macro to mark the start of a critical code region. Preemptive context - * switches cannot occur when in a critical region. - * - * NOTE: This may alter the stack (depending on the portable implementation) - * so must be used with care! - * - * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL - * \ingroup SchedulerControl - */ -#define taskENTER_CRITICAL() portENTER_CRITICAL() -#if( configNUMBER_OF_CORES == 1 ) - #define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() -#else - #define taskENTER_CRITICAL_FROM_ISR() portENTER_CRITICAL_FROM_ISR() -#endif - -/** - * task. h - * - * Macro to mark the end of a critical code region. Preemptive context - * switches cannot occur when in a critical region. - * - * NOTE: This may alter the stack (depending on the portable implementation) - * so must be used with care! - * - * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL - * \ingroup SchedulerControl - */ -#define taskEXIT_CRITICAL() portEXIT_CRITICAL() -#if( configNUMBER_OF_CORES == 1 ) - #define taskEXIT_CRITICAL_FROM_ISR( x ) \ - portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) -#else - #define taskEXIT_CRITICAL_FROM_ISR( x ) portEXIT_CRITICAL_FROM_ISR( x ) -#endif - -/** - * task. h - * - * Macro to disable all maskable interrupts. - * - * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS - * \ingroup SchedulerControl - */ -#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() - -/** - * task. h - * - * Macro to enable microcontroller interrupts. - * - * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS - * \ingroup SchedulerControl - */ -#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() - -/* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is - * 0 to generate more optimal code when configASSERT() is defined as the - * constant is used in assert() statements. */ -#define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 ) -#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 ) -#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 ) - -/* Checks if core ID is valid. */ -#define taskVALID_CORE_ID( xCoreID ) \ - ( ( ( ( ( BaseType_t ) 0 <= ( xCoreID ) ) && \ - ( ( xCoreID ) < ( BaseType_t ) configNUMBER_OF_CORES ) ) ) \ - ? ( pdTRUE ) \ - : ( pdFALSE ) ) - -/*----------------------------------------------------------- - * TASK CREATION API - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * BaseType_t xTaskCreate( - * TaskFunction_t pxTaskCode, - * const char *pcName, - * configSTACK_DEPTH_TYPE usStackDepth, - * void *pvParameters, - * UBaseType_t uxPriority, - * TaskHandle_t *pxCreatedTask - * ); - * @endcode - * - * Create a new task and add it to the list of tasks that are ready to run. - * - * Internally, within the FreeRTOS implementation, tasks use two blocks of - * memory. The first block is used to hold the task's data structures. The - * second block is used by the task as its stack. If a task is created using - * xTaskCreate() then both blocks of memory are automatically dynamically - * allocated inside the xTaskCreate() function. (see - * https://www.FreeRTOS.org/a00111.html). If a task is created using - * xTaskCreateStatic() then the application writer must provide the required - * memory. xTaskCreateStatic() therefore allows a task to be created without - * using any dynamic memory allocation. - * - * See xTaskCreateStatic() for a version that does not use any dynamic memory - * allocation. - * - * xTaskCreate() can only be used to create a task that has unrestricted - * access to the entire microcontroller memory map. Systems that include MPU - * support can alternatively create an MPU constrained task using - * xTaskCreateRestricted(). - * - * @param pxTaskCode Pointer to the task entry function. Tasks - * must be implemented to never return (i.e. continuous loop). - * - * @param pcName A descriptive name for the task. This is mainly used to - * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - - * default is 16. - * - * @param usStackDepth The size of the task stack specified as the number of - * variables the stack can hold - not the number of bytes. For example, if - * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes - * will be allocated for stack storage. - * - * @param pvParameters Pointer that will be used as the parameter for the task - * being created. - * - * @param uxPriority The priority at which the task should run. Systems that - * include MPU support can optionally create tasks in a privileged (system) - * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For - * example, to create a privileged task at priority 2 the uxPriority parameter - * should be set to ( 2 | portPRIVILEGE_BIT ). - * - * @param pxCreatedTask Used to pass back a handle by which the created task - * can be referenced. - * - * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file projdefs.h - * - * Example usage: - * @code{c} - * // Task to be created. - * void vTaskCode( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * } - * } - * - * // Function that creates a task. - * void vOtherFunction( void ) - * { - * static uint8_t ucParameterToPass; - * TaskHandle_t xHandle = NULL; - * - * // Create the task, storing the handle. Note that the passed parameter - * ucParameterToPass - * // must exist for the lifetime of the task, so in this case is declared - * static. If it was just an - * // an automatic stack variable it might no longer exist, or at least have - * been corrupted, by the time - * // the new task attempts to access it. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, - * tskIDLE_PRIORITY, &xHandle ); configASSERT( xHandle ); - * - * // Use the handle to delete the task. - * if( xHandle != NULL ) - * { - * vTaskDelete( xHandle ); - * } - * } - * @endcode - * \defgroup xTaskCreate xTaskCreate - * \ingroup Tasks - */ -#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 ) PRIVILEGED_FUNCTION; -#endif - -#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && \ - ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) -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 ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, - * const char *pcName, - * uint32_t ulStackDepth, - * void *pvParameters, - * UBaseType_t uxPriority, - * StackType_t *puxStackBuffer, - * StaticTask_t *pxTaskBuffer ); - * @endcode - * - * Create a new task and add it to the list of tasks that are ready to run. - * - * Internally, within the FreeRTOS implementation, tasks use two blocks of - * memory. The first block is used to hold the task's data structures. The - * second block is used by the task as its stack. If a task is created using - * xTaskCreate() then both blocks of memory are automatically dynamically - * allocated inside the xTaskCreate() function. (see - * https://www.FreeRTOS.org/a00111.html). If a task is created using - * xTaskCreateStatic() then the application writer must provide the required - * memory. xTaskCreateStatic() therefore allows a task to be created without - * using any dynamic memory allocation. - * - * @param pxTaskCode Pointer to the task entry function. Tasks - * must be implemented to never return (i.e. continuous loop). - * - * @param pcName A descriptive name for the task. This is mainly used to - * facilitate debugging. The maximum length of the string is defined by - * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h. - * - * @param ulStackDepth The size of the task stack specified as the number of - * variables the stack can hold - not the number of bytes. For example, if - * the stack is 32-bits wide and ulStackDepth is defined as 100 then 400 bytes - * will be allocated for stack storage. - * - * @param pvParameters Pointer that will be used as the parameter for the task - * being created. - * - * @param uxPriority The priority at which the task will run. - * - * @param puxStackBuffer Must point to a StackType_t array that has at least - * ulStackDepth indexes - the array will then be used as the task's stack, - * removing the need for the stack to be allocated dynamically. - * - * @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will - * then be used to hold the task's data structures, removing the need for the - * memory to be allocated dynamically. - * - * @return If neither puxStackBuffer nor pxTaskBuffer are NULL, then the task - * will be created and a handle to the created task is returned. If either - * puxStackBuffer or pxTaskBuffer are NULL then the task will not be created and - * NULL is returned. - * - * Example usage: - * @code{c} - * - * // Dimensions of the buffer that the task being created will use as its - stack. - * // NOTE: This is the number of words the stack will hold, not the number of - * // bytes. For example, if each stack item is 32-bits, and this is set to - 100, - * // then 400 bytes (100 * 32-bits) will be allocated. - #define STACK_SIZE 200 - * - * // Structure that will hold the TCB of the task being created. - * StaticTask_t xTaskBuffer; - * - * // Buffer that the task being created will use as its stack. Note this is - * // an array of StackType_t variables. The size of StackType_t is dependent - on - * // the RTOS port. - * StackType_t xStack[ STACK_SIZE ]; - * - * // Function that implements the task being created. - * void vTaskCode( void * pvParameters ) - * { - * // The parameter value is expected to be 1 as 1 is passed in the - * // pvParameters value in the call to xTaskCreateStatic(). - * configASSERT( ( uint32_t ) pvParameters == 1UL ); - * - * for( ;; ) - * { - * // Task code goes here. - * } - * } - * - * // Function that creates a task. - * void vOtherFunction( void ) - * { - * TaskHandle_t xHandle = NULL; - * - * // Create the task without using any dynamic memory allocation. - * xHandle = xTaskCreateStatic( - * vTaskCode, // Function that implements the task. - * "NAME", // Text name for the task. - * STACK_SIZE, // Stack size in words, not bytes. - * ( void * ) 1, // Parameter passed into the task. - * tskIDLE_PRIORITY,// Priority at which the task is created. - * xStack, // Array to use as the task's stack. - * &xTaskBuffer ); // Variable to hold the task's data - structure. - * - * // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have - * // been created, and xHandle will be the task's handle. Use the handle - * // to suspend the task. - * vTaskSuspend( xHandle ); - * } - * @endcode - * \defgroup xTaskCreateStatic xTaskCreateStatic - * \ingroup Tasks - */ -#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 ) PRIVILEGED_FUNCTION; -#endif /* configSUPPORT_STATIC_ALLOCATION */ - -#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && \ - ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) -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 ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, - * TaskHandle_t *pxCreatedTask ); - * @endcode - * - * Only available when configSUPPORT_DYNAMIC_ALLOCATION is set to 1. - * - * xTaskCreateRestricted() should only be used in systems that include an MPU - * implementation. - * - * Create a new task and add it to the list of tasks that are ready to run. - * The function parameters define the memory regions and associated access - * permissions allocated to the task. - * - * See xTaskCreateRestrictedStatic() for a version that does not use any - * dynamic memory allocation. - * - * @param pxTaskDefinition Pointer to a structure that contains a member - * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API - * documentation) plus an optional stack buffer and the memory region - * definitions. - * - * @param pxCreatedTask Used to pass back a handle by which the created task - * can be referenced. - * - * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file projdefs.h - * - * Example usage: - * @code{c} - * // Create an TaskParameters_t structure that defines the task to be created. - * static const TaskParameters_t xCheckTaskParameters = - * { - * vATask, // pvTaskCode - the function that implements the task. - * "ATask", // pcName - just a text name for the task to assist debugging. - * 100, // usStackDepth - the stack size DEFINED IN WORDS. - * NULL, // pvParameters - passed into the task function as the function - * parameters. ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set - * the portPRIVILEGE_BIT if the task should run in a privileged state. - * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack. - * - * // xRegions - Allocate up to three separate memory regions for access by - * // the task, with appropriate access permissions. Different processors have - * // different memory alignment requirements - refer to the FreeRTOS - * documentation - * // for full information. - * { - * // Base address Length Parameters - * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE }, - * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY }, - * { cPrivilegedOnlyAccessArray, 128, - * portMPU_REGION_PRIVILEGED_READ_WRITE } - * } - * }; - * - * int main( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task from the const structure defined above. The task handle - * // is requested (the second parameter is not NULL) but in this case just for - * // demonstration purposes as its not actually used. - * xTaskCreateRestricted( &xRegTest1Parameters, &xHandle ); - * - * // Start the scheduler. - * vTaskStartScheduler(); - * - * // Will only get here if there was insufficient memory to create the idle - * // and/or timer task. - * for( ;; ); - * } - * @endcode - * \defgroup xTaskCreateRestricted xTaskCreateRestricted - * \ingroup Tasks - */ -#if( portUSING_MPU_WRAPPERS == 1 ) -BaseType_t xTaskCreateRestricted( - const TaskParameters_t * const pxTaskDefinition, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configNUMBER_OF_CORES > 1 ) && \ - ( configUSE_CORE_AFFINITY == 1 ) ) -BaseType_t xTaskCreateRestrictedAffinitySet( - const TaskParameters_t * const pxTaskDefinition, - UBaseType_t uxCoreAffinityMask, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * BaseType_t xTaskCreateRestrictedStatic( TaskParameters_t *pxTaskDefinition, - * TaskHandle_t *pxCreatedTask ); - * @endcode - * - * Only available when configSUPPORT_STATIC_ALLOCATION is set to 1. - * - * xTaskCreateRestrictedStatic() should only be used in systems that include an - * MPU implementation. - * - * Internally, within the FreeRTOS implementation, tasks use two blocks of - * memory. The first block is used to hold the task's data structures. The - * second block is used by the task as its stack. If a task is created using - * xTaskCreateRestricted() then the stack is provided by the application writer, - * and the memory used to hold the task's data structure is automatically - * dynamically allocated inside the xTaskCreateRestricted() function. If a task - * is created using xTaskCreateRestrictedStatic() then the application writer - * must provide the memory used to hold the task's data structures too. - * xTaskCreateRestrictedStatic() therefore allows a memory protected task to be - * created without using any dynamic memory allocation. - * - * @param pxTaskDefinition Pointer to a structure that contains a member - * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API - * documentation) plus an optional stack buffer and the memory region - * definitions. If configSUPPORT_STATIC_ALLOCATION is set to 1 the structure - * contains an additional member, which is used to point to a variable of type - * StaticTask_t - which is then used to hold the task's data structure. - * - * @param pxCreatedTask Used to pass back a handle by which the created task - * can be referenced. - * - * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file projdefs.h - * - * Example usage: - * @code{c} - * // Create an TaskParameters_t structure that defines the task to be created. - * // The StaticTask_t variable is only included in the structure when - * // configSUPPORT_STATIC_ALLOCATION is set to 1. The PRIVILEGED_DATA macro - * can - * // be used to force the variable into the RTOS kernel's privileged data area. - * static PRIVILEGED_DATA StaticTask_t xTaskBuffer; - * static const TaskParameters_t xCheckTaskParameters = - * { - * vATask, // pvTaskCode - the function that implements the task. - * "ATask", // pcName - just a text name for the task to assist debugging. - * 100, // usStackDepth - the stack size DEFINED IN WORDS. - * NULL, // pvParameters - passed into the task function as the function - * parameters. ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set - * the portPRIVILEGE_BIT if the task should run in a privileged state. - * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack. - * - * // xRegions - Allocate up to three separate memory regions for access by - * // the task, with appropriate access permissions. Different processors have - * // different memory alignment requirements - refer to the FreeRTOS - * documentation - * // for full information. - * { - * // Base address Length Parameters - * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE }, - * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY }, - * { cPrivilegedOnlyAccessArray, 128, - * portMPU_REGION_PRIVILEGED_READ_WRITE } - * } - * - * &xTaskBuffer; // Holds the task's data structure. - * }; - * - * int main( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task from the const structure defined above. The task handle - * // is requested (the second parameter is not NULL) but in this case just for - * // demonstration purposes as its not actually used. - * xTaskCreateRestrictedStatic( &xRegTest1Parameters, &xHandle ); - * - * // Start the scheduler. - * vTaskStartScheduler(); - * - * // Will only get here if there was insufficient memory to create the idle - * // and/or timer task. - * for( ;; ); - * } - * @endcode - * \defgroup xTaskCreateRestrictedStatic xTaskCreateRestrictedStatic - * \ingroup Tasks - */ -#if( ( portUSING_MPU_WRAPPERS == 1 ) && \ - ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) -BaseType_t xTaskCreateRestrictedStatic( - const TaskParameters_t * const pxTaskDefinition, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -#if( ( portUSING_MPU_WRAPPERS == 1 ) && \ - ( configSUPPORT_STATIC_ALLOCATION == 1 ) && \ - ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) -BaseType_t xTaskCreateRestrictedStaticAffinitySet( - const TaskParameters_t * const pxTaskDefinition, - UBaseType_t uxCoreAffinityMask, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * - * const pxRegions ); - * @endcode - * - * Memory regions are assigned to a restricted task when the task is created by - * a call to xTaskCreateRestricted(). These regions can be redefined using - * vTaskAllocateMPURegions(). - * - * @param xTask The handle of the task being updated. - * - * @param[in] pxRegions A pointer to a MemoryRegion_t structure that contains - * the new memory region definitions. - * - * Example usage: - * @code{c} - * // Define an array of MemoryRegion_t structures that configures an MPU region - * // allowing read/write access for 1024 bytes starting at the beginning of the - * // ucOneKByte array. The other two of the maximum 3 definable regions are - * // unused so set to zero. - * static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] = - * { - * // Base address Length Parameters - * { ucOneKByte, 1024, portMPU_REGION_READ_WRITE }, - * { 0, 0, 0 }, - * { 0, 0, 0 } - * }; - * - * void vATask( void *pvParameters ) - * { - * // This task was created such that it has access to certain regions of - * // memory as defined by the MPU configuration. At some point it is - * // desired that these MPU regions are replaced with that defined in the - * // xAltRegions const struct above. Use a call to vTaskAllocateMPURegions() - * // for this purpose. NULL is used as the task handle to indicate that this - * // function should modify the MPU regions of the calling task. - * vTaskAllocateMPURegions( NULL, xAltRegions ); - * - * // Now the task can continue its function, but from this point on can only - * // access its stack and the ucOneKByte array (unless any other statically - * // defined or shared regions have been declared elsewhere). - * } - * @endcode - * \defgroup vTaskAllocateMPURegions vTaskAllocateMPURegions - * \ingroup Tasks - */ -void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, - const MemoryRegion_t * const pxRegions ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskDelete( TaskHandle_t xTaskToDelete ); - * @endcode - * - * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Remove a task from the RTOS real time kernel's management. The task being - * deleted will be removed from all ready, blocked, suspended and event lists. - * - * NOTE: The idle task is responsible for freeing the kernel allocated - * memory from tasks that have been deleted. It is therefore important that - * the idle task is not starved of microcontroller processing time if your - * application makes any calls to vTaskDelete (). Memory allocated by the - * task code is not automatically freed, and should be freed before the task - * is deleted. - * - * See the demo application file death.c for sample code that utilises - * vTaskDelete (). - * - * @param xTaskToDelete The handle of the task to be deleted. Passing NULL will - * cause the calling task to be deleted. - * - * Example usage: - * @code{c} - * void vOtherFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create the task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // Use the handle to delete the task. - * vTaskDelete( xHandle ); - * } - * @endcode - * \defgroup vTaskDelete vTaskDelete - * \ingroup Tasks - */ -void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- - * TASK CONTROL API - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * void vTaskDelay( const TickType_t xTicksToDelay ); - * @endcode - * - * Delay a task for a given number of ticks. The actual time that the - * task remains blocked depends on the tick rate. The constant - * portTICK_PERIOD_MS can be used to calculate real time from the tick - * rate - with the resolution of one tick period. - * - * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * - * vTaskDelay() specifies a time at which the task wishes to unblock relative to - * the time at which vTaskDelay() is called. For example, specifying a block - * period of 100 ticks will cause the task to unblock 100 ticks after - * vTaskDelay() is called. vTaskDelay() does not therefore provide a good - * method of controlling the frequency of a periodic task as the path taken - * through the code, as well as other task and interrupt activity, will affect - * the frequency at which vTaskDelay() gets called and therefore the time at - * which the task next executes. See xTaskDelayUntil() for an alternative API - * function designed to facilitate fixed frequency execution. It does this by - * specifying an absolute time (rather than a relative time) at which the - * calling task should unblock. - * - * @param xTicksToDelay The amount of time, in tick periods, that - * the calling task should block. - * - * Example usage: - * - * void vTaskFunction( void * pvParameters ) - * { - * // Block for 500ms. - * const TickType_t xDelay = 500 / portTICK_PERIOD_MS; - * - * for( ;; ) - * { - * // Simply toggle the LED every 500ms, blocking between each toggle. - * vToggleLED(); - * vTaskDelay( xDelay ); - * } - * } - * - * \defgroup vTaskDelay vTaskDelay - * \ingroup TaskCtrl - */ -void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * BaseType_t xTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t - * xTimeIncrement ); - * @endcode - * - * INCLUDE_xTaskDelayUntil must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Delay a task until a specified time. This function can be used by periodic - * tasks to ensure a constant execution frequency. - * - * This function differs from vTaskDelay () in one important aspect: vTaskDelay - * () will cause a task to block for the specified number of ticks from the time - * vTaskDelay () is called. It is therefore difficult to use vTaskDelay () by - * itself to generate a fixed execution frequency as the time between a task - * starting to execute and that task calling vTaskDelay () may not be fixed [the - * task may take a different path though the code between calls, or may get - * interrupted or preempted a different number of times each time it executes]. - * - * Whereas vTaskDelay () specifies a wake time relative to the time at which the - * function is called, xTaskDelayUntil () specifies the absolute (exact) time at - * which it wishes to unblock. - * - * The macro pdMS_TO_TICKS() can be used to calculate the number of ticks from a - * time specified in milliseconds with a resolution of one tick period. - * - * @param pxPreviousWakeTime Pointer to a variable that holds the time at which - * the task was last unblocked. The variable must be initialised with the - * current time prior to its first use (see the example below). Following this - * the variable is automatically updated within xTaskDelayUntil (). - * - * @param xTimeIncrement The cycle time period. The task will be unblocked at - * time *pxPreviousWakeTime + xTimeIncrement. Calling xTaskDelayUntil with the - * same xTimeIncrement parameter value will cause the task to execute with - * a fixed interface period. - * - * @return Value which can be used to check whether the task was actually - * delayed. Will be pdTRUE if the task way delayed and pdFALSE otherwise. A - * task will not be delayed if the next expected wake time is in the past. - * - * Example usage: - * @code{c} - * // Perform an action every 10 ticks. - * void vTaskFunction( void * pvParameters ) - * { - * TickType_t xLastWakeTime; - * const TickType_t xFrequency = 10; - * BaseType_t xWasDelayed; - * - * // Initialise the xLastWakeTime variable with the current time. - * xLastWakeTime = xTaskGetTickCount (); - * for( ;; ) - * { - * // Wait for the next cycle. - * xWasDelayed = xTaskDelayUntil( &xLastWakeTime, xFrequency ); - * - * // Perform action here. xWasDelayed value can be used to determine - * // whether a deadline was missed if the code here took too long. - * } - * } - * @endcode - * \defgroup xTaskDelayUntil xTaskDelayUntil - * \ingroup TaskCtrl - */ -BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, - const TickType_t xTimeIncrement ) - PRIVILEGED_FUNCTION; - -/* - * vTaskDelayUntil() is the older version of xTaskDelayUntil() and does not - * return a value. - */ -#define vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ) \ - do \ - { \ - ( void ) xTaskDelayUntil( ( pxPreviousWakeTime ), \ - ( xTimeIncrement ) ); \ - } while( 0 ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskAbortDelay( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this - * function to be available. - * - * A task will enter the Blocked state when it is waiting for an event. The - * event it is waiting for can be a temporal event (waiting for a time), such - * as when vTaskDelay() is called, or an event on an object, such as when - * xQueueReceive() or ulTaskNotifyTake() is called. If the handle of a task - * that is in the Blocked state is used in a call to xTaskAbortDelay() then the - * task will leave the Blocked state, and return from whichever function call - * placed the task into the Blocked state. - * - * There is no 'FromISR' version of this function as an interrupt would need to - * know which object a task was blocked on in order to know which actions to - * take. For example, if the task was blocked on a queue the interrupt handler - * would then need to know if the queue was locked. - * - * @param xTask The handle of the task to remove from the Blocked state. - * - * @return If the task referenced by xTask was not in the Blocked state then - * pdFAIL is returned. Otherwise pdPASS is returned. - * - * \defgroup xTaskAbortDelay xTaskAbortDelay - * \ingroup TaskCtrl - */ -BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Obtain the priority of any task. - * - * @param xTask Handle of the task to be queried. Passing a NULL - * handle results in the priority of the calling task being returned. - * - * @return The priority of xTask. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to obtain the priority of the created task. - * // It was created with tskIDLE_PRIORITY, but may have changed - * // it itself. - * if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY ) - * { - * // The task has changed it's priority. - * } - * - * // ... - * - * // Is our priority higher than the created task? - * if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) ) - * { - * // Our priority (obtained using NULL handle) is higher. - * } - * } - * @endcode - * \defgroup uxTaskPriorityGet uxTaskPriorityGet - * \ingroup TaskCtrl - */ -UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ); - * @endcode - * - * A version of uxTaskPriorityGet() that can be used from an ISR. - */ -UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * eTaskState eTaskGetState( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Obtain the state of any task. States are encoded by the eTaskState - * enumerated type. - * - * @param xTask Handle of the task to be queried. - * - * @return The state of xTask at the time the function was called. Note the - * state of the task might change between the function being called, and the - * functions return value being tested by the calling task. - */ -eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t - * xGetFreeStackSpace, eTaskState eState ); - * @endcode - * - * configUSE_TRACE_FACILITY must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Populates a TaskStatus_t structure with information about a task. - * - * @param xTask Handle of the task being queried. If xTask is NULL then - * information will be returned about the calling task. - * - * @param pxTaskStatus A pointer to the TaskStatus_t structure that will be - * filled with information about the task referenced by the handle passed using - * the xTask parameter. - * - * @param xGetFreeStackSpace The TaskStatus_t structure contains a member to - * report the stack high water mark of the task being queried. Calculating the - * stack high water mark takes a relatively long time, and can make the system - * temporarily unresponsive - so the xGetFreeStackSpace parameter is provided to - * allow the high water mark checking to be skipped. The high watermark value - * will only be written to the TaskStatus_t structure if xGetFreeStackSpace is - * not set to pdFALSE; - * - * @param eState The TaskStatus_t structure contains a member to report the - * state of the task being queried. Obtaining the task state is not as fast as - * a simple assignment - so the eState parameter is provided to allow the state - * information to be omitted from the TaskStatus_t structure. To obtain state - * information then set eState to eInvalid - otherwise the value passed in - * eState will be reported as the task state in the TaskStatus_t structure. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * TaskStatus_t xTaskDetails; - * - * // Obtain the handle of a task from its name. - * xHandle = xTaskGetHandle( "Task_Name" ); - * - * // Check the handle is not NULL. - * configASSERT( xHandle ); - * - * // Use the handle to obtain further information about the task. - * vTaskGetInfo( xHandle, - * &xTaskDetails, - * pdTRUE, // Include the high water mark in xTaskDetails. - * eInvalid ); // Include the task state in xTaskDetails. - * } - * @endcode - * \defgroup vTaskGetInfo vTaskGetInfo - * \ingroup TaskCtrl - */ -void vTaskGetInfo( TaskHandle_t xTask, - TaskStatus_t * pxTaskStatus, - BaseType_t xGetFreeStackSpace, - eTaskState eState ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ); - * @endcode - * - * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Set the priority of any task. - * - * A context switch will occur before the function returns if the priority - * being set is higher than the currently executing task. - * - * @param xTask Handle to the task for which the priority is being set. - * Passing a NULL handle results in the priority of the calling task being set. - * - * @param uxNewPriority The priority to which the task will be set. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to raise the priority of the created task. - * vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 ); - * - * // ... - * - * // Use a NULL handle to raise our priority to the same value. - * vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 ); - * } - * @endcode - * \defgroup vTaskPrioritySet vTaskPrioritySet - * \ingroup TaskCtrl - */ -void vTaskPrioritySet( TaskHandle_t xTask, - UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskSuspend( TaskHandle_t xTaskToSuspend ); - * @endcode - * - * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Suspend any task. When suspended a task will never get any microcontroller - * processing time, no matter what its priority. - * - * Calls to vTaskSuspend are not accumulative - - * i.e. calling vTaskSuspend () twice on the same task still only requires one - * call to vTaskResume () to ready the suspended task. - * - * @param xTaskToSuspend Handle to the task being suspended. Passing a NULL - * handle will cause the calling task to be suspended. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to suspend the created task. - * vTaskSuspend( xHandle ); - * - * // ... - * - * // The created task will not run during this period, unless - * // another task calls vTaskResume( xHandle ). - * - * //... - * - * - * // Suspend ourselves. - * vTaskSuspend( NULL ); - * - * // We cannot get here unless another task calls vTaskResume - * // with our handle as the parameter. - * } - * @endcode - * \defgroup vTaskSuspend vTaskSuspend - * \ingroup TaskCtrl - */ -void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskResume( TaskHandle_t xTaskToResume ); - * @endcode - * - * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Resumes a suspended task. - * - * A task that has been suspended by one or more calls to vTaskSuspend () - * will be made available for running again by a single call to - * vTaskResume (). - * - * @param xTaskToResume Handle to the task being readied. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to suspend the created task. - * vTaskSuspend( xHandle ); - * - * // ... - * - * // The created task will not run during this period, unless - * // another task calls vTaskResume( xHandle ). - * - * //... - * - * - * // Resume the suspended task ourselves. - * vTaskResume( xHandle ); - * - * // The created task will once again get microcontroller processing - * // time in accordance with its priority within the system. - * } - * @endcode - * \defgroup vTaskResume vTaskResume - * \ingroup TaskCtrl - */ -void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void xTaskResumeFromISR( TaskHandle_t xTaskToResume ); - * @endcode - * - * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * An implementation of vTaskResume() that can be called from within an ISR. - * - * A task that has been suspended by one or more calls to vTaskSuspend () - * will be made available for running again by a single call to - * xTaskResumeFromISR (). - * - * xTaskResumeFromISR() should not be used to synchronise a task with an - * interrupt if there is a chance that the interrupt could arrive prior to the - * task being suspended - as this can lead to interrupts being missed. Use of a - * semaphore as a synchronisation mechanism would avoid this eventuality. - * - * @param xTaskToResume Handle to the task being readied. - * - * @return pdTRUE if resuming the task should result in a context switch, - * otherwise pdFALSE. This is used by the ISR to determine if a context switch - * may be required following the ISR. - * - * \defgroup vTaskResumeFromISR vTaskResumeFromISR - * \ingroup TaskCtrl - */ -BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; - -#if( configUSE_CORE_AFFINITY == 1 ) - -/** - * @brief Sets the core affinity mask for a task. - * - * It sets the cores on which a task can run. configUSE_CORE_AFFINITY must - * be defined as 1 for this function to be available. - * - * @param xTask The handle of the task to set the core affinity mask for. - * Passing NULL will set the core affinity mask for the calling task. - * - * @param uxCoreAffinityMask A bitwise value that indicates the cores on - * which the task can run. Cores are numbered from 0 to configNUMBER_OF_CORES - * - 1. For example, to ensure that a task can run on core 0 and core 1, set - * uxCoreAffinityMask to 0x03. - * - * Example usage: - * - * // The function that creates task. - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * UBaseType_t uxCoreAffinityMask; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &( - * xHandle ) ); - * - * // Define the core affinity mask such that this task can only run - * // on core 0 and core 2. - * uxCoreAffinityMask = ( ( 1 << 0 ) | ( 1 << 2 ) ); - * - * //Set the core affinity mask for the task. - * vTaskCoreAffinitySet( xHandle, uxCoreAffinityMask ); - * } - */ -void vTaskCoreAffinitySet( const TaskHandle_t xTask, - UBaseType_t uxCoreAffinityMask ); -#endif - -#if( configUSE_CORE_AFFINITY == 1 ) - -/** - * @brief Gets the core affinity mask for a task. - * - * configUSE_CORE_AFFINITY must be defined as 1 for this function to be - * available. - * - * @param xTask The handle of the task to get the core affinity mask for. - * Passing NULL will get the core affinity mask for the calling task. - * - * @return The core affinity mask which is a bitwise value that indicates - * the cores on which a task can run. Cores are numbered from 0 to - * configNUMBER_OF_CORES - 1. For example, if a task can run on core 0 and core - * 1, the core affinity mask is 0x03. - * - * Example usage: - * - * // Task handle of the networking task - it is populated elsewhere. - * TaskHandle_t xNetworkingTaskHandle; - * - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * UBaseType_t uxNetworkingCoreAffinityMask; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &( - * xHandle ) ); - * - * //Get the core affinity mask for the networking task. - * uxNetworkingCoreAffinityMask = vTaskCoreAffinityGet( - * xNetworkingTaskHandle ); - * - * // Here is a hypothetical scenario, just for the example. Assume that we - * // have 2 cores - Core 0 and core 1. We want to pin the application task - * to - * // the core different than the networking task to ensure that the - * // application task does not interfere with networking. - * if( ( uxNetworkingCoreAffinityMask & ( 1 << 0 ) ) != 0 ) - * { - * // The networking task can run on core 0, pin our task to core 1. - * vTaskCoreAffinitySet( xHandle, ( 1 << 1 ) ); - * } - * else - * { - * // Otherwise, pin our task to core 0. - * vTaskCoreAffinitySet( xHandle, ( 1 << 0 ) ); - * } - * } - */ -UBaseType_t vTaskCoreAffinityGet( ConstTaskHandle_t xTask ); -#endif - -#if( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - -/** - * @brief Disables preemption for a task. - * - * @param xTask The handle of the task to disable preemption. Passing NULL - * disables preemption for the calling task. - * - * Example usage: - * - * void vTaskCode( void *pvParameters ) - * { - * // Silence warnings about unused parameters. - * ( void ) pvParameters; - * - * for( ;; ) - * { - * // ... Perform some function here. - * - * // Disable preemption for this task. - * vTaskPreemptionDisable( NULL ); - * - * // The task will not be preempted when it is executing in this - * portion ... - * - * // ... until the preemption is enabled again. - * vTaskPreemptionEnable( NULL ); - * - * // The task can be preempted when it is executing in this portion. - * } - * } - */ -void vTaskPreemptionDisable( const TaskHandle_t xTask ); -#endif - -#if( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - -/** - * @brief Enables preemption for a task. - * - * @param xTask The handle of the task to enable preemption. Passing NULL - * enables preemption for the calling task. - * - * Example usage: - * - * void vTaskCode( void *pvParameters ) - * { - * // Silence warnings about unused parameters. - * ( void ) pvParameters; - * - * for( ;; ) - * { - * // ... Perform some function here. - * - * // Disable preemption for this task. - * vTaskPreemptionDisable( NULL ); - * - * // The task will not be preempted when it is executing in this - * portion ... - * - * // ... until the preemption is enabled again. - * vTaskPreemptionEnable( NULL ); - * - * // The task can be preempted when it is executing in this portion. - * } - * } - */ -void vTaskPreemptionEnable( const TaskHandle_t xTask ); -#endif - -/*----------------------------------------------------------- - * SCHEDULER CONTROL - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * void vTaskStartScheduler( void ); - * @endcode - * - * Starts the real time kernel tick processing. After calling the kernel - * has control over which tasks are executed and when. - * - * See the demo application file main.c for an example of creating - * tasks and starting the kernel. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * // Create at least one task before starting the kernel. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); - * - * // Start the real time kernel with preemption. - * vTaskStartScheduler (); - * - * // Will not get here unless a task calls vTaskEndScheduler () - * } - * @endcode - * - * \defgroup vTaskStartScheduler vTaskStartScheduler - * \ingroup SchedulerControl - */ -void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskEndScheduler( void ); - * @endcode - * - * NOTE: At the time of writing only the x86 real mode port, which runs on a PC - * in place of DOS, implements this function. - * - * Stops the real time kernel tick. All created tasks will be automatically - * deleted and multitasking (either preemptive or cooperative) will - * stop. Execution then resumes from the point where vTaskStartScheduler () - * was called, as if vTaskStartScheduler () had just returned. - * - * See the demo application file main. c in the demo/PC directory for an - * example that uses vTaskEndScheduler (). - * - * vTaskEndScheduler () requires an exit function to be defined within the - * portable layer (see vPortEndScheduler () in port. c for the PC port). This - * performs hardware specific operations such as stopping the kernel tick. - * - * vTaskEndScheduler () will cause all of the resources allocated by the - * kernel to be freed - but will not free resources allocated by application - * tasks. - * - * Example usage: - * @code{c} - * void vTaskCode( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // At some point we want to end the real time kernel processing - * // so call ... - * vTaskEndScheduler (); - * } - * } - * - * void vAFunction( void ) - * { - * // Create at least one task before starting the kernel. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); - * - * // Start the real time kernel with preemption. - * vTaskStartScheduler (); - * - * // Will only get here when the vTaskCode () task has called - * // vTaskEndScheduler (). When we get here we are back to single task - * // execution. - * } - * @endcode - * - * \defgroup vTaskEndScheduler vTaskEndScheduler - * \ingroup SchedulerControl - */ -void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskSuspendAll( void ); - * @endcode - * - * Suspends the scheduler without disabling interrupts. Context switches will - * not occur while the scheduler is suspended. - * - * After calling vTaskSuspendAll () the calling task will continue to execute - * without risk of being swapped out until a call to xTaskResumeAll () has been - * made. - * - * API functions that have the potential to cause a context switch (for example, - * xTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler - * is suspended. - * - * Example usage: - * @code{c} - * void vTask1( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // ... - * - * // At some point the task wants to perform a long operation during - * // which it does not want to get swapped out. It cannot use - * // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the - * // operation may cause interrupts to be missed - including the - * // ticks. - * - * // Prevent the real time kernel swapping out the task. - * vTaskSuspendAll (); - * - * // Perform the operation here. There is no need to use critical - * // sections as we have all the microcontroller processing time. - * // During this time interrupts will still operate and the kernel - * // tick count will be maintained. - * - * // ... - * - * // The operation is complete. Restart the kernel. - * xTaskResumeAll (); - * } - * } - * @endcode - * \defgroup vTaskSuspendAll vTaskSuspendAll - * \ingroup SchedulerControl - */ -void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * BaseType_t xTaskResumeAll( void ); - * @endcode - * - * Resumes scheduler activity after it was suspended by a call to - * vTaskSuspendAll(). - * - * xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks - * that were previously suspended by a call to vTaskSuspend(). - * - * @return If resuming the scheduler caused a context switch then pdTRUE is - * returned, otherwise pdFALSE is returned. - * - * Example usage: - * @code{c} - * void vTask1( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // ... - * - * // At some point the task wants to perform a long operation during - * // which it does not want to get swapped out. It cannot use - * // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the - * // operation may cause interrupts to be missed - including the - * // ticks. - * - * // Prevent the real time kernel swapping out the task. - * vTaskSuspendAll (); - * - * // Perform the operation here. There is no need to use critical - * // sections as we have all the microcontroller processing time. - * // During this time interrupts will still operate and the real - * // time kernel tick count will be maintained. - * - * // ... - * - * // The operation is complete. Restart the kernel. We want to force - * // a context switch - but there is no point if resuming the scheduler - * // caused a context switch already. - * if( !xTaskResumeAll () ) - * { - * taskYIELD (); - * } - * } - * } - * @endcode - * \defgroup xTaskResumeAll xTaskResumeAll - * \ingroup SchedulerControl - */ -BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- - * TASK UTILITIES - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * TickType_t xTaskGetTickCount( void ); - * @endcode - * - * @return The count of ticks since vTaskStartScheduler was called. - * - * \defgroup xTaskGetTickCount xTaskGetTickCount - * \ingroup TaskUtils - */ -TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * TickType_t xTaskGetTickCountFromISR( void ); - * @endcode - * - * @return The count of ticks since vTaskStartScheduler was called. - * - * This is a version of xTaskGetTickCount() that is safe to be called from an - * ISR - provided that TickType_t is the natural word size of the - * microcontroller being used or interrupt nesting is either not supported or - * not being used. - * - * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR - * \ingroup TaskUtils - */ -TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * uint16_t uxTaskGetNumberOfTasks( void ); - * @endcode - * - * @return The number of tasks that the real time kernel is currently managing. - * This includes all ready, blocked and suspended tasks. A task that - * has been deleted but not yet freed by the idle task will also be - * included in the count. - * - * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks - * \ingroup TaskUtils - */ -UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * char *pcTaskGetName( TaskHandle_t xTaskToQuery ); - * @endcode - * - * @return The text (human readable) name of the task referenced by the handle - * xTaskToQuery. A task can query its own name by either passing in its own - * handle, or by setting xTaskToQuery to NULL. - * - * \defgroup pcTaskGetName pcTaskGetName - * \ingroup TaskUtils - */ -char * pcTaskGetName( TaskHandle_t xTaskToQuery ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ); - * @endcode - * - * NOTE: This function takes a relatively long time to complete and should be - * used sparingly. - * - * @return The handle of the task that has the human readable name - * pcNameToQuery. NULL is returned if no matching name is found. - * INCLUDE_xTaskGetHandle must be set to 1 in FreeRTOSConfig.h for - * pcTaskGetHandle() to be available. - * - * \defgroup pcTaskGetHandle pcTaskGetHandle - * \ingroup TaskUtils - */ -TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask, - * StackType_t ** ppuxStackBuffer, - * StaticTask_t ** ppxTaskBuffer ); - * @endcode - * - * Retrieve pointers to a statically created task's data structure - * buffer and stack buffer. These are the same buffers that are supplied - * at the time of creation. - * - * @param xTask The task for which to retrieve the buffers. - * - * @param ppuxStackBuffer Used to return a pointer to the task's stack buffer. - * - * @param ppxTaskBuffer Used to return a pointer to the task's data structure - * buffer. - * - * @return pdTRUE if buffers were retrieved, pdFALSE otherwise. - * - * \defgroup xTaskGetStaticBuffers xTaskGetStaticBuffers - * \ingroup TaskUtils - */ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) -BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask, - StackType_t ** ppuxStackBuffer, - StaticTask_t ** ppxTaskBuffer ) - PRIVILEGED_FUNCTION; -#endif /* configSUPPORT_STATIC_ALLOCATION */ - -/** - * task.h - * @code{c} - * UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for - * this function to be available. - * - * Returns the high water mark of the stack associated with xTask. That is, - * the minimum free stack space there has been (in words, so on a 32 bit machine - * a value of 1 means 4 bytes) since the task started. The smaller the returned - * number the closer the task has come to overflowing its stack. - * - * 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. - * - * @param xTask Handle of the task associated with the stack to be checked. - * Set xTask to NULL to check the stack of the calling task. - * - * @return The smallest amount of free stack space there has been (in words, so - * actual spaces on the stack rather than bytes) since the task referenced by - * xTask was created. - */ -UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskGetStackHighWaterMark2 must be set to 1 in FreeRTOSConfig.h for - * this function to be available. - * - * Returns the high water mark of the stack associated with xTask. That is, - * the minimum free stack space there has been (in words, so on a 32 bit machine - * a value of 1 means 4 bytes) since the task started. The smaller the returned - * number the closer the task has come to overflowing its stack. - * - * 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. - * - * @param xTask Handle of the task associated with the stack to be checked. - * Set xTask to NULL to check the stack of the calling task. - * - * @return The smallest amount of free stack space there has been (in words, so - * actual spaces on the stack rather than bytes) since the task referenced by - * xTask was created. - */ -configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/* When using trace macros it is sometimes necessary to include task.h before - * FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been - * defined, so the following two prototypes will cause a compilation error. This - * can be fixed by simply guarding against the inclusion of these two prototypes - * unless they are explicitly required by the configUSE_APPLICATION_TASK_TAG - * configuration constant. */ -#ifdef configUSE_APPLICATION_TASK_TAG - #if configUSE_APPLICATION_TASK_TAG == 1 - -/** - * task.h - * @code{c} - * void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t - * pxHookFunction ); - * @endcode - * - * Sets pxHookFunction to be the task hook function used by the task xTask. - * Passing xTask as NULL has the effect of setting the calling tasks hook - * function. - */ -void vTaskSetApplicationTaskTag( TaskHandle_t xTask, - TaskHookFunction_t pxHookFunction ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * void xTaskGetApplicationTaskTag( TaskHandle_t xTask ); - * @endcode - * - * Returns the pxHookFunction value assigned to the task xTask. Do not - * call from an interrupt service routine - call - * xTaskGetApplicationTaskTagFromISR() instead. - */ -TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * void xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ); - * @endcode - * - * Returns the pxHookFunction value assigned to the task xTask. Can - * be called from an interrupt service routine. - */ -TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ -#endif /* ifdef configUSE_APPLICATION_TASK_TAG */ - -#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) - -/* Each task contains an array of pointers that is dimensioned by the - * configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. The - * kernel does not use the pointers itself, so the application writer can use - * the pointers for any purpose they wish. The following two functions are - * used to set and query a pointer respectively. */ -void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, - BaseType_t xIndex, - void * pvValue ) PRIVILEGED_FUNCTION; -void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, - BaseType_t xIndex ) - PRIVILEGED_FUNCTION; - -#endif - -#if( configCHECK_FOR_STACK_OVERFLOW > 0 ) - -/** - * task.h - * @code{c} - * void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName); - * @endcode - * - * The application stack overflow hook is called when a stack overflow is - * detected for a task. - * - * Details on stack overflow detection can be found here: - * https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html - * - * @param xTask the task that just exceeded its stack boundaries. - * @param pcTaskName A character string containing the name of the offending - * task. - */ -void vApplicationStackOverflowHook( TaskHandle_t xTask, char * pcTaskName ); - -#endif - -#if( configUSE_IDLE_HOOK == 1 ) - -/** - * task.h - * @code{c} - * void vApplicationIdleHook( void ); - * @endcode - * - * The application idle hook is called by the idle task. - * This allows the application designer to add background functionality without - * the overhead of a separate task. - * NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A - * FUNCTION THAT MIGHT BLOCK. - */ -void vApplicationIdleHook( void ); - -#endif - -#if( configUSE_TICK_HOOK != 0 ) - -/** - * task.h - * @code{c} - * void vApplicationTickHook( void ); - * @endcode - * - * This hook function is called in the system tick handler after any OS work is - * completed. - */ -void vApplicationTickHook( void ); /*lint !e526 Symbol not defined as it is an - application callback. */ - -#endif - -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) - -/** - * task.h - * @code{c} - * void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, - * StackType_t ** ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) - * @endcode - * - * This function is used to provide a statically allocated block of memory to - * FreeRTOS to hold the Idle Task TCB. This function is required when - * configSUPPORT_STATIC_ALLOCATION is set. For more information see this URI: - * https://www.FreeRTOS.org/a00110.html#configSUPPORT_STATIC_ALLOCATION - * - * @param ppxIdleTaskTCBBuffer A handle to a statically allocated TCB buffer - * @param ppxIdleTaskStackBuffer A handle to a statically allocated Stack buffer - * for the idle task - * @param pulIdleTaskStackSize A pointer to the number of elements that will fit - * in the allocated stack buffer - */ -void vApplicationGetIdleTaskMemory( - StaticTask_t ** ppxIdleTaskTCBBuffer, - StackType_t ** ppxIdleTaskStackBuffer, - uint32_t * pulIdleTaskStackSize ); /*lint !e526 Symbol not defined as it is - an application callback. */ -#endif - -/** - * task.h - * @code{c} - * BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void - * *pvParameter ); - * @endcode - * - * Calls the hook function associated with xTask. Passing xTask as NULL has - * the effect of calling the Running tasks (the calling task) hook function. - * - * pvParameter is passed to the hook function for the task to interpret as it - * wants. The return value is the value returned by the task hook function - * registered by the user. - */ -BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, - void * pvParameter ) - PRIVILEGED_FUNCTION; - -/** - * xTaskGetIdleTaskHandle() is only available if - * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. - * - * Simply returns the handle of the idle task. It is not valid to call - * xTaskGetIdleTaskHandle() before the scheduler has been started. - */ -TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; - -/** - * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for - * uxTaskGetSystemState() to be available. - * - * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in - * the system. TaskStatus_t structures contain, among other things, members - * for the task handle, task name, task priority, task state, and total amount - * of run time consumed by the task. See the TaskStatus_t structure - * definition in this file for the full member list. - * - * NOTE: This function is intended for debugging use only as its use results in - * the scheduler remaining suspended for an extended period. - * - * @param pxTaskStatusArray A pointer to an array of TaskStatus_t structures. - * The array must contain at least one TaskStatus_t structure for each task - * that is under the control of the RTOS. The number of tasks under the control - * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API - * function. - * - * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray - * parameter. The size is specified as the number of indexes in the array, or - * the number of TaskStatus_t structures contained in the array, not by the - * number of bytes in the array. - * - * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in - * FreeRTOSConfig.h then *pulTotalRunTime is set by uxTaskGetSystemState() to - * the total run time (as defined by the run time stats clock, see - * https://www.FreeRTOS.org/rtos-run-time-stats.html) since the target booted. - * pulTotalRunTime can be set to NULL to omit the total run time information. - * - * @return The number of TaskStatus_t structures that were populated by - * uxTaskGetSystemState(). This should equal the number returned by the - * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed - * in the uxArraySize parameter was too small. - * - * Example usage: - * @code{c} - * // This example demonstrates how a human readable table of run time stats - * // information is generated from raw data provided by - * uxTaskGetSystemState(). - * // The human readable table is written to pcWriteBuffer - * void vTaskGetRunTimeStats( char *pcWriteBuffer ) - * { - * TaskStatus_t *pxTaskStatusArray; - * volatile UBaseType_t uxArraySize, x; - * configRUN_TIME_COUNTER_TYPE ulTotalRunTime, ulStatsAsPercentage; - * - * // Make sure the write buffer does not contain a string. - * pcWriteBuffer = 0x00; - * - * // Take a snapshot of the number of tasks in case it changes while this - * // function is executing. - * uxArraySize = uxTaskGetNumberOfTasks(); - * - * // Allocate a TaskStatus_t structure for each task. An array could be - * // allocated statically at compile time. - * pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) - * ); - * - * if( pxTaskStatusArray != NULL ) - * { - * // Generate raw status information about each task. - * uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, - * &ulTotalRunTime ); - * - * // For percentage calculations. - * ulTotalRunTime /= 100UL; - * - * // Avoid divide by zero errors. - * if( ulTotalRunTime > 0 ) - * { - * // For each populated position in the pxTaskStatusArray array, - * // format the raw data as human readable ASCII 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. - * // ulTotalRunTimeDiv100 has already been divided by 100. - * ulStatsAsPercentage = pxTaskStatusArray[ x - * ].ulRunTimeCounter / ulTotalRunTime; - * - * if( ulStatsAsPercentage > 0UL ) - * { - * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", - * pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, - * ulStatsAsPercentage ); - * } - * else - * { - * // If the percentage is zero here then the task has - * // consumed less than 1% of the total run time. - * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", - * pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter ); - * } - * - * pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); - * } - * } - * - * // The array is no longer needed, free the memory it consumes. - * vPortFree( pxTaskStatusArray ); - * } - * } - * @endcode - */ -UBaseType_t uxTaskGetSystemState( - TaskStatus_t * const pxTaskStatusArray, - const UBaseType_t uxArraySize, - configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskList( char *pcWriteBuffer ); - * @endcode - * - * configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must - * both be defined as 1 for this function to be available. See the - * configuration section of the FreeRTOS.org website for more information. - * - * NOTE 1: This function will disable interrupts for its duration. It is - * not intended for normal application runtime use but as a debug aid. - * - * Lists all the current tasks, along with their current state and stack - * usage high water mark. - * - * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or - * suspended ('S'). - * - * 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(). - * - * @param pcWriteBuffer A buffer into which the above mentioned details - * will be written, in ASCII form. This buffer is assumed to be large - * enough to contain the generated report. Approximately 40 bytes per - * task should be sufficient. - * - * \defgroup vTaskList vTaskList - * \ingroup TaskUtils - */ -void vTaskList( char * pcWriteBuffer ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * void vTaskGetRunTimeStats( char *pcWriteBuffer ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS - * must both be defined as 1 for this function to be available. The application - * must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() - * to configure a peripheral timer/counter and return the timers current count - * value respectively. The counter should be at least 10 times the frequency of - * the tick count. - * - * NOTE 1: This function will disable interrupts for its duration. It is - * not intended for normal application runtime use but as a debug aid. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * Calling vTaskGetRunTimeStats() writes the total execution time of each - * task into a buffer, both as an absolute count value and as a percentage - * of the total system execution time. - * - * NOTE 2: - * - * 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(). - * - * @param pcWriteBuffer A buffer into which the execution times will be - * written, in ASCII form. This buffer is assumed to be large enough to - * contain the generated report. Approximately 40 bytes per task should - * be sufficient. - * - * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats - * \ingroup TaskUtils - */ -void vTaskGetRunTimeStats( char * pcWriteBuffer ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask - * ); configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t - * xTask ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS must be defined as 1 for these functions to be - * available. The application must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() to configure a peripheral timer/counter and - * return the timers current count value respectively. The counter should be - * at least 10 times the frequency of the tick count. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total - * execution time of each task into a buffer, ulTaskGetRunTimeCounter() - * returns the total execution time of just one task and - * ulTaskGetRunTimePercent() returns the percentage of the CPU time used by - * just one task. - * - * @return The total run time of the given task or the percentage of the total - * run time consumed by the given task. This is the amount of time the task - * has actually been executing. The unit of time is dependent on the frequency - * configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() macros. - * - * \defgroup ulTaskGetRunTimeCounter ulTaskGetRunTimeCounter - * \ingroup TaskUtils - */ -configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; -configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ); - * configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS must be defined as 1 for these functions to be - * available. The application must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() to configure a peripheral timer/counter and - * return the timers current count value respectively. The counter should be - * at least 10 times the frequency of the tick count. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total - * execution time of each task into a buffer, ulTaskGetIdleRunTimeCounter() - * returns the total execution time of just the idle task and - * ulTaskGetIdleRunTimePercent() returns the percentage of the CPU time used by - * just the idle task. - * - * Note the amount of idle time is only a good measure of the slack time in a - * system if there are no other tasks executing at the idle priority, tickless - * idle is not used, and configIDLE_SHOULD_YIELD is set to 0. - * - * @return The total run time of the idle task or the percentage of the total - * run time consumed by the idle task. This is the amount of time the - * idle task has actually been executing. The unit of time is dependent on the - * frequency configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() macros. - * - * \defgroup ulTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter - * \ingroup TaskUtils - */ -configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ) - PRIVILEGED_FUNCTION; -configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyIndexed( TaskHandle_t xTaskToNotify, UBaseType_t - * uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction ); BaseType_t - * xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction - * eAction ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * Sends a direct to task notification to a task, with an optional value and - * action. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * A task can use xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() to - * [optionally] block to wait for a notification to be pending. The task does - * not consume any CPU time while it is in the Blocked state. - * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their - * un-indexed equivalents). If the task was already in the Blocked state to - * wait for a notification when the notification arrives then the task will - * automatically be removed from the Blocked state (unblocked) and the - * notification cleared. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotify() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling xTaskNotify() is equivalent to calling xTaskNotifyIndexed() - * with the uxIndexToNotify parameter set to 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotify() does - * not have this parameter and always sends notifications to index 0. - * - * @param ulValue Data that can be sent with the notification. How the data is - * used depends on the value of the eAction parameter. - * - * @param eAction Specifies how the notification updates the task's notification - * value, if at all. Valid values for eAction are as follows: - * - * eSetBits - - * The target notification value is bitwise ORed with ulValue. - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * eIncrement - - * The target notification value is incremented. ulValue is not used and - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * eSetValueWithOverwrite - - * The target notification value is set to the value of ulValue, even if the - * task being notified had not yet processed the previous notification at the - * same array index (the task already had a notification pending at that index). - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * eSetValueWithoutOverwrite - - * If the task being notified did not already have a notification pending at the - * same array index then the target notification value is set to ulValue and - * xTaskNotifyIndexed() will return pdPASS. If the task being notified already - * had a notification pending at the same array index then no action is - * performed and pdFAIL is returned. - * - * eNoAction - - * The task receives a notification at the specified array index without the - * notification value at that index being updated. ulValue is not used and - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * pulPreviousNotificationValue - - * Can be used to pass out the subject task's notification value before any - * bits are modified by the notify function. - * - * @return Dependent on the value of eAction. See the description of the - * eAction parameter. - * - * \defgroup xTaskNotifyIndexed xTaskNotifyIndexed - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, - UBaseType_t uxIndexToNotify, - uint32_t ulValue, - eNotifyAction eAction, - uint32_t * pulPreviousNotificationValue ) - PRIVILEGED_FUNCTION; -#define xTaskNotify( xTaskToNotify, ulValue, eAction ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - NULL ) -#define xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - NULL ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyAndQueryIndexed( TaskHandle_t xTaskToNotify, - * UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, - * uint32_t *pulPreviousNotifyValue ); BaseType_t xTaskNotifyAndQuery( - * TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t - * *pulPreviousNotifyValue ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * xTaskNotifyAndQueryIndexed() performs the same operation as - * xTaskNotifyIndexed() with the addition that it also returns the subject - * task's prior notification value (the notification value at the time the - * function is called rather than when the function returns) in the additional - * pulPreviousNotifyValue parameter. - * - * xTaskNotifyAndQuery() performs the same operation as xTaskNotify() with the - * addition that it also returns the subject task's prior notification value - * (the notification value as it was at the time the function is called, rather - * than when the function returns) in the additional pulPreviousNotifyValue - * parameter. - * - * \defgroup xTaskNotifyAndQueryIndexed xTaskNotifyAndQueryIndexed - * \ingroup TaskNotifications - */ -#define xTaskNotifyAndQuery( xTaskToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotifyValue ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotifyValue ) ) -#define xTaskNotifyAndQueryIndexed( xTaskToNotify, \ - uxIndexToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotifyValue ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotifyValue ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t - * uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t - * *pxHigherPriorityTaskWoken ); BaseType_t xTaskNotifyFromISR( TaskHandle_t - * xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t - * *pxHigherPriorityTaskWoken ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * A version of xTaskNotifyIndexed() that can be used from an interrupt service - * routine (ISR). - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] - * block to wait for a notification value to have a non-zero value. The task - * does not consume any CPU time while it is in the Blocked state. - * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their - * un-indexed equivalents). If the task was already in the Blocked state to - * wait for a notification when the notification arrives then the task will - * automatically be removed from the Blocked state (unblocked) and the - * notification cleared. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyFromISR() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling xTaskNotifyFromISR() is equivalent to calling - * xTaskNotifyIndexedFromISR() with the uxIndexToNotify parameter set to 0. - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyFromISR() - * does not have this parameter and always sends notifications to index 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param ulValue Data that can be sent with the notification. How the data is - * used depends on the value of the eAction parameter. - * - * @param eAction Specifies how the notification updates the task's notification - * value, if at all. Valid values for eAction are as follows: - * - * eSetBits - - * The task's notification value is bitwise ORed with ulValue. xTaskNotify() - * always returns pdPASS in this case. - * - * eIncrement - - * The task's notification value is incremented. ulValue is not used and - * xTaskNotify() always returns pdPASS in this case. - * - * eSetValueWithOverwrite - - * The task's notification value is set to the value of ulValue, even if the - * task being notified had not yet processed the previous notification (the - * task already had a notification pending). xTaskNotify() always returns - * pdPASS in this case. - * - * eSetValueWithoutOverwrite - - * If the task being notified did not already have a notification pending then - * the task's notification value is set to ulValue and xTaskNotify() will - * return pdPASS. If the task being notified already had a notification - * pending then no action is performed and pdFAIL is returned. - * - * eNoAction - - * The task receives a notification without its notification value being - * updated. ulValue is not used and xTaskNotify() always returns pdPASS in - * this case. - * - * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set - * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the - * task to which the notification was sent to leave the Blocked state, and the - * unblocked task has a priority higher than the currently running task. If - * xTaskNotifyFromISR() sets this value to pdTRUE then a context switch should - * be requested before the interrupt is exited. How a context switch is - * requested from an ISR is dependent on the port - see the documentation page - * for the port in use. - * - * @return Dependent on the value of eAction. See the description of the - * eAction parameter. - * - * \defgroup xTaskNotifyIndexedFromISR xTaskNotifyIndexedFromISR - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, - UBaseType_t uxIndexToNotify, - uint32_t ulValue, - eNotifyAction eAction, - uint32_t * pulPreviousNotificationValue, - BaseType_t * pxHigherPriorityTaskWoken ) - PRIVILEGED_FUNCTION; -#define xTaskNotifyFromISR( xTaskToNotify, \ - ulValue, \ - eAction, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - NULL, \ - ( pxHigherPriorityTaskWoken ) ) -#define xTaskNotifyIndexedFromISR( xTaskToNotify, \ - uxIndexToNotify, \ - ulValue, \ - eAction, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - NULL, \ - ( pxHigherPriorityTaskWoken ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify, - * UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, - * uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken - * ); BaseType_t xTaskNotifyAndQueryFromISR( TaskHandle_t xTaskToNotify, - * uint32_t ulValue, eNotifyAction eAction, uint32_t - * *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * xTaskNotifyAndQueryIndexedFromISR() performs the same operation as - * xTaskNotifyIndexedFromISR() with the addition that it also returns the - * subject task's prior notification value (the notification value at the time - * the function is called rather than at the time the function returns) in the - * additional pulPreviousNotifyValue parameter. - * - * xTaskNotifyAndQueryFromISR() performs the same operation as - * xTaskNotifyFromISR() with the addition that it also returns the subject - * task's prior notification value (the notification value at the time the - * function is called rather than at the time the function returns) in the - * additional pulPreviousNotifyValue parameter. - * - * \defgroup xTaskNotifyAndQueryIndexedFromISR xTaskNotifyAndQueryIndexedFromISR - * \ingroup TaskNotifications - */ -#define xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, \ - uxIndexToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotificationValue, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotificationValue ), \ - ( pxHigherPriorityTaskWoken ) ) -#define xTaskNotifyAndQueryFromISR( xTaskToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotificationValue, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotificationValue ), \ - ( pxHigherPriorityTaskWoken ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyWaitIndexed( UBaseType_t uxIndexToWaitOn, uint32_t - * ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t - * *pulNotificationValue, TickType_t xTicksToWait ); - * - * BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t - * ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait - * ); - * @endcode - * - * Waits for a direct to task notification to be pending at a given index within - * an array of direct to task notifications. - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this - * function to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their - * un-indexed equivalents). If the task was already in the Blocked state to - * wait for a notification when the notification arrives then the task will - * automatically be removed from the Blocked state (unblocked) and the - * notification cleared. - * - * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] - * block to wait for a notification value to have a non-zero value. The task - * does not consume any CPU time while it is in the Blocked state. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyWait() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling xTaskNotifyWait() is equivalent to calling - * xTaskNotifyWaitIndexed() with the uxIndexToWaitOn parameter set to 0. - * - * @param uxIndexToWaitOn The index within the calling task's array of - * notification values on which the calling task will wait for a notification to - * be received. uxIndexToWaitOn must be less than - * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyWait() does - * not have this parameter and always waits for notifications on index 0. - * - * @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value - * will be cleared in the calling task's notification value before the task - * checks to see if any notifications are pending, and optionally blocks if no - * notifications are pending. Setting ulBitsToClearOnEntry to ULONG_MAX (if - * limits.h is included) or 0xffffffffUL (if limits.h is not included) will have - * the effect of resetting the task's notification value to 0. Setting - * ulBitsToClearOnEntry to 0 will leave the task's notification value unchanged. - * - * @param ulBitsToClearOnExit If a notification is pending or received before - * the calling task exits the xTaskNotifyWait() function then the task's - * notification value (see the xTaskNotify() API function) is passed out using - * the pulNotificationValue parameter. Then any bits that are set in - * ulBitsToClearOnExit will be cleared in the task's notification value (note - * *pulNotificationValue is set before any bits are cleared). Setting - * ulBitsToClearOnExit to ULONG_MAX (if limits.h is included) or 0xffffffffUL - * (if limits.h is not included) will have the effect of resetting the task's - * notification value to 0 before the function exits. Setting - * ulBitsToClearOnExit to 0 will leave the task's notification value unchanged - * when the function exits (in which case the value passed out in - * pulNotificationValue will match the task's notification value). - * - * @param pulNotificationValue Used to pass the task's notification value out - * of the function. Note the value passed out will not be effected by the - * clearing of any bits caused by ulBitsToClearOnExit being non-zero. - * - * @param xTicksToWait The maximum amount of time that the task should wait in - * the Blocked state for a notification to be received, should a notification - * not already be pending when xTaskNotifyWait() was called. The task - * will not consume any processing time while it is in the Blocked state. This - * is specified in kernel ticks, the macro pdMS_TO_TICKS( value_in_ms ) can be - * used to convert a time specified in milliseconds to a time specified in - * ticks. - * - * @return If a notification was received (including notifications that were - * already pending when xTaskNotifyWait was called) then pdPASS is - * returned. Otherwise pdFAIL is returned. - * - * \defgroup xTaskNotifyWaitIndexed xTaskNotifyWaitIndexed - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, - uint32_t ulBitsToClearOnEntry, - uint32_t ulBitsToClearOnExit, - uint32_t * pulNotificationValue, - TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -#define xTaskNotifyWait( ulBitsToClearOnEntry, \ - ulBitsToClearOnExit, \ - pulNotificationValue, \ - xTicksToWait ) \ - xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, \ - ( ulBitsToClearOnEntry ), \ - ( ulBitsToClearOnExit ), \ - ( pulNotificationValue ), \ - ( xTicksToWait ) ) -#define xTaskNotifyWaitIndexed( uxIndexToWaitOn, \ - ulBitsToClearOnEntry, \ - ulBitsToClearOnExit, \ - pulNotificationValue, \ - xTicksToWait ) \ - xTaskGenericNotifyWait( ( uxIndexToWaitOn ), \ - ( ulBitsToClearOnEntry ), \ - ( ulBitsToClearOnExit ), \ - ( pulNotificationValue ), \ - ( xTicksToWait ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t - * uxIndexToNotify ); BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify ); - * @endcode - * - * Sends a direct to task notification to a particular index in the target - * task's notification array in a manner similar to giving a counting semaphore. - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * macros to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * xTaskNotifyGiveIndexed() is a helper macro intended for use when task - * notifications are used as light weight and faster binary or counting - * semaphore equivalents. Actual FreeRTOS semaphores are given using the - * xSemaphoreGive() API function, the equivalent action that instead uses a task - * notification is xTaskNotifyGiveIndexed(). - * - * When task notifications are being used as a binary or counting semaphore - * equivalent then the task being notified should wait for the notification - * using the ulTaskNotifyTakeIndexed() API function rather than the - * xTaskNotifyWaitIndexed() API function. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyGive() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling xTaskNotifyGive() is equivalent to calling - * xTaskNotifyGiveIndexed() with the uxIndexToNotify parameter set to 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyGive() - * does not have this parameter and always sends notifications to index 0. - * - * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the - * eAction parameter set to eIncrement - so pdPASS is always returned. - * - * \defgroup xTaskNotifyGiveIndexed xTaskNotifyGiveIndexed - * \ingroup TaskNotifications - */ -#define xTaskNotifyGive( xTaskToNotify ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( 0 ), \ - eIncrement, \ - NULL ) -#define xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( 0 ), \ - eIncrement, \ - NULL ) - -/** - * task. h - * @code{c} - * void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t - * uxIndexToNotify, BaseType_t *pxHigherPriorityTaskWoken ); void - * vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t - * *pxHigherPriorityTaskWoken ); - * @endcode - * - * A version of xTaskNotifyGiveIndexed() that can be called from an interrupt - * service routine (ISR). - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro - * to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * vTaskNotifyGiveIndexedFromISR() is intended for use when task notifications - * are used as light weight and faster binary or counting semaphore equivalents. - * Actual FreeRTOS semaphores are given from an ISR using the - * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses - * a task notification is vTaskNotifyGiveIndexedFromISR(). - * - * When task notifications are being used as a binary or counting semaphore - * equivalent then the task being notified should wait for the notification - * using the ulTaskNotifyTakeIndexed() API function rather than the - * xTaskNotifyWaitIndexed() API function. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyFromISR() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling xTaskNotifyGiveFromISR() is equivalent to calling - * xTaskNotifyGiveIndexedFromISR() with the uxIndexToNotify parameter set to 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. - * xTaskNotifyGiveFromISR() does not have this parameter and always sends - * notifications to index 0. - * - * @param pxHigherPriorityTaskWoken vTaskNotifyGiveFromISR() will set - * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the - * task to which the notification was sent to leave the Blocked state, and the - * unblocked task has a priority higher than the currently running task. If - * vTaskNotifyGiveFromISR() sets this value to pdTRUE then a context switch - * should be requested before the interrupt is exited. How a context switch is - * requested from an ISR is dependent on the port - see the documentation page - * for the port in use. - * - * \defgroup vTaskNotifyGiveIndexedFromISR vTaskNotifyGiveIndexedFromISR - * \ingroup TaskNotifications - */ -void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify, - UBaseType_t uxIndexToNotify, - BaseType_t * pxHigherPriorityTaskWoken ) - PRIVILEGED_FUNCTION; -#define vTaskNotifyGiveFromISR( xTaskToNotify, pxHigherPriorityTaskWoken ) \ - vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( pxHigherPriorityTaskWoken ) ) -#define vTaskNotifyGiveIndexedFromISR( xTaskToNotify, \ - uxIndexToNotify, \ - pxHigherPriorityTaskWoken ) \ - vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( pxHigherPriorityTaskWoken ) ) - -/** - * task. h - * @code{c} - * uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn, BaseType_t - * xClearCountOnExit, TickType_t xTicksToWait ); - * - * uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t - * xTicksToWait ); - * @endcode - * - * Waits for a direct to task notification on a particular index in the calling - * task's notification array in a manner similar to taking a counting semaphore. - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this - * function to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * ulTaskNotifyTakeIndexed() is intended for use when a task notification is - * used as a faster and lighter weight binary or counting semaphore alternative. - * Actual FreeRTOS semaphores are taken using the xSemaphoreTake() API function, - * the equivalent action that instead uses a task notification is - * ulTaskNotifyTakeIndexed(). - * - * When a task is using its notification value as a binary or counting semaphore - * other tasks should send notifications to it using the - * xTaskNotifyGiveIndexed() macro, or xTaskNotifyIndex() function with the - * eAction parameter set to eIncrement. - * - * ulTaskNotifyTakeIndexed() can either clear the task's notification value at - * the array index specified by the uxIndexToWaitOn parameter to zero on exit, - * in which case the notification value acts like a binary semaphore, or - * decrement the notification value on exit, in which case the notification - * value acts like a counting semaphore. - * - * A task can use ulTaskNotifyTakeIndexed() to [optionally] block to wait for - * a notification. The task does not consume any CPU time while it is in the - * Blocked state. - * - * Where as xTaskNotifyWaitIndexed() will return when a notification is pending, - * ulTaskNotifyTakeIndexed() will return when the task's notification value is - * not zero. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. ulTaskNotifyTake() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling ulTaskNotifyTake() is equivalent to calling - * ulTaskNotifyTakeIndexed() with the uxIndexToWaitOn parameter set to 0. - * - * @param uxIndexToWaitOn The index within the calling task's array of - * notification values on which the calling task will wait for a notification to - * be non-zero. uxIndexToWaitOn must be less than - * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyTake() does - * not have this parameter and always waits for notifications on index 0. - * - * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's - * notification value is decremented when the function exits. In this way the - * notification value acts like a counting semaphore. If xClearCountOnExit is - * not pdFALSE then the task's notification value is cleared to zero when the - * function exits. In this way the notification value acts like a binary - * semaphore. - * - * @param xTicksToWait The maximum amount of time that the task should wait in - * the Blocked state for the task's notification value to be greater than zero, - * should the count not already be greater than zero when - * ulTaskNotifyTake() was called. The task will not consume any processing - * time while it is in the Blocked state. This is specified in kernel ticks, - * the macro pdMS_TO_TICKS( value_in_ms ) can be used to convert a time - * specified in milliseconds to a time specified in ticks. - * - * @return The task's notification count before it is either cleared to zero or - * decremented (see the xClearCountOnExit parameter). - * - * \defgroup ulTaskNotifyTakeIndexed ulTaskNotifyTakeIndexed - * \ingroup TaskNotifications - */ -uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, - BaseType_t xClearCountOnExit, - TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -#define ulTaskNotifyTake( xClearCountOnExit, xTicksToWait ) \ - ulTaskGenericNotifyTake( ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( xClearCountOnExit ), \ - ( xTicksToWait ) ) -#define ulTaskNotifyTakeIndexed( uxIndexToWaitOn, \ - xClearCountOnExit, \ - xTicksToWait ) \ - ulTaskGenericNotifyTake( ( uxIndexToWaitOn ), \ - ( xClearCountOnExit ), \ - ( xTicksToWait ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t - * uxIndexToCLear ); - * - * BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * If a notification is sent to an index within the array of notifications then - * the notification at that index is said to be 'pending' until it is read or - * explicitly cleared by the receiving task. xTaskNotifyStateClearIndexed() - * is the function that clears a pending notification without reading the - * notification value. The notification value at the same array index is not - * altered. Set xTask to NULL to clear the notification state of the calling - * task. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyStateClear() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling xTaskNotifyStateClear() is equivalent to calling - * xTaskNotifyStateClearIndexed() with the uxIndexToNotify parameter set to 0. - * - * @param xTask The handle of the RTOS task that will have a notification state - * cleared. Set xTask to NULL to clear a notification state in the calling - * task. To obtain a task's handle create the task using xTaskCreate() and - * make use of the pxCreatedTask parameter, or create the task using - * xTaskCreateStatic() and store the returned value, or use the task's name in - * a call to xTaskGetHandle(). - * - * @param uxIndexToClear The index within the target task's array of - * notification values to act upon. For example, setting uxIndexToClear to 1 - * will clear the state of the notification at index 1 within the array. - * uxIndexToClear must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. - * ulTaskNotifyStateClear() does not have this parameter and always acts on the - * notification at index 0. - * - * @return pdTRUE if the task's notification state was set to - * eNotWaitingNotification, otherwise pdFALSE. - * - * \defgroup xTaskNotifyStateClearIndexed xTaskNotifyStateClearIndexed - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask, - UBaseType_t uxIndexToClear ) - PRIVILEGED_FUNCTION; -#define xTaskNotifyStateClear( xTask ) \ - xTaskGenericNotifyStateClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ) ) -#define xTaskNotifyStateClearIndexed( xTask, uxIndexToClear ) \ - xTaskGenericNotifyStateClear( ( xTask ), ( uxIndexToClear ) ) - -/** - * task. h - * @code{c} - * uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, UBaseType_t - * uxIndexToClear, uint32_t ulBitsToClear ); - * - * uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear - * ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * ulTaskNotifyValueClearIndexed() clears the bits specified by the - * ulBitsToClear bit mask in the notification value at array index - * uxIndexToClear of the task referenced by xTask. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. ulTaskNotifyValueClear() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling ulTaskNotifyValueClear() is equivalent to calling - * ulTaskNotifyValueClearIndexed() with the uxIndexToClear parameter set to 0. - * - * @param xTask The handle of the RTOS task that will have bits in one of its - * notification values cleared. Set xTask to NULL to clear bits in a - * notification value of the calling task. To obtain a task's handle create the - * task using xTaskCreate() and make use of the pxCreatedTask parameter, or - * create the task using xTaskCreateStatic() and store the returned value, or - * use the task's name in a call to xTaskGetHandle(). - * - * @param uxIndexToClear The index within the target task's array of - * notification values in which to clear the bits. uxIndexToClear - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. - * ulTaskNotifyValueClear() does not have this parameter and always clears bits - * in the notification value at index 0. - * - * @param ulBitsToClear Bit mask of the bits to clear in the notification value - * of xTask. Set a bit to 1 to clear the corresponding bits in the task's - * notification value. Set ulBitsToClear to 0xffffffff (UINT_MAX on 32-bit - * architectures) to clear the notification value to 0. Set ulBitsToClear to 0 - * to query the task's notification value without clearing any bits. - * - * - * @return The value of the target task's notification value before the bits - * specified by ulBitsToClear were cleared. - * \defgroup ulTaskNotifyValueClear ulTaskNotifyValueClear - * \ingroup TaskNotifications - */ -uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask, - UBaseType_t uxIndexToClear, - uint32_t ulBitsToClear ) - PRIVILEGED_FUNCTION; -#define ulTaskNotifyValueClear( xTask, ulBitsToClear ) \ - ulTaskGenericNotifyValueClear( ( xTask ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulBitsToClear ) ) -#define ulTaskNotifyValueClearIndexed( xTask, uxIndexToClear, ulBitsToClear ) \ - ulTaskGenericNotifyValueClear( ( xTask ), \ - ( uxIndexToClear ), \ - ( ulBitsToClear ) ) - -/** - * task.h - * @code{c} - * void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ); - * @endcode - * - * Capture the current time for future use with xTaskCheckForTimeOut(). - * - * @param pxTimeOut Pointer to a timeout object into which the current time - * is to be captured. The captured time includes the tick count and the number - * of times the tick count has overflowed since the system first booted. - * \defgroup vTaskSetTimeOutState vTaskSetTimeOutState - * \ingroup TaskCtrl - */ -void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * - * const pxTicksToWait ); - * @endcode - * - * Determines if pxTicksToWait ticks has passed since a time was captured - * using a call to vTaskSetTimeOutState(). The captured time includes the tick - * count and the number of times the tick count has overflowed. - * - * @param pxTimeOut The time status as captured previously using - * vTaskSetTimeOutState. If the timeout has not yet occurred, it is updated - * to reflect the current time status. - * @param pxTicksToWait The number of ticks to check for timeout i.e. if - * pxTicksToWait ticks have passed since pxTimeOut was last updated (either by - * vTaskSetTimeOutState() or xTaskCheckForTimeOut()), the timeout has occurred. - * If the timeout has not occurred, pxTicksToWait is updated to reflect the - * number of remaining ticks. - * - * @return If timeout has occurred, pdTRUE is returned. Otherwise pdFALSE is - * returned and pxTicksToWait is updated to reflect the number of remaining - * ticks. - * - * @see https://www.FreeRTOS.org/xTaskCheckForTimeOut.html - * - * Example Usage: - * @code{c} - * // Driver library function used to receive uxWantedBytes from an Rx buffer - * // that is filled by a UART interrupt. If there are not enough bytes in the - * // Rx buffer then the task enters the Blocked state until it is notified - * that - * // more data has been placed into the buffer. If there is still not enough - * // data then the task re-enters the Blocked state, and - * xTaskCheckForTimeOut() - * // is used to re-calculate the Block time to ensure the total amount of time - * // spent in the Blocked state does not exceed MAX_TIME_TO_WAIT. This - * // continues until either the buffer contains at least uxWantedBytes bytes, - * // or the total amount of time spent in the Blocked state reaches - * // MAX_TIME_TO_WAIT - at which point the task reads however many bytes are - * // available up to a maximum of uxWantedBytes. - * - * size_t xUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes ) - * { - * size_t uxReceived = 0; - * TickType_t xTicksToWait = MAX_TIME_TO_WAIT; - * TimeOut_t xTimeOut; - * - * // Initialize xTimeOut. This records the time at which this function - * // was entered. - * vTaskSetTimeOutState( &xTimeOut ); - * - * // Loop until the buffer contains the wanted number of bytes, or a - * // timeout occurs. - * while( UART_bytes_in_rx_buffer( pxUARTInstance ) < uxWantedBytes ) - * { - * // The buffer didn't contain enough data so this task is going to - * // enter the Blocked state. Adjusting xTicksToWait to account for - * // any time that has been spent in the Blocked state within this - * // function so far to ensure the total amount of time spent in the - * // Blocked state does not exceed MAX_TIME_TO_WAIT. - * if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) != pdFALSE ) - * { - * //Timed out before the wanted number of bytes were available, - * // exit the loop. - * break; - * } - * - * // Wait for a maximum of xTicksToWait ticks to be notified that the - * // receive interrupt has placed more data into the buffer. - * ulTaskNotifyTake( pdTRUE, xTicksToWait ); - * } - * - * // Attempt to read uxWantedBytes from the receive buffer into pucBuffer. - * // The actual number of bytes read (which might be less than - * // uxWantedBytes) is returned. - * uxReceived = UART_read_from_receive_buffer( pxUARTInstance, - * pucBuffer, - * uxWantedBytes ); - * - * return uxReceived; - * } - * @endcode - * \defgroup xTaskCheckForTimeOut xTaskCheckForTimeOut - * \ingroup TaskCtrl - */ -BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, - TickType_t * const pxTicksToWait ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ); - * @endcode - * - * This function corrects the tick count value after the application code has - * held interrupts disabled for an extended period resulting in tick interrupts - * having been missed. - * - * This function is similar to vTaskStepTick(), however, unlike - * vTaskStepTick(), xTaskCatchUpTicks() may move the tick count forward past a - * time at which a task should be removed from the blocked state. That means - * tasks may have to be removed from the blocked state as the tick count is - * moved. - * - * @param xTicksToCatchUp The number of tick interrupts that have been missed - * due to interrupts being disabled. Its value is not computed automatically, - * so must be computed by the application writer. - * - * @return pdTRUE if moving the tick count forward resulted in a task leaving - * the blocked state and a context switch being performed. Otherwise pdFALSE. - * - * \defgroup xTaskCatchUpTicks xTaskCatchUpTicks - * \ingroup TaskCtrl - */ -BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- - * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES - *----------------------------------------------------------*/ - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY - * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS - * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * Called from the real time kernel tick (either preemptive or cooperative), - * this increments the tick count and checks if any tasks that are blocked - * for a finite period required removing from a blocked list and placing on - * a ready list. If a non-zero value is returned then a context switch is - * required because either: - * + A task was removed from a blocked list because its timeout had expired, - * or - * + Time slicing is in use and there is a task of equal priority to the - * currently running task. - */ -BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * Removes the calling task from the ready list and places it both - * on the list of tasks waiting for a particular event, and the - * list of delayed tasks. The task will be removed from both lists - * and replaced on the ready list should either the event occur (and - * there be no higher priority tasks waiting on the same event) or - * the delay period expires. - * - * The 'unordered' version replaces the event list item value with the - * xItemValue value, and inserts the list item at the end of the list. - * - * The 'ordered' version uses the existing event list item value (which is the - * owning task's priority) to insert the list item into the event list in task - * priority order. - * - * @param pxEventList The list containing tasks that are blocked waiting - * for the event to occur. - * - * @param xItemValue The item value to use for the event list item when the - * event list is not ordered by task priority. - * - * @param xTicksToWait The maximum amount of time that the task should wait - * for the event to occur. This is specified in kernel ticks, the constant - * portTICK_PERIOD_MS can be used to convert kernel ticks into a real time - * period. - */ -void vTaskPlaceOnEventList( List_t * const pxEventList, - const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, - const TickType_t xItemValue, - const TickType_t xTicksToWait ) - PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * This function performs nearly the same function as vTaskPlaceOnEventList(). - * The difference being that this function does not permit tasks to block - * indefinitely, whereas vTaskPlaceOnEventList() does. - * - */ -void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, - TickType_t xTicksToWait, - const BaseType_t xWaitIndefinitely ) - PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * Removes a task from both the specified event list and the list of blocked - * tasks, and places it on a ready queue. - * - * xTaskRemoveFromEventList()/vTaskRemoveFromUnorderedEventList() will be called - * if either an event occurs to unblock a task, or the block timeout period - * expires. - * - * xTaskRemoveFromEventList() is used when the event list is in task priority - * order. It removes the list item from the head of the event list as that will - * have the highest priority owning task of all the tasks on the event list. - * vTaskRemoveFromUnorderedEventList() is used when the event list is not - * ordered and the event list items hold something other than the owning tasks - * priority. In this case the event list item value is updated to the value - * passed in the xItemValue parameter. - * - * @return pdTRUE if the task being removed has a higher priority than the task - * making the call, otherwise pdFALSE. - */ -BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) - PRIVILEGED_FUNCTION; -void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, - const TickType_t xItemValue ) - PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY - * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS - * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * Sets the pointer to the current TCB to the TCB of the highest priority task - * that is ready to run. - */ -#if( configNUMBER_OF_CORES == 1 ) -portDONT_DISCARD void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; -#else -portDONT_DISCARD void vTaskSwitchContext( BaseType_t xCoreID ) - PRIVILEGED_FUNCTION; -#endif - -/* - * THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY - * THE EVENT BITS MODULE. - */ -TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION; - -/* - * Return the handle of the calling task. - */ -TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; - -/* - * Return the handle of the task running on specified core. - */ -TaskHandle_t xTaskGetCurrentTaskHandleCPU( BaseType_t xCoreID ) - PRIVILEGED_FUNCTION; - -/* - * Shortcut used by the queue implementation to prevent unnecessary call to - * taskYIELD(); - */ -void vTaskMissedYield( void ) PRIVILEGED_FUNCTION; - -/* - * Returns the scheduler state as taskSCHEDULER_RUNNING, - * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. - */ -BaseType_t xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION; - -/* - * Raises the priority of the mutex holder to that of the calling task should - * the mutex holder have a priority less than the calling task. - */ -BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) - PRIVILEGED_FUNCTION; - -/* - * Set the priority of a task back to its proper priority in the case that it - * inherited a higher priority while it was holding a semaphore. - */ -BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) - PRIVILEGED_FUNCTION; - -/* - * If a higher priority task attempting to obtain a mutex caused a lower - * priority task to inherit the higher priority task's priority - but the higher - * priority task then timed out without obtaining the mutex, then the lower - * priority task will disinherit the priority again - but only down as far as - * the highest priority task that is still waiting for the mutex (if there were - * more than one task waiting for the mutex). - */ -void vTaskPriorityDisinheritAfterTimeout( - TaskHandle_t const pxMutexHolder, - UBaseType_t uxHighestPriorityWaitingTask ) PRIVILEGED_FUNCTION; - -/* - * Get the uxTaskNumber assigned to the task referenced by the xTask parameter. - */ -UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/* - * Set the uxTaskNumber of the task referenced by the xTask parameter to - * uxHandle. - */ -void vTaskSetTaskNumber( TaskHandle_t xTask, - const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION; - -/* - * Only available when configUSE_TICKLESS_IDLE is set to 1. - * If tickless mode is being used, or a low power mode is implemented, then - * the tick interrupt will not execute during idle periods. When this is the - * case, the tick count value maintained by the scheduler needs to be kept up - * to date with the actual execution time by being skipped forward by a time - * equal to the idle period. - */ -void vTaskStepTick( TickType_t xTicksToJump ) PRIVILEGED_FUNCTION; - -/* - * Only available when configUSE_TICKLESS_IDLE is set to 1. - * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port - * specific sleep function to determine if it is ok to proceed with the sleep, - * and if it is ok to proceed, if it is ok to sleep indefinitely. - * - * This function is necessary because portSUPPRESS_TICKS_AND_SLEEP() is only - * called with the scheduler suspended, not from within a critical section. It - * is therefore possible for an interrupt to request a context switch between - * portSUPPRESS_TICKS_AND_SLEEP() and the low power mode actually being - * entered. eTaskConfirmSleepModeStatus() should be called from a short - * critical section between the timer being stopped and the sleep mode being - * entered to ensure it is ok to proceed into the sleep mode. - */ -eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION; - -/* - * For internal use only. Increment the mutex held count when a mutex is - * taken and return the handle of the task that has taken the mutex. - */ -TaskHandle_t pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION; - -/* - * For internal use only. Same as vTaskSetTimeOutState(), but without a - * critical section. - */ -void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) - PRIVILEGED_FUNCTION; - -/* - * For internal use only. Same as portYIELD_WITHIN_API() in single core - * FreeRTOS. For SMP this is not defined by the port. - */ -void vTaskYieldWithinAPI( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when portCRITICAL_NESTING_IN_TCB is set to 1 - * or configNUMBER_OF_CORES is greater than 1. This function can be used in the - * implementation of portENTER_CRITICAL if port wants to maintain critical - * nesting count in TCB in single core FreeRTOS. It should be used in the - * implementation of portENTER_CRITICAL if port is running a multiple core - * FreeRTOS. - */ -void vTaskEnterCritical( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when portCRITICAL_NESTING_IN_TCB is set to 1 - * or configNUMBER_OF_CORES is greater than 1. This function can be used in the - * implementation of portEXIT_CRITICAL if port wants to maintain critical - * nesting count in TCB in single core FreeRTOS. It should be used in the - * implementation of portEXIT_CRITICAL if port is running a multiple core - * FreeRTOS. - */ -void vTaskExitCritical( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when configNUMBER_OF_CORES is greater than 1. - * This function should be used in the implementation of - * portENTER_CRITICAL_FROM_ISR if port is running a multiple core FreeRTOS. - */ -UBaseType_t vTaskEnterCriticalFromISR( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when configNUMBER_OF_CORES is greater than 1. - * This function should be used in the implementation of - * portEXIT_CRITICAL_FROM_ISR if port is running a multiple core FreeRTOS. - */ -void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus ); - -#if( portUSING_MPU_WRAPPERS == 1 ) - -/* - * For internal use only. Get MPU settings associated with a task. - */ -xMPU_SETTINGS * xTaskGetMPUSettings( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -#endif /* portUSING_MPU_WRAPPERS */ - -/* *INDENT-OFF* */ -#ifdef __cplusplus -} -#endif -/* *INDENT-ON* */ -#endif /* INC_TASK_H */ diff --git a/formatting/goodFiles/include/fileWithErrorInclude/goodTask.h b/formatting/goodFiles/include/fileWithErrorInclude/goodTask.h deleted file mode 100644 index 3edd544f..00000000 --- a/formatting/goodFiles/include/fileWithErrorInclude/goodTask.h +++ /dev/null @@ -1,3761 +0,0 @@ -/* - * FreeRTOS Kernel - * 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 - * - */ - -#ifndef INC_TASK_H -#define INC_TASK_H - -#ifndef INC_FREERTOS_H - #error \ - "include FreeRTOS.h must appear in source files before include task.h" -#endif - -#include "list.h" - -/* *INDENT-OFF* */ -#ifdef __cplusplus -extern "C" { -#endif -/* *INDENT-ON* */ - -/*----------------------------------------------------------- - * MACROS AND DEFINITIONS - *----------------------------------------------------------*/ - -/* - * If tskKERNEL_VERSION_NUMBER ends with + it represents the version in - * development after the numbered release. - * - * The tskKERNEL_VERSION_MAJOR, tskKERNEL_VERSION_MINOR, tskKERNEL_VERSION_BUILD - * values will reflect the last released version number. - */ -#define tskKERNEL_VERSION_NUMBER "V10.4.4+" -#define tskKERNEL_VERSION_MAJOR 10 -#define tskKERNEL_VERSION_MINOR 4 -#define tskKERNEL_VERSION_BUILD 4 - -/* MPU region parameters passed in ulParameters - * of MemoryRegion_t struct. */ -#define tskMPU_REGION_READ_ONLY ( 1UL << 0UL ) -#define tskMPU_REGION_READ_WRITE ( 1UL << 1UL ) -#define tskMPU_REGION_EXECUTE_NEVER ( 1UL << 2UL ) -#define tskMPU_REGION_NORMAL_MEMORY ( 1UL << 3UL ) -#define tskMPU_REGION_DEVICE_MEMORY ( 1UL << 4UL ) - -/* MPU region permissions stored in MPU settings to - * authorize access requests. */ -#define tskMPU_READ_PERMISSION ( 1UL << 0UL ) -#define tskMPU_WRITE_PERMISSION ( 1UL << 1UL ) - -/* The direct to task notification feature used to have only a single - * notification per task. Now there is an array of notifications per task that - * is dimensioned by configTASK_NOTIFICATION_ARRAY_ENTRIES. For backward - * compatibility, any use of the original direct to task notification defaults - * to using the first index in the array. */ -#define tskDEFAULT_INDEX_TO_NOTIFY ( 0 ) - -/** - * task. h - * - * Type by which tasks are referenced. For example, a call to xTaskCreate - * returns (via a pointer parameter) an TaskHandle_t variable that can then - * be used as a parameter to vTaskDelete to delete the task. - * - * \defgroup TaskHandle_t TaskHandle_t - * \ingroup Tasks - */ -struct tskTaskControlBlock; /* The old naming convention is used to prevent - breaking kernel aware debuggers. */ -typedef struct tskTaskControlBlock * TaskHandle_t; -typedef const struct tskTaskControlBlock * ConstTaskHandle_t; - -/* - * Defines the prototype to which the application task hook function must - * conform. - */ -typedef BaseType_t ( *TaskHookFunction_t )( void * ); - -/* Task states returned by eTaskGetState. */ -typedef enum -{ - eRunning = 0, /* A task is querying the state of itself, so must be running. - */ - eReady, /* The task being queried is in a ready or pending ready list. */ - eBlocked, /* The task being queried is in the Blocked state. */ - eSuspended, /* The task being queried is in the Suspended state, or is in - the Blocked state with an infinite time out. */ - eDeleted, /* The task being queried has been deleted, but its TCB has not - yet been freed. */ - eInvalid /* Used as an 'invalid state' value. */ -} eTaskState; - -/* Actions that can be performed when vTaskNotify() is called. */ -typedef enum -{ - eNoAction = 0, /* Notify the task without updating its notify value. */ - eSetBits, /* Set bits in the task's notification value. */ - eIncrement, /* Increment the task's notification value. */ - eSetValueWithOverwrite, /* Set the task's notification value to a specific - value even if the previous value has not yet been - read by the task. */ - eSetValueWithoutOverwrite /* Set the task's notification value if the - previous value has been read by the task. */ -} eNotifyAction; - -/* - * Used internally only. - */ -typedef struct xTIME_OUT -{ - BaseType_t xOverflowCount; - TickType_t xTimeOnEntering; -} TimeOut_t; - -/* - * Defines the memory ranges allocated to the task when an MPU is used. - */ -typedef struct xMEMORY_REGION -{ - void * pvBaseAddress; - uint32_t ulLengthInBytes; - uint32_t ulParameters; -} MemoryRegion_t; - -/* - * Parameters required to create an MPU protected task. - */ -typedef struct xTASK_PARAMETERS -{ - TaskFunction_t pvTaskCode; - const char * pcName; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - configSTACK_DEPTH_TYPE usStackDepth; - void * pvParameters; - UBaseType_t uxPriority; - StackType_t * puxStackBuffer; - MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ]; -#if( ( portUSING_MPU_WRAPPERS == 1 ) && \ - ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - StaticTask_t * const pxTaskBuffer; -#endif -} TaskParameters_t; - -/* Used with the uxTaskGetSystemState() function to return the state of each - * task in the system. */ -typedef struct xTASK_STATUS -{ - TaskHandle_t xHandle; /* The handle of the task to which the rest of the - information in the structure relates. */ - const char * pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - UBaseType_t xTaskNumber; /* A number unique to the task. */ - eTaskState eCurrentState; /* The state in which the task existed when the - structure was populated. */ - UBaseType_t uxCurrentPriority; /* The priority at which the task was running - (may be inherited) when the structure was - populated. */ - UBaseType_t uxBasePriority; /* The priority to which the task will return if - the task's current priority has been - inherited to avoid unbounded priority - inversion when obtaining a mutex. Only valid - if configUSE_MUTEXES is defined as 1 in - FreeRTOSConfig.h. */ - configRUN_TIME_COUNTER_TYPE - ulRunTimeCounter; /* The total run time - allocated to the task so - far, as defined by the run - time stats clock. See - https://www.FreeRTOS.org/rtos-run-time-stats.html. - Only valid when - configGENERATE_RUN_TIME_STATS - is defined as 1 in - FreeRTOSConfig.h. */ - StackType_t * pxStackBase; /* Points to the lowest address of the task's - stack area. */ -#if( ( portSTACK_GROWTH > 0 ) && ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) - StackType_t * pxTopOfStack; /* Points to the top address of the task's stack - area. */ - StackType_t * pxEndOfStack; /* Points to the end address of the task's stack - area. */ -#endif - configSTACK_DEPTH_TYPE usStackHighWaterMark; /* The minimum amount of stack - space that has remained for - the task since the task was - created. The closer this - value is to zero the closer - the task has come to - overflowing its stack. */ -#if( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - UBaseType_t uxCoreAffinityMask; /* The core affinity mask for the task */ -#endif -} TaskStatus_t; - -/* Possible return values for eTaskConfirmSleepModeStatus(). */ -typedef enum -{ - eAbortSleep = 0, /* A task has been made ready or a context switch pended - since portSUPPRESS_TICKS_AND_SLEEP() was called - abort - entering a sleep mode. */ - eStandardSleep, /* Enter a sleep mode that will not last any longer than the - expected idle time. */ -#if( INCLUDE_vTaskSuspend == 1 ) - eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe - to enter a sleep mode that can only be exited by - an external interrupt. */ -#endif /* INCLUDE_vTaskSuspend */ -} eSleepModeStatus; - -/** - * Defines the priority used by the idle task. This must not be modified. - * - * \ingroup TaskUtils - */ -#define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U ) - -/** - * Defines affinity to all available cores. - * - * \ingroup TaskUtils - */ -#define tskNO_AFFINITY ( ( UBaseType_t ) -1 ) - -/** - * task. h - * - * Macro for forcing a context switch. - * - * \defgroup taskYIELD taskYIELD - * \ingroup SchedulerControl - */ -#define taskYIELD() portYIELD() - -/** - * task. h - * - * Macro to mark the start of a critical code region. Preemptive context - * switches cannot occur when in a critical region. - * - * NOTE: This may alter the stack (depending on the portable implementation) - * so must be used with care! - * - * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL - * \ingroup SchedulerControl - */ -#define taskENTER_CRITICAL() portENTER_CRITICAL() -#if( configNUMBER_OF_CORES == 1 ) - #define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() -#else - #define taskENTER_CRITICAL_FROM_ISR() portENTER_CRITICAL_FROM_ISR() -#endif - -/** - * task. h - * - * Macro to mark the end of a critical code region. Preemptive context - * switches cannot occur when in a critical region. - * - * NOTE: This may alter the stack (depending on the portable implementation) - * so must be used with care! - * - * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL - * \ingroup SchedulerControl - */ -#define taskEXIT_CRITICAL() portEXIT_CRITICAL() -#if( configNUMBER_OF_CORES == 1 ) - #define taskEXIT_CRITICAL_FROM_ISR( x ) \ - portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) -#else - #define taskEXIT_CRITICAL_FROM_ISR( x ) portEXIT_CRITICAL_FROM_ISR( x ) -#endif - -/** - * task. h - * - * Macro to disable all maskable interrupts. - * - * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS - * \ingroup SchedulerControl - */ -#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() - -/** - * task. h - * - * Macro to enable microcontroller interrupts. - * - * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS - * \ingroup SchedulerControl - */ -#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() - -/* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is - * 0 to generate more optimal code when configASSERT() is defined as the - * constant is used in assert() statements. */ -#define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 ) -#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 ) -#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 ) - -/* Checks if core ID is valid. */ -#define taskVALID_CORE_ID( xCoreID ) \ - ( ( ( ( ( BaseType_t ) 0 <= ( xCoreID ) ) && \ - ( ( xCoreID ) < ( BaseType_t ) configNUMBER_OF_CORES ) ) ) \ - ? ( pdTRUE ) \ - : ( pdFALSE ) ) - -/*----------------------------------------------------------- - * TASK CREATION API - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * BaseType_t xTaskCreate( - * TaskFunction_t pxTaskCode, - * const char *pcName, - * configSTACK_DEPTH_TYPE usStackDepth, - * void *pvParameters, - * UBaseType_t uxPriority, - * TaskHandle_t *pxCreatedTask - * ); - * @endcode - * - * Create a new task and add it to the list of tasks that are ready to run. - * - * Internally, within the FreeRTOS implementation, tasks use two blocks of - * memory. The first block is used to hold the task's data structures. The - * second block is used by the task as its stack. If a task is created using - * xTaskCreate() then both blocks of memory are automatically dynamically - * allocated inside the xTaskCreate() function. (see - * https://www.FreeRTOS.org/a00111.html). If a task is created using - * xTaskCreateStatic() then the application writer must provide the required - * memory. xTaskCreateStatic() therefore allows a task to be created without - * using any dynamic memory allocation. - * - * See xTaskCreateStatic() for a version that does not use any dynamic memory - * allocation. - * - * xTaskCreate() can only be used to create a task that has unrestricted - * access to the entire microcontroller memory map. Systems that include MPU - * support can alternatively create an MPU constrained task using - * xTaskCreateRestricted(). - * - * @param pxTaskCode Pointer to the task entry function. Tasks - * must be implemented to never return (i.e. continuous loop). - * - * @param pcName A descriptive name for the task. This is mainly used to - * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - - * default is 16. - * - * @param usStackDepth The size of the task stack specified as the number of - * variables the stack can hold - not the number of bytes. For example, if - * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes - * will be allocated for stack storage. - * - * @param pvParameters Pointer that will be used as the parameter for the task - * being created. - * - * @param uxPriority The priority at which the task should run. Systems that - * include MPU support can optionally create tasks in a privileged (system) - * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For - * example, to create a privileged task at priority 2 the uxPriority parameter - * should be set to ( 2 | portPRIVILEGE_BIT ). - * - * @param pxCreatedTask Used to pass back a handle by which the created task - * can be referenced. - * - * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file projdefs.h - * - * Example usage: - * @code{c} - * // Task to be created. - * void vTaskCode( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * } - * } - * - * // Function that creates a task. - * void vOtherFunction( void ) - * { - * static uint8_t ucParameterToPass; - * TaskHandle_t xHandle = NULL; - * - * // Create the task, storing the handle. Note that the passed parameter - * ucParameterToPass - * // must exist for the lifetime of the task, so in this case is declared - * static. If it was just an - * // an automatic stack variable it might no longer exist, or at least have - * been corrupted, by the time - * // the new task attempts to access it. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, - * tskIDLE_PRIORITY, &xHandle ); configASSERT( xHandle ); - * - * // Use the handle to delete the task. - * if( xHandle != NULL ) - * { - * vTaskDelete( xHandle ); - * } - * } - * @endcode - * \defgroup xTaskCreate xTaskCreate - * \ingroup Tasks - */ -#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 ) PRIVILEGED_FUNCTION; -#endif - -#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && \ - ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) -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 ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, - * const char *pcName, - * uint32_t ulStackDepth, - * void *pvParameters, - * UBaseType_t uxPriority, - * StackType_t *puxStackBuffer, - * StaticTask_t *pxTaskBuffer ); - * @endcode - * - * Create a new task and add it to the list of tasks that are ready to run. - * - * Internally, within the FreeRTOS implementation, tasks use two blocks of - * memory. The first block is used to hold the task's data structures. The - * second block is used by the task as its stack. If a task is created using - * xTaskCreate() then both blocks of memory are automatically dynamically - * allocated inside the xTaskCreate() function. (see - * https://www.FreeRTOS.org/a00111.html). If a task is created using - * xTaskCreateStatic() then the application writer must provide the required - * memory. xTaskCreateStatic() therefore allows a task to be created without - * using any dynamic memory allocation. - * - * @param pxTaskCode Pointer to the task entry function. Tasks - * must be implemented to never return (i.e. continuous loop). - * - * @param pcName A descriptive name for the task. This is mainly used to - * facilitate debugging. The maximum length of the string is defined by - * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h. - * - * @param ulStackDepth The size of the task stack specified as the number of - * variables the stack can hold - not the number of bytes. For example, if - * the stack is 32-bits wide and ulStackDepth is defined as 100 then 400 bytes - * will be allocated for stack storage. - * - * @param pvParameters Pointer that will be used as the parameter for the task - * being created. - * - * @param uxPriority The priority at which the task will run. - * - * @param puxStackBuffer Must point to a StackType_t array that has at least - * ulStackDepth indexes - the array will then be used as the task's stack, - * removing the need for the stack to be allocated dynamically. - * - * @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will - * then be used to hold the task's data structures, removing the need for the - * memory to be allocated dynamically. - * - * @return If neither puxStackBuffer nor pxTaskBuffer are NULL, then the task - * will be created and a handle to the created task is returned. If either - * puxStackBuffer or pxTaskBuffer are NULL then the task will not be created and - * NULL is returned. - * - * Example usage: - * @code{c} - * - * // Dimensions of the buffer that the task being created will use as its - stack. - * // NOTE: This is the number of words the stack will hold, not the number of - * // bytes. For example, if each stack item is 32-bits, and this is set to - 100, - * // then 400 bytes (100 * 32-bits) will be allocated. - #define STACK_SIZE 200 - * - * // Structure that will hold the TCB of the task being created. - * StaticTask_t xTaskBuffer; - * - * // Buffer that the task being created will use as its stack. Note this is - * // an array of StackType_t variables. The size of StackType_t is dependent - on - * // the RTOS port. - * StackType_t xStack[ STACK_SIZE ]; - * - * // Function that implements the task being created. - * void vTaskCode( void * pvParameters ) - * { - * // The parameter value is expected to be 1 as 1 is passed in the - * // pvParameters value in the call to xTaskCreateStatic(). - * configASSERT( ( uint32_t ) pvParameters == 1UL ); - * - * for( ;; ) - * { - * // Task code goes here. - * } - * } - * - * // Function that creates a task. - * void vOtherFunction( void ) - * { - * TaskHandle_t xHandle = NULL; - * - * // Create the task without using any dynamic memory allocation. - * xHandle = xTaskCreateStatic( - * vTaskCode, // Function that implements the task. - * "NAME", // Text name for the task. - * STACK_SIZE, // Stack size in words, not bytes. - * ( void * ) 1, // Parameter passed into the task. - * tskIDLE_PRIORITY,// Priority at which the task is created. - * xStack, // Array to use as the task's stack. - * &xTaskBuffer ); // Variable to hold the task's data - structure. - * - * // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have - * // been created, and xHandle will be the task's handle. Use the handle - * // to suspend the task. - * vTaskSuspend( xHandle ); - * } - * @endcode - * \defgroup xTaskCreateStatic xTaskCreateStatic - * \ingroup Tasks - */ -#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 ) PRIVILEGED_FUNCTION; -#endif /* configSUPPORT_STATIC_ALLOCATION */ - -#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && \ - ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) -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 ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, - * TaskHandle_t *pxCreatedTask ); - * @endcode - * - * Only available when configSUPPORT_DYNAMIC_ALLOCATION is set to 1. - * - * xTaskCreateRestricted() should only be used in systems that include an MPU - * implementation. - * - * Create a new task and add it to the list of tasks that are ready to run. - * The function parameters define the memory regions and associated access - * permissions allocated to the task. - * - * See xTaskCreateRestrictedStatic() for a version that does not use any - * dynamic memory allocation. - * - * @param pxTaskDefinition Pointer to a structure that contains a member - * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API - * documentation) plus an optional stack buffer and the memory region - * definitions. - * - * @param pxCreatedTask Used to pass back a handle by which the created task - * can be referenced. - * - * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file projdefs.h - * - * Example usage: - * @code{c} - * // Create an TaskParameters_t structure that defines the task to be created. - * static const TaskParameters_t xCheckTaskParameters = - * { - * vATask, // pvTaskCode - the function that implements the task. - * "ATask", // pcName - just a text name for the task to assist debugging. - * 100, // usStackDepth - the stack size DEFINED IN WORDS. - * NULL, // pvParameters - passed into the task function as the function - * parameters. ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set - * the portPRIVILEGE_BIT if the task should run in a privileged state. - * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack. - * - * // xRegions - Allocate up to three separate memory regions for access by - * // the task, with appropriate access permissions. Different processors have - * // different memory alignment requirements - refer to the FreeRTOS - * documentation - * // for full information. - * { - * // Base address Length Parameters - * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE }, - * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY }, - * { cPrivilegedOnlyAccessArray, 128, - * portMPU_REGION_PRIVILEGED_READ_WRITE } - * } - * }; - * - * int main( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task from the const structure defined above. The task handle - * // is requested (the second parameter is not NULL) but in this case just for - * // demonstration purposes as its not actually used. - * xTaskCreateRestricted( &xRegTest1Parameters, &xHandle ); - * - * // Start the scheduler. - * vTaskStartScheduler(); - * - * // Will only get here if there was insufficient memory to create the idle - * // and/or timer task. - * for( ;; ); - * } - * @endcode - * \defgroup xTaskCreateRestricted xTaskCreateRestricted - * \ingroup Tasks - */ -#if( portUSING_MPU_WRAPPERS == 1 ) -BaseType_t xTaskCreateRestricted( - const TaskParameters_t * const pxTaskDefinition, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configNUMBER_OF_CORES > 1 ) && \ - ( configUSE_CORE_AFFINITY == 1 ) ) -BaseType_t xTaskCreateRestrictedAffinitySet( - const TaskParameters_t * const pxTaskDefinition, - UBaseType_t uxCoreAffinityMask, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * BaseType_t xTaskCreateRestrictedStatic( TaskParameters_t *pxTaskDefinition, - * TaskHandle_t *pxCreatedTask ); - * @endcode - * - * Only available when configSUPPORT_STATIC_ALLOCATION is set to 1. - * - * xTaskCreateRestrictedStatic() should only be used in systems that include an - * MPU implementation. - * - * Internally, within the FreeRTOS implementation, tasks use two blocks of - * memory. The first block is used to hold the task's data structures. The - * second block is used by the task as its stack. If a task is created using - * xTaskCreateRestricted() then the stack is provided by the application writer, - * and the memory used to hold the task's data structure is automatically - * dynamically allocated inside the xTaskCreateRestricted() function. If a task - * is created using xTaskCreateRestrictedStatic() then the application writer - * must provide the memory used to hold the task's data structures too. - * xTaskCreateRestrictedStatic() therefore allows a memory protected task to be - * created without using any dynamic memory allocation. - * - * @param pxTaskDefinition Pointer to a structure that contains a member - * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API - * documentation) plus an optional stack buffer and the memory region - * definitions. If configSUPPORT_STATIC_ALLOCATION is set to 1 the structure - * contains an additional member, which is used to point to a variable of type - * StaticTask_t - which is then used to hold the task's data structure. - * - * @param pxCreatedTask Used to pass back a handle by which the created task - * can be referenced. - * - * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file projdefs.h - * - * Example usage: - * @code{c} - * // Create an TaskParameters_t structure that defines the task to be created. - * // The StaticTask_t variable is only included in the structure when - * // configSUPPORT_STATIC_ALLOCATION is set to 1. The PRIVILEGED_DATA macro - * can - * // be used to force the variable into the RTOS kernel's privileged data area. - * static PRIVILEGED_DATA StaticTask_t xTaskBuffer; - * static const TaskParameters_t xCheckTaskParameters = - * { - * vATask, // pvTaskCode - the function that implements the task. - * "ATask", // pcName - just a text name for the task to assist debugging. - * 100, // usStackDepth - the stack size DEFINED IN WORDS. - * NULL, // pvParameters - passed into the task function as the function - * parameters. ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set - * the portPRIVILEGE_BIT if the task should run in a privileged state. - * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack. - * - * // xRegions - Allocate up to three separate memory regions for access by - * // the task, with appropriate access permissions. Different processors have - * // different memory alignment requirements - refer to the FreeRTOS - * documentation - * // for full information. - * { - * // Base address Length Parameters - * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE }, - * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY }, - * { cPrivilegedOnlyAccessArray, 128, - * portMPU_REGION_PRIVILEGED_READ_WRITE } - * } - * - * &xTaskBuffer; // Holds the task's data structure. - * }; - * - * int main( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task from the const structure defined above. The task handle - * // is requested (the second parameter is not NULL) but in this case just for - * // demonstration purposes as its not actually used. - * xTaskCreateRestrictedStatic( &xRegTest1Parameters, &xHandle ); - * - * // Start the scheduler. - * vTaskStartScheduler(); - * - * // Will only get here if there was insufficient memory to create the idle - * // and/or timer task. - * for( ;; ); - * } - * @endcode - * \defgroup xTaskCreateRestrictedStatic xTaskCreateRestrictedStatic - * \ingroup Tasks - */ -#if( ( portUSING_MPU_WRAPPERS == 1 ) && \ - ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) -BaseType_t xTaskCreateRestrictedStatic( - const TaskParameters_t * const pxTaskDefinition, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -#if( ( portUSING_MPU_WRAPPERS == 1 ) && \ - ( configSUPPORT_STATIC_ALLOCATION == 1 ) && \ - ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) -BaseType_t xTaskCreateRestrictedStaticAffinitySet( - const TaskParameters_t * const pxTaskDefinition, - UBaseType_t uxCoreAffinityMask, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * - * const pxRegions ); - * @endcode - * - * Memory regions are assigned to a restricted task when the task is created by - * a call to xTaskCreateRestricted(). These regions can be redefined using - * vTaskAllocateMPURegions(). - * - * @param xTask The handle of the task being updated. - * - * @param[in] pxRegions A pointer to a MemoryRegion_t structure that contains - * the new memory region definitions. - * - * Example usage: - * @code{c} - * // Define an array of MemoryRegion_t structures that configures an MPU region - * // allowing read/write access for 1024 bytes starting at the beginning of the - * // ucOneKByte array. The other two of the maximum 3 definable regions are - * // unused so set to zero. - * static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] = - * { - * // Base address Length Parameters - * { ucOneKByte, 1024, portMPU_REGION_READ_WRITE }, - * { 0, 0, 0 }, - * { 0, 0, 0 } - * }; - * - * void vATask( void *pvParameters ) - * { - * // This task was created such that it has access to certain regions of - * // memory as defined by the MPU configuration. At some point it is - * // desired that these MPU regions are replaced with that defined in the - * // xAltRegions const struct above. Use a call to vTaskAllocateMPURegions() - * // for this purpose. NULL is used as the task handle to indicate that this - * // function should modify the MPU regions of the calling task. - * vTaskAllocateMPURegions( NULL, xAltRegions ); - * - * // Now the task can continue its function, but from this point on can only - * // access its stack and the ucOneKByte array (unless any other statically - * // defined or shared regions have been declared elsewhere). - * } - * @endcode - * \defgroup vTaskAllocateMPURegions vTaskAllocateMPURegions - * \ingroup Tasks - */ -void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, - const MemoryRegion_t * const pxRegions ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskDelete( TaskHandle_t xTaskToDelete ); - * @endcode - * - * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Remove a task from the RTOS real time kernel's management. The task being - * deleted will be removed from all ready, blocked, suspended and event lists. - * - * NOTE: The idle task is responsible for freeing the kernel allocated - * memory from tasks that have been deleted. It is therefore important that - * the idle task is not starved of microcontroller processing time if your - * application makes any calls to vTaskDelete (). Memory allocated by the - * task code is not automatically freed, and should be freed before the task - * is deleted. - * - * See the demo application file death.c for sample code that utilises - * vTaskDelete (). - * - * @param xTaskToDelete The handle of the task to be deleted. Passing NULL will - * cause the calling task to be deleted. - * - * Example usage: - * @code{c} - * void vOtherFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create the task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // Use the handle to delete the task. - * vTaskDelete( xHandle ); - * } - * @endcode - * \defgroup vTaskDelete vTaskDelete - * \ingroup Tasks - */ -void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- - * TASK CONTROL API - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * void vTaskDelay( const TickType_t xTicksToDelay ); - * @endcode - * - * Delay a task for a given number of ticks. The actual time that the - * task remains blocked depends on the tick rate. The constant - * portTICK_PERIOD_MS can be used to calculate real time from the tick - * rate - with the resolution of one tick period. - * - * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * - * vTaskDelay() specifies a time at which the task wishes to unblock relative to - * the time at which vTaskDelay() is called. For example, specifying a block - * period of 100 ticks will cause the task to unblock 100 ticks after - * vTaskDelay() is called. vTaskDelay() does not therefore provide a good - * method of controlling the frequency of a periodic task as the path taken - * through the code, as well as other task and interrupt activity, will affect - * the frequency at which vTaskDelay() gets called and therefore the time at - * which the task next executes. See xTaskDelayUntil() for an alternative API - * function designed to facilitate fixed frequency execution. It does this by - * specifying an absolute time (rather than a relative time) at which the - * calling task should unblock. - * - * @param xTicksToDelay The amount of time, in tick periods, that - * the calling task should block. - * - * Example usage: - * - * void vTaskFunction( void * pvParameters ) - * { - * // Block for 500ms. - * const TickType_t xDelay = 500 / portTICK_PERIOD_MS; - * - * for( ;; ) - * { - * // Simply toggle the LED every 500ms, blocking between each toggle. - * vToggleLED(); - * vTaskDelay( xDelay ); - * } - * } - * - * \defgroup vTaskDelay vTaskDelay - * \ingroup TaskCtrl - */ -void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * BaseType_t xTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t - * xTimeIncrement ); - * @endcode - * - * INCLUDE_xTaskDelayUntil must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Delay a task until a specified time. This function can be used by periodic - * tasks to ensure a constant execution frequency. - * - * This function differs from vTaskDelay () in one important aspect: vTaskDelay - * () will cause a task to block for the specified number of ticks from the time - * vTaskDelay () is called. It is therefore difficult to use vTaskDelay () by - * itself to generate a fixed execution frequency as the time between a task - * starting to execute and that task calling vTaskDelay () may not be fixed [the - * task may take a different path though the code between calls, or may get - * interrupted or preempted a different number of times each time it executes]. - * - * Whereas vTaskDelay () specifies a wake time relative to the time at which the - * function is called, xTaskDelayUntil () specifies the absolute (exact) time at - * which it wishes to unblock. - * - * The macro pdMS_TO_TICKS() can be used to calculate the number of ticks from a - * time specified in milliseconds with a resolution of one tick period. - * - * @param pxPreviousWakeTime Pointer to a variable that holds the time at which - * the task was last unblocked. The variable must be initialised with the - * current time prior to its first use (see the example below). Following this - * the variable is automatically updated within xTaskDelayUntil (). - * - * @param xTimeIncrement The cycle time period. The task will be unblocked at - * time *pxPreviousWakeTime + xTimeIncrement. Calling xTaskDelayUntil with the - * same xTimeIncrement parameter value will cause the task to execute with - * a fixed interface period. - * - * @return Value which can be used to check whether the task was actually - * delayed. Will be pdTRUE if the task way delayed and pdFALSE otherwise. A - * task will not be delayed if the next expected wake time is in the past. - * - * Example usage: - * @code{c} - * // Perform an action every 10 ticks. - * void vTaskFunction( void * pvParameters ) - * { - * TickType_t xLastWakeTime; - * const TickType_t xFrequency = 10; - * BaseType_t xWasDelayed; - * - * // Initialise the xLastWakeTime variable with the current time. - * xLastWakeTime = xTaskGetTickCount (); - * for( ;; ) - * { - * // Wait for the next cycle. - * xWasDelayed = xTaskDelayUntil( &xLastWakeTime, xFrequency ); - * - * // Perform action here. xWasDelayed value can be used to determine - * // whether a deadline was missed if the code here took too long. - * } - * } - * @endcode - * \defgroup xTaskDelayUntil xTaskDelayUntil - * \ingroup TaskCtrl - */ -BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, - const TickType_t xTimeIncrement ) - PRIVILEGED_FUNCTION; - -/* - * vTaskDelayUntil() is the older version of xTaskDelayUntil() and does not - * return a value. - */ -#define vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ) \ - do \ - { \ - ( void ) xTaskDelayUntil( ( pxPreviousWakeTime ), \ - ( xTimeIncrement ) ); \ - } while( 0 ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskAbortDelay( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this - * function to be available. - * - * A task will enter the Blocked state when it is waiting for an event. The - * event it is waiting for can be a temporal event (waiting for a time), such - * as when vTaskDelay() is called, or an event on an object, such as when - * xQueueReceive() or ulTaskNotifyTake() is called. If the handle of a task - * that is in the Blocked state is used in a call to xTaskAbortDelay() then the - * task will leave the Blocked state, and return from whichever function call - * placed the task into the Blocked state. - * - * There is no 'FromISR' version of this function as an interrupt would need to - * know which object a task was blocked on in order to know which actions to - * take. For example, if the task was blocked on a queue the interrupt handler - * would then need to know if the queue was locked. - * - * @param xTask The handle of the task to remove from the Blocked state. - * - * @return If the task referenced by xTask was not in the Blocked state then - * pdFAIL is returned. Otherwise pdPASS is returned. - * - * \defgroup xTaskAbortDelay xTaskAbortDelay - * \ingroup TaskCtrl - */ -BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Obtain the priority of any task. - * - * @param xTask Handle of the task to be queried. Passing a NULL - * handle results in the priority of the calling task being returned. - * - * @return The priority of xTask. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to obtain the priority of the created task. - * // It was created with tskIDLE_PRIORITY, but may have changed - * // it itself. - * if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY ) - * { - * // The task has changed it's priority. - * } - * - * // ... - * - * // Is our priority higher than the created task? - * if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) ) - * { - * // Our priority (obtained using NULL handle) is higher. - * } - * } - * @endcode - * \defgroup uxTaskPriorityGet uxTaskPriorityGet - * \ingroup TaskCtrl - */ -UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ); - * @endcode - * - * A version of uxTaskPriorityGet() that can be used from an ISR. - */ -UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * eTaskState eTaskGetState( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Obtain the state of any task. States are encoded by the eTaskState - * enumerated type. - * - * @param xTask Handle of the task to be queried. - * - * @return The state of xTask at the time the function was called. Note the - * state of the task might change between the function being called, and the - * functions return value being tested by the calling task. - */ -eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t - * xGetFreeStackSpace, eTaskState eState ); - * @endcode - * - * configUSE_TRACE_FACILITY must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Populates a TaskStatus_t structure with information about a task. - * - * @param xTask Handle of the task being queried. If xTask is NULL then - * information will be returned about the calling task. - * - * @param pxTaskStatus A pointer to the TaskStatus_t structure that will be - * filled with information about the task referenced by the handle passed using - * the xTask parameter. - * - * @param xGetFreeStackSpace The TaskStatus_t structure contains a member to - * report the stack high water mark of the task being queried. Calculating the - * stack high water mark takes a relatively long time, and can make the system - * temporarily unresponsive - so the xGetFreeStackSpace parameter is provided to - * allow the high water mark checking to be skipped. The high watermark value - * will only be written to the TaskStatus_t structure if xGetFreeStackSpace is - * not set to pdFALSE; - * - * @param eState The TaskStatus_t structure contains a member to report the - * state of the task being queried. Obtaining the task state is not as fast as - * a simple assignment - so the eState parameter is provided to allow the state - * information to be omitted from the TaskStatus_t structure. To obtain state - * information then set eState to eInvalid - otherwise the value passed in - * eState will be reported as the task state in the TaskStatus_t structure. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * TaskStatus_t xTaskDetails; - * - * // Obtain the handle of a task from its name. - * xHandle = xTaskGetHandle( "Task_Name" ); - * - * // Check the handle is not NULL. - * configASSERT( xHandle ); - * - * // Use the handle to obtain further information about the task. - * vTaskGetInfo( xHandle, - * &xTaskDetails, - * pdTRUE, // Include the high water mark in xTaskDetails. - * eInvalid ); // Include the task state in xTaskDetails. - * } - * @endcode - * \defgroup vTaskGetInfo vTaskGetInfo - * \ingroup TaskCtrl - */ -void vTaskGetInfo( TaskHandle_t xTask, - TaskStatus_t * pxTaskStatus, - BaseType_t xGetFreeStackSpace, - eTaskState eState ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ); - * @endcode - * - * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Set the priority of any task. - * - * A context switch will occur before the function returns if the priority - * being set is higher than the currently executing task. - * - * @param xTask Handle to the task for which the priority is being set. - * Passing a NULL handle results in the priority of the calling task being set. - * - * @param uxNewPriority The priority to which the task will be set. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to raise the priority of the created task. - * vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 ); - * - * // ... - * - * // Use a NULL handle to raise our priority to the same value. - * vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 ); - * } - * @endcode - * \defgroup vTaskPrioritySet vTaskPrioritySet - * \ingroup TaskCtrl - */ -void vTaskPrioritySet( TaskHandle_t xTask, - UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskSuspend( TaskHandle_t xTaskToSuspend ); - * @endcode - * - * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Suspend any task. When suspended a task will never get any microcontroller - * processing time, no matter what its priority. - * - * Calls to vTaskSuspend are not accumulative - - * i.e. calling vTaskSuspend () twice on the same task still only requires one - * call to vTaskResume () to ready the suspended task. - * - * @param xTaskToSuspend Handle to the task being suspended. Passing a NULL - * handle will cause the calling task to be suspended. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to suspend the created task. - * vTaskSuspend( xHandle ); - * - * // ... - * - * // The created task will not run during this period, unless - * // another task calls vTaskResume( xHandle ). - * - * //... - * - * - * // Suspend ourselves. - * vTaskSuspend( NULL ); - * - * // We cannot get here unless another task calls vTaskResume - * // with our handle as the parameter. - * } - * @endcode - * \defgroup vTaskSuspend vTaskSuspend - * \ingroup TaskCtrl - */ -void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskResume( TaskHandle_t xTaskToResume ); - * @endcode - * - * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Resumes a suspended task. - * - * A task that has been suspended by one or more calls to vTaskSuspend () - * will be made available for running again by a single call to - * vTaskResume (). - * - * @param xTaskToResume Handle to the task being readied. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to suspend the created task. - * vTaskSuspend( xHandle ); - * - * // ... - * - * // The created task will not run during this period, unless - * // another task calls vTaskResume( xHandle ). - * - * //... - * - * - * // Resume the suspended task ourselves. - * vTaskResume( xHandle ); - * - * // The created task will once again get microcontroller processing - * // time in accordance with its priority within the system. - * } - * @endcode - * \defgroup vTaskResume vTaskResume - * \ingroup TaskCtrl - */ -void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void xTaskResumeFromISR( TaskHandle_t xTaskToResume ); - * @endcode - * - * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * An implementation of vTaskResume() that can be called from within an ISR. - * - * A task that has been suspended by one or more calls to vTaskSuspend () - * will be made available for running again by a single call to - * xTaskResumeFromISR (). - * - * xTaskResumeFromISR() should not be used to synchronise a task with an - * interrupt if there is a chance that the interrupt could arrive prior to the - * task being suspended - as this can lead to interrupts being missed. Use of a - * semaphore as a synchronisation mechanism would avoid this eventuality. - * - * @param xTaskToResume Handle to the task being readied. - * - * @return pdTRUE if resuming the task should result in a context switch, - * otherwise pdFALSE. This is used by the ISR to determine if a context switch - * may be required following the ISR. - * - * \defgroup vTaskResumeFromISR vTaskResumeFromISR - * \ingroup TaskCtrl - */ -BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; - -#if( configUSE_CORE_AFFINITY == 1 ) - -/** - * @brief Sets the core affinity mask for a task. - * - * It sets the cores on which a task can run. configUSE_CORE_AFFINITY must - * be defined as 1 for this function to be available. - * - * @param xTask The handle of the task to set the core affinity mask for. - * Passing NULL will set the core affinity mask for the calling task. - * - * @param uxCoreAffinityMask A bitwise value that indicates the cores on - * which the task can run. Cores are numbered from 0 to configNUMBER_OF_CORES - * - 1. For example, to ensure that a task can run on core 0 and core 1, set - * uxCoreAffinityMask to 0x03. - * - * Example usage: - * - * // The function that creates task. - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * UBaseType_t uxCoreAffinityMask; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &( - * xHandle ) ); - * - * // Define the core affinity mask such that this task can only run - * // on core 0 and core 2. - * uxCoreAffinityMask = ( ( 1 << 0 ) | ( 1 << 2 ) ); - * - * //Set the core affinity mask for the task. - * vTaskCoreAffinitySet( xHandle, uxCoreAffinityMask ); - * } - */ -void vTaskCoreAffinitySet( const TaskHandle_t xTask, - UBaseType_t uxCoreAffinityMask ); -#endif - -#if( configUSE_CORE_AFFINITY == 1 ) - -/** - * @brief Gets the core affinity mask for a task. - * - * configUSE_CORE_AFFINITY must be defined as 1 for this function to be - * available. - * - * @param xTask The handle of the task to get the core affinity mask for. - * Passing NULL will get the core affinity mask for the calling task. - * - * @return The core affinity mask which is a bitwise value that indicates - * the cores on which a task can run. Cores are numbered from 0 to - * configNUMBER_OF_CORES - 1. For example, if a task can run on core 0 and core - * 1, the core affinity mask is 0x03. - * - * Example usage: - * - * // Task handle of the networking task - it is populated elsewhere. - * TaskHandle_t xNetworkingTaskHandle; - * - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * UBaseType_t uxNetworkingCoreAffinityMask; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &( - * xHandle ) ); - * - * //Get the core affinity mask for the networking task. - * uxNetworkingCoreAffinityMask = vTaskCoreAffinityGet( - * xNetworkingTaskHandle ); - * - * // Here is a hypothetical scenario, just for the example. Assume that we - * // have 2 cores - Core 0 and core 1. We want to pin the application task - * to - * // the core different than the networking task to ensure that the - * // application task does not interfere with networking. - * if( ( uxNetworkingCoreAffinityMask & ( 1 << 0 ) ) != 0 ) - * { - * // The networking task can run on core 0, pin our task to core 1. - * vTaskCoreAffinitySet( xHandle, ( 1 << 1 ) ); - * } - * else - * { - * // Otherwise, pin our task to core 0. - * vTaskCoreAffinitySet( xHandle, ( 1 << 0 ) ); - * } - * } - */ -UBaseType_t vTaskCoreAffinityGet( ConstTaskHandle_t xTask ); -#endif - -#if( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - -/** - * @brief Disables preemption for a task. - * - * @param xTask The handle of the task to disable preemption. Passing NULL - * disables preemption for the calling task. - * - * Example usage: - * - * void vTaskCode( void *pvParameters ) - * { - * // Silence warnings about unused parameters. - * ( void ) pvParameters; - * - * for( ;; ) - * { - * // ... Perform some function here. - * - * // Disable preemption for this task. - * vTaskPreemptionDisable( NULL ); - * - * // The task will not be preempted when it is executing in this - * portion ... - * - * // ... until the preemption is enabled again. - * vTaskPreemptionEnable( NULL ); - * - * // The task can be preempted when it is executing in this portion. - * } - * } - */ -void vTaskPreemptionDisable( const TaskHandle_t xTask ); -#endif - -#if( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - -/** - * @brief Enables preemption for a task. - * - * @param xTask The handle of the task to enable preemption. Passing NULL - * enables preemption for the calling task. - * - * Example usage: - * - * void vTaskCode( void *pvParameters ) - * { - * // Silence warnings about unused parameters. - * ( void ) pvParameters; - * - * for( ;; ) - * { - * // ... Perform some function here. - * - * // Disable preemption for this task. - * vTaskPreemptionDisable( NULL ); - * - * // The task will not be preempted when it is executing in this - * portion ... - * - * // ... until the preemption is enabled again. - * vTaskPreemptionEnable( NULL ); - * - * // The task can be preempted when it is executing in this portion. - * } - * } - */ -void vTaskPreemptionEnable( const TaskHandle_t xTask ); -#endif - -/*----------------------------------------------------------- - * SCHEDULER CONTROL - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * void vTaskStartScheduler( void ); - * @endcode - * - * Starts the real time kernel tick processing. After calling the kernel - * has control over which tasks are executed and when. - * - * See the demo application file main.c for an example of creating - * tasks and starting the kernel. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * // Create at least one task before starting the kernel. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); - * - * // Start the real time kernel with preemption. - * vTaskStartScheduler (); - * - * // Will not get here unless a task calls vTaskEndScheduler () - * } - * @endcode - * - * \defgroup vTaskStartScheduler vTaskStartScheduler - * \ingroup SchedulerControl - */ -void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskEndScheduler( void ); - * @endcode - * - * NOTE: At the time of writing only the x86 real mode port, which runs on a PC - * in place of DOS, implements this function. - * - * Stops the real time kernel tick. All created tasks will be automatically - * deleted and multitasking (either preemptive or cooperative) will - * stop. Execution then resumes from the point where vTaskStartScheduler () - * was called, as if vTaskStartScheduler () had just returned. - * - * See the demo application file main. c in the demo/PC directory for an - * example that uses vTaskEndScheduler (). - * - * vTaskEndScheduler () requires an exit function to be defined within the - * portable layer (see vPortEndScheduler () in port. c for the PC port). This - * performs hardware specific operations such as stopping the kernel tick. - * - * vTaskEndScheduler () will cause all of the resources allocated by the - * kernel to be freed - but will not free resources allocated by application - * tasks. - * - * Example usage: - * @code{c} - * void vTaskCode( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // At some point we want to end the real time kernel processing - * // so call ... - * vTaskEndScheduler (); - * } - * } - * - * void vAFunction( void ) - * { - * // Create at least one task before starting the kernel. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); - * - * // Start the real time kernel with preemption. - * vTaskStartScheduler (); - * - * // Will only get here when the vTaskCode () task has called - * // vTaskEndScheduler (). When we get here we are back to single task - * // execution. - * } - * @endcode - * - * \defgroup vTaskEndScheduler vTaskEndScheduler - * \ingroup SchedulerControl - */ -void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskSuspendAll( void ); - * @endcode - * - * Suspends the scheduler without disabling interrupts. Context switches will - * not occur while the scheduler is suspended. - * - * After calling vTaskSuspendAll () the calling task will continue to execute - * without risk of being swapped out until a call to xTaskResumeAll () has been - * made. - * - * API functions that have the potential to cause a context switch (for example, - * xTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler - * is suspended. - * - * Example usage: - * @code{c} - * void vTask1( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // ... - * - * // At some point the task wants to perform a long operation during - * // which it does not want to get swapped out. It cannot use - * // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the - * // operation may cause interrupts to be missed - including the - * // ticks. - * - * // Prevent the real time kernel swapping out the task. - * vTaskSuspendAll (); - * - * // Perform the operation here. There is no need to use critical - * // sections as we have all the microcontroller processing time. - * // During this time interrupts will still operate and the kernel - * // tick count will be maintained. - * - * // ... - * - * // The operation is complete. Restart the kernel. - * xTaskResumeAll (); - * } - * } - * @endcode - * \defgroup vTaskSuspendAll vTaskSuspendAll - * \ingroup SchedulerControl - */ -void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * BaseType_t xTaskResumeAll( void ); - * @endcode - * - * Resumes scheduler activity after it was suspended by a call to - * vTaskSuspendAll(). - * - * xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks - * that were previously suspended by a call to vTaskSuspend(). - * - * @return If resuming the scheduler caused a context switch then pdTRUE is - * returned, otherwise pdFALSE is returned. - * - * Example usage: - * @code{c} - * void vTask1( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // ... - * - * // At some point the task wants to perform a long operation during - * // which it does not want to get swapped out. It cannot use - * // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the - * // operation may cause interrupts to be missed - including the - * // ticks. - * - * // Prevent the real time kernel swapping out the task. - * vTaskSuspendAll (); - * - * // Perform the operation here. There is no need to use critical - * // sections as we have all the microcontroller processing time. - * // During this time interrupts will still operate and the real - * // time kernel tick count will be maintained. - * - * // ... - * - * // The operation is complete. Restart the kernel. We want to force - * // a context switch - but there is no point if resuming the scheduler - * // caused a context switch already. - * if( !xTaskResumeAll () ) - * { - * taskYIELD (); - * } - * } - * } - * @endcode - * \defgroup xTaskResumeAll xTaskResumeAll - * \ingroup SchedulerControl - */ -BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- - * TASK UTILITIES - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * TickType_t xTaskGetTickCount( void ); - * @endcode - * - * @return The count of ticks since vTaskStartScheduler was called. - * - * \defgroup xTaskGetTickCount xTaskGetTickCount - * \ingroup TaskUtils - */ -TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * TickType_t xTaskGetTickCountFromISR( void ); - * @endcode - * - * @return The count of ticks since vTaskStartScheduler was called. - * - * This is a version of xTaskGetTickCount() that is safe to be called from an - * ISR - provided that TickType_t is the natural word size of the - * microcontroller being used or interrupt nesting is either not supported or - * not being used. - * - * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR - * \ingroup TaskUtils - */ -TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * uint16_t uxTaskGetNumberOfTasks( void ); - * @endcode - * - * @return The number of tasks that the real time kernel is currently managing. - * This includes all ready, blocked and suspended tasks. A task that - * has been deleted but not yet freed by the idle task will also be - * included in the count. - * - * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks - * \ingroup TaskUtils - */ -UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * char *pcTaskGetName( TaskHandle_t xTaskToQuery ); - * @endcode - * - * @return The text (human readable) name of the task referenced by the handle - * xTaskToQuery. A task can query its own name by either passing in its own - * handle, or by setting xTaskToQuery to NULL. - * - * \defgroup pcTaskGetName pcTaskGetName - * \ingroup TaskUtils - */ -char * pcTaskGetName( TaskHandle_t xTaskToQuery ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ); - * @endcode - * - * NOTE: This function takes a relatively long time to complete and should be - * used sparingly. - * - * @return The handle of the task that has the human readable name - * pcNameToQuery. NULL is returned if no matching name is found. - * INCLUDE_xTaskGetHandle must be set to 1 in FreeRTOSConfig.h for - * pcTaskGetHandle() to be available. - * - * \defgroup pcTaskGetHandle pcTaskGetHandle - * \ingroup TaskUtils - */ -TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask, - * StackType_t ** ppuxStackBuffer, - * StaticTask_t ** ppxTaskBuffer ); - * @endcode - * - * Retrieve pointers to a statically created task's data structure - * buffer and stack buffer. These are the same buffers that are supplied - * at the time of creation. - * - * @param xTask The task for which to retrieve the buffers. - * - * @param ppuxStackBuffer Used to return a pointer to the task's stack buffer. - * - * @param ppxTaskBuffer Used to return a pointer to the task's data structure - * buffer. - * - * @return pdTRUE if buffers were retrieved, pdFALSE otherwise. - * - * \defgroup xTaskGetStaticBuffers xTaskGetStaticBuffers - * \ingroup TaskUtils - */ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) -BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask, - StackType_t ** ppuxStackBuffer, - StaticTask_t ** ppxTaskBuffer ) - PRIVILEGED_FUNCTION; -#endif /* configSUPPORT_STATIC_ALLOCATION */ - -/** - * task.h - * @code{c} - * UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for - * this function to be available. - * - * Returns the high water mark of the stack associated with xTask. That is, - * the minimum free stack space there has been (in words, so on a 32 bit machine - * a value of 1 means 4 bytes) since the task started. The smaller the returned - * number the closer the task has come to overflowing its stack. - * - * 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. - * - * @param xTask Handle of the task associated with the stack to be checked. - * Set xTask to NULL to check the stack of the calling task. - * - * @return The smallest amount of free stack space there has been (in words, so - * actual spaces on the stack rather than bytes) since the task referenced by - * xTask was created. - */ -UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskGetStackHighWaterMark2 must be set to 1 in FreeRTOSConfig.h for - * this function to be available. - * - * Returns the high water mark of the stack associated with xTask. That is, - * the minimum free stack space there has been (in words, so on a 32 bit machine - * a value of 1 means 4 bytes) since the task started. The smaller the returned - * number the closer the task has come to overflowing its stack. - * - * 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. - * - * @param xTask Handle of the task associated with the stack to be checked. - * Set xTask to NULL to check the stack of the calling task. - * - * @return The smallest amount of free stack space there has been (in words, so - * actual spaces on the stack rather than bytes) since the task referenced by - * xTask was created. - */ -configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/* When using trace macros it is sometimes necessary to include task.h before - * FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been - * defined, so the following two prototypes will cause a compilation error. This - * can be fixed by simply guarding against the inclusion of these two prototypes - * unless they are explicitly required by the configUSE_APPLICATION_TASK_TAG - * configuration constant. */ -#ifdef configUSE_APPLICATION_TASK_TAG - #if configUSE_APPLICATION_TASK_TAG == 1 - -/** - * task.h - * @code{c} - * void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t - * pxHookFunction ); - * @endcode - * - * Sets pxHookFunction to be the task hook function used by the task xTask. - * Passing xTask as NULL has the effect of setting the calling tasks hook - * function. - */ -void vTaskSetApplicationTaskTag( TaskHandle_t xTask, - TaskHookFunction_t pxHookFunction ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * void xTaskGetApplicationTaskTag( TaskHandle_t xTask ); - * @endcode - * - * Returns the pxHookFunction value assigned to the task xTask. Do not - * call from an interrupt service routine - call - * xTaskGetApplicationTaskTagFromISR() instead. - */ -TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * void xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ); - * @endcode - * - * Returns the pxHookFunction value assigned to the task xTask. Can - * be called from an interrupt service routine. - */ -TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ -#endif /* ifdef configUSE_APPLICATION_TASK_TAG */ - -#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) - -/* Each task contains an array of pointers that is dimensioned by the - * configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. The - * kernel does not use the pointers itself, so the application writer can use - * the pointers for any purpose they wish. The following two functions are - * used to set and query a pointer respectively. */ -void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, - BaseType_t xIndex, - void * pvValue ) PRIVILEGED_FUNCTION; -void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, - BaseType_t xIndex ) - PRIVILEGED_FUNCTION; - -#endif - -#if( configCHECK_FOR_STACK_OVERFLOW > 0 ) - -/** - * task.h - * @code{c} - * void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName); - * @endcode - * - * The application stack overflow hook is called when a stack overflow is - * detected for a task. - * - * Details on stack overflow detection can be found here: - * https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html - * - * @param xTask the task that just exceeded its stack boundaries. - * @param pcTaskName A character string containing the name of the offending - * task. - */ -void vApplicationStackOverflowHook( TaskHandle_t xTask, char * pcTaskName ); - -#endif - -#if( configUSE_IDLE_HOOK == 1 ) - -/** - * task.h - * @code{c} - * void vApplicationIdleHook( void ); - * @endcode - * - * The application idle hook is called by the idle task. - * This allows the application designer to add background functionality without - * the overhead of a separate task. - * NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A - * FUNCTION THAT MIGHT BLOCK. - */ -void vApplicationIdleHook( void ); - -#endif - -#if( configUSE_TICK_HOOK != 0 ) - -/** - * task.h - * @code{c} - * void vApplicationTickHook( void ); - * @endcode - * - * This hook function is called in the system tick handler after any OS work is - * completed. - */ -void vApplicationTickHook( void ); /*lint !e526 Symbol not defined as it is an - application callback. */ - -#endif - -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) - -/** - * task.h - * @code{c} - * void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, - * StackType_t ** ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) - * @endcode - * - * This function is used to provide a statically allocated block of memory to - * FreeRTOS to hold the Idle Task TCB. This function is required when - * configSUPPORT_STATIC_ALLOCATION is set. For more information see this URI: - * https://www.FreeRTOS.org/a00110.html#configSUPPORT_STATIC_ALLOCATION - * - * @param ppxIdleTaskTCBBuffer A handle to a statically allocated TCB buffer - * @param ppxIdleTaskStackBuffer A handle to a statically allocated Stack buffer - * for the idle task - * @param pulIdleTaskStackSize A pointer to the number of elements that will fit - * in the allocated stack buffer - */ -void vApplicationGetIdleTaskMemory( - StaticTask_t ** ppxIdleTaskTCBBuffer, - StackType_t ** ppxIdleTaskStackBuffer, - uint32_t * pulIdleTaskStackSize ); /*lint !e526 Symbol not defined as it is - an application callback. */ -#endif - -/** - * task.h - * @code{c} - * BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void - * *pvParameter ); - * @endcode - * - * Calls the hook function associated with xTask. Passing xTask as NULL has - * the effect of calling the Running tasks (the calling task) hook function. - * - * pvParameter is passed to the hook function for the task to interpret as it - * wants. The return value is the value returned by the task hook function - * registered by the user. - */ -BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, - void * pvParameter ) - PRIVILEGED_FUNCTION; - -/** - * xTaskGetIdleTaskHandle() is only available if - * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. - * - * Simply returns the handle of the idle task. It is not valid to call - * xTaskGetIdleTaskHandle() before the scheduler has been started. - */ -TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; - -/** - * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for - * uxTaskGetSystemState() to be available. - * - * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in - * the system. TaskStatus_t structures contain, among other things, members - * for the task handle, task name, task priority, task state, and total amount - * of run time consumed by the task. See the TaskStatus_t structure - * definition in this file for the full member list. - * - * NOTE: This function is intended for debugging use only as its use results in - * the scheduler remaining suspended for an extended period. - * - * @param pxTaskStatusArray A pointer to an array of TaskStatus_t structures. - * The array must contain at least one TaskStatus_t structure for each task - * that is under the control of the RTOS. The number of tasks under the control - * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API - * function. - * - * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray - * parameter. The size is specified as the number of indexes in the array, or - * the number of TaskStatus_t structures contained in the array, not by the - * number of bytes in the array. - * - * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in - * FreeRTOSConfig.h then *pulTotalRunTime is set by uxTaskGetSystemState() to - * the total run time (as defined by the run time stats clock, see - * https://www.FreeRTOS.org/rtos-run-time-stats.html) since the target booted. - * pulTotalRunTime can be set to NULL to omit the total run time information. - * - * @return The number of TaskStatus_t structures that were populated by - * uxTaskGetSystemState(). This should equal the number returned by the - * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed - * in the uxArraySize parameter was too small. - * - * Example usage: - * @code{c} - * // This example demonstrates how a human readable table of run time stats - * // information is generated from raw data provided by - * uxTaskGetSystemState(). - * // The human readable table is written to pcWriteBuffer - * void vTaskGetRunTimeStats( char *pcWriteBuffer ) - * { - * TaskStatus_t *pxTaskStatusArray; - * volatile UBaseType_t uxArraySize, x; - * configRUN_TIME_COUNTER_TYPE ulTotalRunTime, ulStatsAsPercentage; - * - * // Make sure the write buffer does not contain a string. - * pcWriteBuffer = 0x00; - * - * // Take a snapshot of the number of tasks in case it changes while this - * // function is executing. - * uxArraySize = uxTaskGetNumberOfTasks(); - * - * // Allocate a TaskStatus_t structure for each task. An array could be - * // allocated statically at compile time. - * pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) - * ); - * - * if( pxTaskStatusArray != NULL ) - * { - * // Generate raw status information about each task. - * uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, - * &ulTotalRunTime ); - * - * // For percentage calculations. - * ulTotalRunTime /= 100UL; - * - * // Avoid divide by zero errors. - * if( ulTotalRunTime > 0 ) - * { - * // For each populated position in the pxTaskStatusArray array, - * // format the raw data as human readable ASCII 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. - * // ulTotalRunTimeDiv100 has already been divided by 100. - * ulStatsAsPercentage = pxTaskStatusArray[ x - * ].ulRunTimeCounter / ulTotalRunTime; - * - * if( ulStatsAsPercentage > 0UL ) - * { - * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", - * pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, - * ulStatsAsPercentage ); - * } - * else - * { - * // If the percentage is zero here then the task has - * // consumed less than 1% of the total run time. - * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", - * pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter ); - * } - * - * pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); - * } - * } - * - * // The array is no longer needed, free the memory it consumes. - * vPortFree( pxTaskStatusArray ); - * } - * } - * @endcode - */ -UBaseType_t uxTaskGetSystemState( - TaskStatus_t * const pxTaskStatusArray, - const UBaseType_t uxArraySize, - configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskList( char *pcWriteBuffer ); - * @endcode - * - * configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must - * both be defined as 1 for this function to be available. See the - * configuration section of the FreeRTOS.org website for more information. - * - * NOTE 1: This function will disable interrupts for its duration. It is - * not intended for normal application runtime use but as a debug aid. - * - * Lists all the current tasks, along with their current state and stack - * usage high water mark. - * - * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or - * suspended ('S'). - * - * 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(). - * - * @param pcWriteBuffer A buffer into which the above mentioned details - * will be written, in ASCII form. This buffer is assumed to be large - * enough to contain the generated report. Approximately 40 bytes per - * task should be sufficient. - * - * \defgroup vTaskList vTaskList - * \ingroup TaskUtils - */ -void vTaskList( char * pcWriteBuffer ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * void vTaskGetRunTimeStats( char *pcWriteBuffer ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS - * must both be defined as 1 for this function to be available. The application - * must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() - * to configure a peripheral timer/counter and return the timers current count - * value respectively. The counter should be at least 10 times the frequency of - * the tick count. - * - * NOTE 1: This function will disable interrupts for its duration. It is - * not intended for normal application runtime use but as a debug aid. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * Calling vTaskGetRunTimeStats() writes the total execution time of each - * task into a buffer, both as an absolute count value and as a percentage - * of the total system execution time. - * - * NOTE 2: - * - * 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(). - * - * @param pcWriteBuffer A buffer into which the execution times will be - * written, in ASCII form. This buffer is assumed to be large enough to - * contain the generated report. Approximately 40 bytes per task should - * be sufficient. - * - * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats - * \ingroup TaskUtils - */ -void vTaskGetRunTimeStats( char * pcWriteBuffer ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask - * ); configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t - * xTask ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS must be defined as 1 for these functions to be - * available. The application must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() to configure a peripheral timer/counter and - * return the timers current count value respectively. The counter should be - * at least 10 times the frequency of the tick count. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total - * execution time of each task into a buffer, ulTaskGetRunTimeCounter() - * returns the total execution time of just one task and - * ulTaskGetRunTimePercent() returns the percentage of the CPU time used by - * just one task. - * - * @return The total run time of the given task or the percentage of the total - * run time consumed by the given task. This is the amount of time the task - * has actually been executing. The unit of time is dependent on the frequency - * configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() macros. - * - * \defgroup ulTaskGetRunTimeCounter ulTaskGetRunTimeCounter - * \ingroup TaskUtils - */ -configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; -configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ); - * configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS must be defined as 1 for these functions to be - * available. The application must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() to configure a peripheral timer/counter and - * return the timers current count value respectively. The counter should be - * at least 10 times the frequency of the tick count. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total - * execution time of each task into a buffer, ulTaskGetIdleRunTimeCounter() - * returns the total execution time of just the idle task and - * ulTaskGetIdleRunTimePercent() returns the percentage of the CPU time used by - * just the idle task. - * - * Note the amount of idle time is only a good measure of the slack time in a - * system if there are no other tasks executing at the idle priority, tickless - * idle is not used, and configIDLE_SHOULD_YIELD is set to 0. - * - * @return The total run time of the idle task or the percentage of the total - * run time consumed by the idle task. This is the amount of time the - * idle task has actually been executing. The unit of time is dependent on the - * frequency configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() macros. - * - * \defgroup ulTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter - * \ingroup TaskUtils - */ -configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ) - PRIVILEGED_FUNCTION; -configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyIndexed( TaskHandle_t xTaskToNotify, UBaseType_t - * uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction ); BaseType_t - * xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction - * eAction ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * Sends a direct to task notification to a task, with an optional value and - * action. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * A task can use xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() to - * [optionally] block to wait for a notification to be pending. The task does - * not consume any CPU time while it is in the Blocked state. - * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their - * un-indexed equivalents). If the task was already in the Blocked state to - * wait for a notification when the notification arrives then the task will - * automatically be removed from the Blocked state (unblocked) and the - * notification cleared. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotify() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling xTaskNotify() is equivalent to calling xTaskNotifyIndexed() - * with the uxIndexToNotify parameter set to 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotify() does - * not have this parameter and always sends notifications to index 0. - * - * @param ulValue Data that can be sent with the notification. How the data is - * used depends on the value of the eAction parameter. - * - * @param eAction Specifies how the notification updates the task's notification - * value, if at all. Valid values for eAction are as follows: - * - * eSetBits - - * The target notification value is bitwise ORed with ulValue. - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * eIncrement - - * The target notification value is incremented. ulValue is not used and - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * eSetValueWithOverwrite - - * The target notification value is set to the value of ulValue, even if the - * task being notified had not yet processed the previous notification at the - * same array index (the task already had a notification pending at that index). - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * eSetValueWithoutOverwrite - - * If the task being notified did not already have a notification pending at the - * same array index then the target notification value is set to ulValue and - * xTaskNotifyIndexed() will return pdPASS. If the task being notified already - * had a notification pending at the same array index then no action is - * performed and pdFAIL is returned. - * - * eNoAction - - * The task receives a notification at the specified array index without the - * notification value at that index being updated. ulValue is not used and - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * pulPreviousNotificationValue - - * Can be used to pass out the subject task's notification value before any - * bits are modified by the notify function. - * - * @return Dependent on the value of eAction. See the description of the - * eAction parameter. - * - * \defgroup xTaskNotifyIndexed xTaskNotifyIndexed - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, - UBaseType_t uxIndexToNotify, - uint32_t ulValue, - eNotifyAction eAction, - uint32_t * pulPreviousNotificationValue ) - PRIVILEGED_FUNCTION; -#define xTaskNotify( xTaskToNotify, ulValue, eAction ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - NULL ) -#define xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - NULL ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyAndQueryIndexed( TaskHandle_t xTaskToNotify, - * UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, - * uint32_t *pulPreviousNotifyValue ); BaseType_t xTaskNotifyAndQuery( - * TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t - * *pulPreviousNotifyValue ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * xTaskNotifyAndQueryIndexed() performs the same operation as - * xTaskNotifyIndexed() with the addition that it also returns the subject - * task's prior notification value (the notification value at the time the - * function is called rather than when the function returns) in the additional - * pulPreviousNotifyValue parameter. - * - * xTaskNotifyAndQuery() performs the same operation as xTaskNotify() with the - * addition that it also returns the subject task's prior notification value - * (the notification value as it was at the time the function is called, rather - * than when the function returns) in the additional pulPreviousNotifyValue - * parameter. - * - * \defgroup xTaskNotifyAndQueryIndexed xTaskNotifyAndQueryIndexed - * \ingroup TaskNotifications - */ -#define xTaskNotifyAndQuery( xTaskToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotifyValue ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotifyValue ) ) -#define xTaskNotifyAndQueryIndexed( xTaskToNotify, \ - uxIndexToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotifyValue ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotifyValue ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t - * uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t - * *pxHigherPriorityTaskWoken ); BaseType_t xTaskNotifyFromISR( TaskHandle_t - * xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t - * *pxHigherPriorityTaskWoken ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * A version of xTaskNotifyIndexed() that can be used from an interrupt service - * routine (ISR). - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] - * block to wait for a notification value to have a non-zero value. The task - * does not consume any CPU time while it is in the Blocked state. - * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their - * un-indexed equivalents). If the task was already in the Blocked state to - * wait for a notification when the notification arrives then the task will - * automatically be removed from the Blocked state (unblocked) and the - * notification cleared. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyFromISR() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling xTaskNotifyFromISR() is equivalent to calling - * xTaskNotifyIndexedFromISR() with the uxIndexToNotify parameter set to 0. - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyFromISR() - * does not have this parameter and always sends notifications to index 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param ulValue Data that can be sent with the notification. How the data is - * used depends on the value of the eAction parameter. - * - * @param eAction Specifies how the notification updates the task's notification - * value, if at all. Valid values for eAction are as follows: - * - * eSetBits - - * The task's notification value is bitwise ORed with ulValue. xTaskNotify() - * always returns pdPASS in this case. - * - * eIncrement - - * The task's notification value is incremented. ulValue is not used and - * xTaskNotify() always returns pdPASS in this case. - * - * eSetValueWithOverwrite - - * The task's notification value is set to the value of ulValue, even if the - * task being notified had not yet processed the previous notification (the - * task already had a notification pending). xTaskNotify() always returns - * pdPASS in this case. - * - * eSetValueWithoutOverwrite - - * If the task being notified did not already have a notification pending then - * the task's notification value is set to ulValue and xTaskNotify() will - * return pdPASS. If the task being notified already had a notification - * pending then no action is performed and pdFAIL is returned. - * - * eNoAction - - * The task receives a notification without its notification value being - * updated. ulValue is not used and xTaskNotify() always returns pdPASS in - * this case. - * - * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set - * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the - * task to which the notification was sent to leave the Blocked state, and the - * unblocked task has a priority higher than the currently running task. If - * xTaskNotifyFromISR() sets this value to pdTRUE then a context switch should - * be requested before the interrupt is exited. How a context switch is - * requested from an ISR is dependent on the port - see the documentation page - * for the port in use. - * - * @return Dependent on the value of eAction. See the description of the - * eAction parameter. - * - * \defgroup xTaskNotifyIndexedFromISR xTaskNotifyIndexedFromISR - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, - UBaseType_t uxIndexToNotify, - uint32_t ulValue, - eNotifyAction eAction, - uint32_t * pulPreviousNotificationValue, - BaseType_t * pxHigherPriorityTaskWoken ) - PRIVILEGED_FUNCTION; -#define xTaskNotifyFromISR( xTaskToNotify, \ - ulValue, \ - eAction, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - NULL, \ - ( pxHigherPriorityTaskWoken ) ) -#define xTaskNotifyIndexedFromISR( xTaskToNotify, \ - uxIndexToNotify, \ - ulValue, \ - eAction, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - NULL, \ - ( pxHigherPriorityTaskWoken ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify, - * UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, - * uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken - * ); BaseType_t xTaskNotifyAndQueryFromISR( TaskHandle_t xTaskToNotify, - * uint32_t ulValue, eNotifyAction eAction, uint32_t - * *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * xTaskNotifyAndQueryIndexedFromISR() performs the same operation as - * xTaskNotifyIndexedFromISR() with the addition that it also returns the - * subject task's prior notification value (the notification value at the time - * the function is called rather than at the time the function returns) in the - * additional pulPreviousNotifyValue parameter. - * - * xTaskNotifyAndQueryFromISR() performs the same operation as - * xTaskNotifyFromISR() with the addition that it also returns the subject - * task's prior notification value (the notification value at the time the - * function is called rather than at the time the function returns) in the - * additional pulPreviousNotifyValue parameter. - * - * \defgroup xTaskNotifyAndQueryIndexedFromISR xTaskNotifyAndQueryIndexedFromISR - * \ingroup TaskNotifications - */ -#define xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, \ - uxIndexToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotificationValue, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotificationValue ), \ - ( pxHigherPriorityTaskWoken ) ) -#define xTaskNotifyAndQueryFromISR( xTaskToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotificationValue, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotificationValue ), \ - ( pxHigherPriorityTaskWoken ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyWaitIndexed( UBaseType_t uxIndexToWaitOn, uint32_t - * ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t - * *pulNotificationValue, TickType_t xTicksToWait ); - * - * BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t - * ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait - * ); - * @endcode - * - * Waits for a direct to task notification to be pending at a given index within - * an array of direct to task notifications. - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this - * function to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their - * un-indexed equivalents). If the task was already in the Blocked state to - * wait for a notification when the notification arrives then the task will - * automatically be removed from the Blocked state (unblocked) and the - * notification cleared. - * - * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] - * block to wait for a notification value to have a non-zero value. The task - * does not consume any CPU time while it is in the Blocked state. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyWait() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling xTaskNotifyWait() is equivalent to calling - * xTaskNotifyWaitIndexed() with the uxIndexToWaitOn parameter set to 0. - * - * @param uxIndexToWaitOn The index within the calling task's array of - * notification values on which the calling task will wait for a notification to - * be received. uxIndexToWaitOn must be less than - * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyWait() does - * not have this parameter and always waits for notifications on index 0. - * - * @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value - * will be cleared in the calling task's notification value before the task - * checks to see if any notifications are pending, and optionally blocks if no - * notifications are pending. Setting ulBitsToClearOnEntry to ULONG_MAX (if - * limits.h is included) or 0xffffffffUL (if limits.h is not included) will have - * the effect of resetting the task's notification value to 0. Setting - * ulBitsToClearOnEntry to 0 will leave the task's notification value unchanged. - * - * @param ulBitsToClearOnExit If a notification is pending or received before - * the calling task exits the xTaskNotifyWait() function then the task's - * notification value (see the xTaskNotify() API function) is passed out using - * the pulNotificationValue parameter. Then any bits that are set in - * ulBitsToClearOnExit will be cleared in the task's notification value (note - * *pulNotificationValue is set before any bits are cleared). Setting - * ulBitsToClearOnExit to ULONG_MAX (if limits.h is included) or 0xffffffffUL - * (if limits.h is not included) will have the effect of resetting the task's - * notification value to 0 before the function exits. Setting - * ulBitsToClearOnExit to 0 will leave the task's notification value unchanged - * when the function exits (in which case the value passed out in - * pulNotificationValue will match the task's notification value). - * - * @param pulNotificationValue Used to pass the task's notification value out - * of the function. Note the value passed out will not be effected by the - * clearing of any bits caused by ulBitsToClearOnExit being non-zero. - * - * @param xTicksToWait The maximum amount of time that the task should wait in - * the Blocked state for a notification to be received, should a notification - * not already be pending when xTaskNotifyWait() was called. The task - * will not consume any processing time while it is in the Blocked state. This - * is specified in kernel ticks, the macro pdMS_TO_TICKS( value_in_ms ) can be - * used to convert a time specified in milliseconds to a time specified in - * ticks. - * - * @return If a notification was received (including notifications that were - * already pending when xTaskNotifyWait was called) then pdPASS is - * returned. Otherwise pdFAIL is returned. - * - * \defgroup xTaskNotifyWaitIndexed xTaskNotifyWaitIndexed - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, - uint32_t ulBitsToClearOnEntry, - uint32_t ulBitsToClearOnExit, - uint32_t * pulNotificationValue, - TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -#define xTaskNotifyWait( ulBitsToClearOnEntry, \ - ulBitsToClearOnExit, \ - pulNotificationValue, \ - xTicksToWait ) \ - xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, \ - ( ulBitsToClearOnEntry ), \ - ( ulBitsToClearOnExit ), \ - ( pulNotificationValue ), \ - ( xTicksToWait ) ) -#define xTaskNotifyWaitIndexed( uxIndexToWaitOn, \ - ulBitsToClearOnEntry, \ - ulBitsToClearOnExit, \ - pulNotificationValue, \ - xTicksToWait ) \ - xTaskGenericNotifyWait( ( uxIndexToWaitOn ), \ - ( ulBitsToClearOnEntry ), \ - ( ulBitsToClearOnExit ), \ - ( pulNotificationValue ), \ - ( xTicksToWait ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t - * uxIndexToNotify ); BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify ); - * @endcode - * - * Sends a direct to task notification to a particular index in the target - * task's notification array in a manner similar to giving a counting semaphore. - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * macros to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * xTaskNotifyGiveIndexed() is a helper macro intended for use when task - * notifications are used as light weight and faster binary or counting - * semaphore equivalents. Actual FreeRTOS semaphores are given using the - * xSemaphoreGive() API function, the equivalent action that instead uses a task - * notification is xTaskNotifyGiveIndexed(). - * - * When task notifications are being used as a binary or counting semaphore - * equivalent then the task being notified should wait for the notification - * using the ulTaskNotifyTakeIndexed() API function rather than the - * xTaskNotifyWaitIndexed() API function. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyGive() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling xTaskNotifyGive() is equivalent to calling - * xTaskNotifyGiveIndexed() with the uxIndexToNotify parameter set to 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyGive() - * does not have this parameter and always sends notifications to index 0. - * - * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the - * eAction parameter set to eIncrement - so pdPASS is always returned. - * - * \defgroup xTaskNotifyGiveIndexed xTaskNotifyGiveIndexed - * \ingroup TaskNotifications - */ -#define xTaskNotifyGive( xTaskToNotify ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( 0 ), \ - eIncrement, \ - NULL ) -#define xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( 0 ), \ - eIncrement, \ - NULL ) - -/** - * task. h - * @code{c} - * void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t - * uxIndexToNotify, BaseType_t *pxHigherPriorityTaskWoken ); void - * vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t - * *pxHigherPriorityTaskWoken ); - * @endcode - * - * A version of xTaskNotifyGiveIndexed() that can be called from an interrupt - * service routine (ISR). - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro - * to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * vTaskNotifyGiveIndexedFromISR() is intended for use when task notifications - * are used as light weight and faster binary or counting semaphore equivalents. - * Actual FreeRTOS semaphores are given from an ISR using the - * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses - * a task notification is vTaskNotifyGiveIndexedFromISR(). - * - * When task notifications are being used as a binary or counting semaphore - * equivalent then the task being notified should wait for the notification - * using the ulTaskNotifyTakeIndexed() API function rather than the - * xTaskNotifyWaitIndexed() API function. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyFromISR() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling xTaskNotifyGiveFromISR() is equivalent to calling - * xTaskNotifyGiveIndexedFromISR() with the uxIndexToNotify parameter set to 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. - * xTaskNotifyGiveFromISR() does not have this parameter and always sends - * notifications to index 0. - * - * @param pxHigherPriorityTaskWoken vTaskNotifyGiveFromISR() will set - * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the - * task to which the notification was sent to leave the Blocked state, and the - * unblocked task has a priority higher than the currently running task. If - * vTaskNotifyGiveFromISR() sets this value to pdTRUE then a context switch - * should be requested before the interrupt is exited. How a context switch is - * requested from an ISR is dependent on the port - see the documentation page - * for the port in use. - * - * \defgroup vTaskNotifyGiveIndexedFromISR vTaskNotifyGiveIndexedFromISR - * \ingroup TaskNotifications - */ -void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify, - UBaseType_t uxIndexToNotify, - BaseType_t * pxHigherPriorityTaskWoken ) - PRIVILEGED_FUNCTION; -#define vTaskNotifyGiveFromISR( xTaskToNotify, pxHigherPriorityTaskWoken ) \ - vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( pxHigherPriorityTaskWoken ) ) -#define vTaskNotifyGiveIndexedFromISR( xTaskToNotify, \ - uxIndexToNotify, \ - pxHigherPriorityTaskWoken ) \ - vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( pxHigherPriorityTaskWoken ) ) - -/** - * task. h - * @code{c} - * uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn, BaseType_t - * xClearCountOnExit, TickType_t xTicksToWait ); - * - * uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t - * xTicksToWait ); - * @endcode - * - * Waits for a direct to task notification on a particular index in the calling - * task's notification array in a manner similar to taking a counting semaphore. - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this - * function to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * ulTaskNotifyTakeIndexed() is intended for use when a task notification is - * used as a faster and lighter weight binary or counting semaphore alternative. - * Actual FreeRTOS semaphores are taken using the xSemaphoreTake() API function, - * the equivalent action that instead uses a task notification is - * ulTaskNotifyTakeIndexed(). - * - * When a task is using its notification value as a binary or counting semaphore - * other tasks should send notifications to it using the - * xTaskNotifyGiveIndexed() macro, or xTaskNotifyIndex() function with the - * eAction parameter set to eIncrement. - * - * ulTaskNotifyTakeIndexed() can either clear the task's notification value at - * the array index specified by the uxIndexToWaitOn parameter to zero on exit, - * in which case the notification value acts like a binary semaphore, or - * decrement the notification value on exit, in which case the notification - * value acts like a counting semaphore. - * - * A task can use ulTaskNotifyTakeIndexed() to [optionally] block to wait for - * a notification. The task does not consume any CPU time while it is in the - * Blocked state. - * - * Where as xTaskNotifyWaitIndexed() will return when a notification is pending, - * ulTaskNotifyTakeIndexed() will return when the task's notification value is - * not zero. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. ulTaskNotifyTake() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling ulTaskNotifyTake() is equivalent to calling - * ulTaskNotifyTakeIndexed() with the uxIndexToWaitOn parameter set to 0. - * - * @param uxIndexToWaitOn The index within the calling task's array of - * notification values on which the calling task will wait for a notification to - * be non-zero. uxIndexToWaitOn must be less than - * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyTake() does - * not have this parameter and always waits for notifications on index 0. - * - * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's - * notification value is decremented when the function exits. In this way the - * notification value acts like a counting semaphore. If xClearCountOnExit is - * not pdFALSE then the task's notification value is cleared to zero when the - * function exits. In this way the notification value acts like a binary - * semaphore. - * - * @param xTicksToWait The maximum amount of time that the task should wait in - * the Blocked state for the task's notification value to be greater than zero, - * should the count not already be greater than zero when - * ulTaskNotifyTake() was called. The task will not consume any processing - * time while it is in the Blocked state. This is specified in kernel ticks, - * the macro pdMS_TO_TICKS( value_in_ms ) can be used to convert a time - * specified in milliseconds to a time specified in ticks. - * - * @return The task's notification count before it is either cleared to zero or - * decremented (see the xClearCountOnExit parameter). - * - * \defgroup ulTaskNotifyTakeIndexed ulTaskNotifyTakeIndexed - * \ingroup TaskNotifications - */ -uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, - BaseType_t xClearCountOnExit, - TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -#define ulTaskNotifyTake( xClearCountOnExit, xTicksToWait ) \ - ulTaskGenericNotifyTake( ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( xClearCountOnExit ), \ - ( xTicksToWait ) ) -#define ulTaskNotifyTakeIndexed( uxIndexToWaitOn, \ - xClearCountOnExit, \ - xTicksToWait ) \ - ulTaskGenericNotifyTake( ( uxIndexToWaitOn ), \ - ( xClearCountOnExit ), \ - ( xTicksToWait ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t - * uxIndexToCLear ); - * - * BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * If a notification is sent to an index within the array of notifications then - * the notification at that index is said to be 'pending' until it is read or - * explicitly cleared by the receiving task. xTaskNotifyStateClearIndexed() - * is the function that clears a pending notification without reading the - * notification value. The notification value at the same array index is not - * altered. Set xTask to NULL to clear the notification state of the calling - * task. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyStateClear() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling xTaskNotifyStateClear() is equivalent to calling - * xTaskNotifyStateClearIndexed() with the uxIndexToNotify parameter set to 0. - * - * @param xTask The handle of the RTOS task that will have a notification state - * cleared. Set xTask to NULL to clear a notification state in the calling - * task. To obtain a task's handle create the task using xTaskCreate() and - * make use of the pxCreatedTask parameter, or create the task using - * xTaskCreateStatic() and store the returned value, or use the task's name in - * a call to xTaskGetHandle(). - * - * @param uxIndexToClear The index within the target task's array of - * notification values to act upon. For example, setting uxIndexToClear to 1 - * will clear the state of the notification at index 1 within the array. - * uxIndexToClear must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. - * ulTaskNotifyStateClear() does not have this parameter and always acts on the - * notification at index 0. - * - * @return pdTRUE if the task's notification state was set to - * eNotWaitingNotification, otherwise pdFALSE. - * - * \defgroup xTaskNotifyStateClearIndexed xTaskNotifyStateClearIndexed - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask, - UBaseType_t uxIndexToClear ) - PRIVILEGED_FUNCTION; -#define xTaskNotifyStateClear( xTask ) \ - xTaskGenericNotifyStateClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ) ) -#define xTaskNotifyStateClearIndexed( xTask, uxIndexToClear ) \ - xTaskGenericNotifyStateClear( ( xTask ), ( uxIndexToClear ) ) - -/** - * task. h - * @code{c} - * uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, UBaseType_t - * uxIndexToClear, uint32_t ulBitsToClear ); - * - * uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear - * ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * ulTaskNotifyValueClearIndexed() clears the bits specified by the - * ulBitsToClear bit mask in the notification value at array index - * uxIndexToClear of the task referenced by xTask. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. ulTaskNotifyValueClear() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling ulTaskNotifyValueClear() is equivalent to calling - * ulTaskNotifyValueClearIndexed() with the uxIndexToClear parameter set to 0. - * - * @param xTask The handle of the RTOS task that will have bits in one of its - * notification values cleared. Set xTask to NULL to clear bits in a - * notification value of the calling task. To obtain a task's handle create the - * task using xTaskCreate() and make use of the pxCreatedTask parameter, or - * create the task using xTaskCreateStatic() and store the returned value, or - * use the task's name in a call to xTaskGetHandle(). - * - * @param uxIndexToClear The index within the target task's array of - * notification values in which to clear the bits. uxIndexToClear - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. - * ulTaskNotifyValueClear() does not have this parameter and always clears bits - * in the notification value at index 0. - * - * @param ulBitsToClear Bit mask of the bits to clear in the notification value - * of xTask. Set a bit to 1 to clear the corresponding bits in the task's - * notification value. Set ulBitsToClear to 0xffffffff (UINT_MAX on 32-bit - * architectures) to clear the notification value to 0. Set ulBitsToClear to 0 - * to query the task's notification value without clearing any bits. - * - * - * @return The value of the target task's notification value before the bits - * specified by ulBitsToClear were cleared. - * \defgroup ulTaskNotifyValueClear ulTaskNotifyValueClear - * \ingroup TaskNotifications - */ -uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask, - UBaseType_t uxIndexToClear, - uint32_t ulBitsToClear ) - PRIVILEGED_FUNCTION; -#define ulTaskNotifyValueClear( xTask, ulBitsToClear ) \ - ulTaskGenericNotifyValueClear( ( xTask ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulBitsToClear ) ) -#define ulTaskNotifyValueClearIndexed( xTask, uxIndexToClear, ulBitsToClear ) \ - ulTaskGenericNotifyValueClear( ( xTask ), \ - ( uxIndexToClear ), \ - ( ulBitsToClear ) ) - -/** - * task.h - * @code{c} - * void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ); - * @endcode - * - * Capture the current time for future use with xTaskCheckForTimeOut(). - * - * @param pxTimeOut Pointer to a timeout object into which the current time - * is to be captured. The captured time includes the tick count and the number - * of times the tick count has overflowed since the system first booted. - * \defgroup vTaskSetTimeOutState vTaskSetTimeOutState - * \ingroup TaskCtrl - */ -void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * - * const pxTicksToWait ); - * @endcode - * - * Determines if pxTicksToWait ticks has passed since a time was captured - * using a call to vTaskSetTimeOutState(). The captured time includes the tick - * count and the number of times the tick count has overflowed. - * - * @param pxTimeOut The time status as captured previously using - * vTaskSetTimeOutState. If the timeout has not yet occurred, it is updated - * to reflect the current time status. - * @param pxTicksToWait The number of ticks to check for timeout i.e. if - * pxTicksToWait ticks have passed since pxTimeOut was last updated (either by - * vTaskSetTimeOutState() or xTaskCheckForTimeOut()), the timeout has occurred. - * If the timeout has not occurred, pxTicksToWait is updated to reflect the - * number of remaining ticks. - * - * @return If timeout has occurred, pdTRUE is returned. Otherwise pdFALSE is - * returned and pxTicksToWait is updated to reflect the number of remaining - * ticks. - * - * @see https://www.FreeRTOS.org/xTaskCheckForTimeOut.html - * - * Example Usage: - * @code{c} - * // Driver library function used to receive uxWantedBytes from an Rx buffer - * // that is filled by a UART interrupt. If there are not enough bytes in the - * // Rx buffer then the task enters the Blocked state until it is notified - * that - * // more data has been placed into the buffer. If there is still not enough - * // data then the task re-enters the Blocked state, and - * xTaskCheckForTimeOut() - * // is used to re-calculate the Block time to ensure the total amount of time - * // spent in the Blocked state does not exceed MAX_TIME_TO_WAIT. This - * // continues until either the buffer contains at least uxWantedBytes bytes, - * // or the total amount of time spent in the Blocked state reaches - * // MAX_TIME_TO_WAIT - at which point the task reads however many bytes are - * // available up to a maximum of uxWantedBytes. - * - * size_t xUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes ) - * { - * size_t uxReceived = 0; - * TickType_t xTicksToWait = MAX_TIME_TO_WAIT; - * TimeOut_t xTimeOut; - * - * // Initialize xTimeOut. This records the time at which this function - * // was entered. - * vTaskSetTimeOutState( &xTimeOut ); - * - * // Loop until the buffer contains the wanted number of bytes, or a - * // timeout occurs. - * while( UART_bytes_in_rx_buffer( pxUARTInstance ) < uxWantedBytes ) - * { - * // The buffer didn't contain enough data so this task is going to - * // enter the Blocked state. Adjusting xTicksToWait to account for - * // any time that has been spent in the Blocked state within this - * // function so far to ensure the total amount of time spent in the - * // Blocked state does not exceed MAX_TIME_TO_WAIT. - * if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) != pdFALSE ) - * { - * //Timed out before the wanted number of bytes were available, - * // exit the loop. - * break; - * } - * - * // Wait for a maximum of xTicksToWait ticks to be notified that the - * // receive interrupt has placed more data into the buffer. - * ulTaskNotifyTake( pdTRUE, xTicksToWait ); - * } - * - * // Attempt to read uxWantedBytes from the receive buffer into pucBuffer. - * // The actual number of bytes read (which might be less than - * // uxWantedBytes) is returned. - * uxReceived = UART_read_from_receive_buffer( pxUARTInstance, - * pucBuffer, - * uxWantedBytes ); - * - * return uxReceived; - * } - * @endcode - * \defgroup xTaskCheckForTimeOut xTaskCheckForTimeOut - * \ingroup TaskCtrl - */ -BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, - TickType_t * const pxTicksToWait ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ); - * @endcode - * - * This function corrects the tick count value after the application code has - * held interrupts disabled for an extended period resulting in tick interrupts - * having been missed. - * - * This function is similar to vTaskStepTick(), however, unlike - * vTaskStepTick(), xTaskCatchUpTicks() may move the tick count forward past a - * time at which a task should be removed from the blocked state. That means - * tasks may have to be removed from the blocked state as the tick count is - * moved. - * - * @param xTicksToCatchUp The number of tick interrupts that have been missed - * due to interrupts being disabled. Its value is not computed automatically, - * so must be computed by the application writer. - * - * @return pdTRUE if moving the tick count forward resulted in a task leaving - * the blocked state and a context switch being performed. Otherwise pdFALSE. - * - * \defgroup xTaskCatchUpTicks xTaskCatchUpTicks - * \ingroup TaskCtrl - */ -BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- - * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES - *----------------------------------------------------------*/ - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY - * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS - * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * Called from the real time kernel tick (either preemptive or cooperative), - * this increments the tick count and checks if any tasks that are blocked - * for a finite period required removing from a blocked list and placing on - * a ready list. If a non-zero value is returned then a context switch is - * required because either: - * + A task was removed from a blocked list because its timeout had expired, - * or - * + Time slicing is in use and there is a task of equal priority to the - * currently running task. - */ -BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * Removes the calling task from the ready list and places it both - * on the list of tasks waiting for a particular event, and the - * list of delayed tasks. The task will be removed from both lists - * and replaced on the ready list should either the event occur (and - * there be no higher priority tasks waiting on the same event) or - * the delay period expires. - * - * The 'unordered' version replaces the event list item value with the - * xItemValue value, and inserts the list item at the end of the list. - * - * The 'ordered' version uses the existing event list item value (which is the - * owning task's priority) to insert the list item into the event list in task - * priority order. - * - * @param pxEventList The list containing tasks that are blocked waiting - * for the event to occur. - * - * @param xItemValue The item value to use for the event list item when the - * event list is not ordered by task priority. - * - * @param xTicksToWait The maximum amount of time that the task should wait - * for the event to occur. This is specified in kernel ticks, the constant - * portTICK_PERIOD_MS can be used to convert kernel ticks into a real time - * period. - */ -void vTaskPlaceOnEventList( List_t * const pxEventList, - const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, - const TickType_t xItemValue, - const TickType_t xTicksToWait ) - PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * This function performs nearly the same function as vTaskPlaceOnEventList(). - * The difference being that this function does not permit tasks to block - * indefinitely, whereas vTaskPlaceOnEventList() does. - * - */ -void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, - TickType_t xTicksToWait, - const BaseType_t xWaitIndefinitely ) - PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * Removes a task from both the specified event list and the list of blocked - * tasks, and places it on a ready queue. - * - * xTaskRemoveFromEventList()/vTaskRemoveFromUnorderedEventList() will be called - * if either an event occurs to unblock a task, or the block timeout period - * expires. - * - * xTaskRemoveFromEventList() is used when the event list is in task priority - * order. It removes the list item from the head of the event list as that will - * have the highest priority owning task of all the tasks on the event list. - * vTaskRemoveFromUnorderedEventList() is used when the event list is not - * ordered and the event list items hold something other than the owning tasks - * priority. In this case the event list item value is updated to the value - * passed in the xItemValue parameter. - * - * @return pdTRUE if the task being removed has a higher priority than the task - * making the call, otherwise pdFALSE. - */ -BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) - PRIVILEGED_FUNCTION; -void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, - const TickType_t xItemValue ) - PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY - * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS - * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * Sets the pointer to the current TCB to the TCB of the highest priority task - * that is ready to run. - */ -#if( configNUMBER_OF_CORES == 1 ) -portDONT_DISCARD void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; -#else -portDONT_DISCARD void vTaskSwitchContext( BaseType_t xCoreID ) - PRIVILEGED_FUNCTION; -#endif - -/* - * THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY - * THE EVENT BITS MODULE. - */ -TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION; - -/* - * Return the handle of the calling task. - */ -TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; - -/* - * Return the handle of the task running on specified core. - */ -TaskHandle_t xTaskGetCurrentTaskHandleCPU( BaseType_t xCoreID ) - PRIVILEGED_FUNCTION; - -/* - * Shortcut used by the queue implementation to prevent unnecessary call to - * taskYIELD(); - */ -void vTaskMissedYield( void ) PRIVILEGED_FUNCTION; - -/* - * Returns the scheduler state as taskSCHEDULER_RUNNING, - * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. - */ -BaseType_t xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION; - -/* - * Raises the priority of the mutex holder to that of the calling task should - * the mutex holder have a priority less than the calling task. - */ -BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) - PRIVILEGED_FUNCTION; - -/* - * Set the priority of a task back to its proper priority in the case that it - * inherited a higher priority while it was holding a semaphore. - */ -BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) - PRIVILEGED_FUNCTION; - -/* - * If a higher priority task attempting to obtain a mutex caused a lower - * priority task to inherit the higher priority task's priority - but the higher - * priority task then timed out without obtaining the mutex, then the lower - * priority task will disinherit the priority again - but only down as far as - * the highest priority task that is still waiting for the mutex (if there were - * more than one task waiting for the mutex). - */ -void vTaskPriorityDisinheritAfterTimeout( - TaskHandle_t const pxMutexHolder, - UBaseType_t uxHighestPriorityWaitingTask ) PRIVILEGED_FUNCTION; - -/* - * Get the uxTaskNumber assigned to the task referenced by the xTask parameter. - */ -UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/* - * Set the uxTaskNumber of the task referenced by the xTask parameter to - * uxHandle. - */ -void vTaskSetTaskNumber( TaskHandle_t xTask, - const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION; - -/* - * Only available when configUSE_TICKLESS_IDLE is set to 1. - * If tickless mode is being used, or a low power mode is implemented, then - * the tick interrupt will not execute during idle periods. When this is the - * case, the tick count value maintained by the scheduler needs to be kept up - * to date with the actual execution time by being skipped forward by a time - * equal to the idle period. - */ -void vTaskStepTick( TickType_t xTicksToJump ) PRIVILEGED_FUNCTION; - -/* - * Only available when configUSE_TICKLESS_IDLE is set to 1. - * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port - * specific sleep function to determine if it is ok to proceed with the sleep, - * and if it is ok to proceed, if it is ok to sleep indefinitely. - * - * This function is necessary because portSUPPRESS_TICKS_AND_SLEEP() is only - * called with the scheduler suspended, not from within a critical section. It - * is therefore possible for an interrupt to request a context switch between - * portSUPPRESS_TICKS_AND_SLEEP() and the low power mode actually being - * entered. eTaskConfirmSleepModeStatus() should be called from a short - * critical section between the timer being stopped and the sleep mode being - * entered to ensure it is ok to proceed into the sleep mode. - */ -eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION; - -/* - * For internal use only. Increment the mutex held count when a mutex is - * taken and return the handle of the task that has taken the mutex. - */ -TaskHandle_t pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION; - -/* - * For internal use only. Same as vTaskSetTimeOutState(), but without a - * critical section. - */ -void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) - PRIVILEGED_FUNCTION; - -/* - * For internal use only. Same as portYIELD_WITHIN_API() in single core - * FreeRTOS. For SMP this is not defined by the port. - */ -void vTaskYieldWithinAPI( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when portCRITICAL_NESTING_IN_TCB is set to 1 - * or configNUMBER_OF_CORES is greater than 1. This function can be used in the - * implementation of portENTER_CRITICAL if port wants to maintain critical - * nesting count in TCB in single core FreeRTOS. It should be used in the - * implementation of portENTER_CRITICAL if port is running a multiple core - * FreeRTOS. - */ -void vTaskEnterCritical( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when portCRITICAL_NESTING_IN_TCB is set to 1 - * or configNUMBER_OF_CORES is greater than 1. This function can be used in the - * implementation of portEXIT_CRITICAL if port wants to maintain critical - * nesting count in TCB in single core FreeRTOS. It should be used in the - * implementation of portEXIT_CRITICAL if port is running a multiple core - * FreeRTOS. - */ -void vTaskExitCritical( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when configNUMBER_OF_CORES is greater than 1. - * This function should be used in the implementation of - * portENTER_CRITICAL_FROM_ISR if port is running a multiple core FreeRTOS. - */ -UBaseType_t vTaskEnterCriticalFromISR( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when configNUMBER_OF_CORES is greater than 1. - * This function should be used in the implementation of - * portEXIT_CRITICAL_FROM_ISR if port is running a multiple core FreeRTOS. - */ -void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus ); - -#if( portUSING_MPU_WRAPPERS == 1 ) - -/* - * For internal use only. Get MPU settings associated with a task. - */ -xMPU_SETTINGS * xTaskGetMPUSettings( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -#endif /* portUSING_MPU_WRAPPERS */ - -/* *INDENT-OFF* */ -#ifdef __cplusplus -} -#endif -/* *INDENT-ON* */ -#endif /* INC_TASK_H */ diff --git a/formatting/goodFiles/include/formatErrorTest.h b/formatting/goodFiles/include/formatErrorTest.h deleted file mode 100644 index 3c540dc7..00000000 --- a/formatting/goodFiles/include/formatErrorTest.h +++ /dev/null @@ -1,3761 +0,0 @@ -/* - * FreeRTOS Kernel - * 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 - * - */ - -#ifndef INC_TASK_H -#define INC_TASK_H - -#ifndef INC_FREERTOS_H - #error \ - "include FreeRTOS.h must appear in source files before include task.h" -#endif - -#include "list.h" - -/* *INDENT-OFF* */ -#ifdef __cplusplus -extern "C" { -#endif -/* *INDENT-ON* */ - -/*----------------------------------------------------------- - * MACROS AND DEFINITIONS - *----------------------------------------------------------*/ - -/* - * If tskKERNEL_VERSION_NUMBER ends with + it represents the version in - * development after the numbered release. - * - * The tskKERNEL_VERSION_MAJOR, tskKERNEL_VERSION_MINOR, tskKERNEL_VERSION_BUILD - * values will reflect the last released version number. - */ -#define tskKERNEL_VERSION_NUMBER "V10.4.4+" -#define tskKERNEL_VERSION_MAJOR 10 -#define tskKERNEL_VERSION_MINOR 4 -#define tskKERNEL_VERSION_BUILD 4 - -/* MPU region parameters passed in ulParameters - * of MemoryRegion_t struct. */ -#define tskMPU_REGION_READ_ONLY ( 1UL << 0UL ) -#define tskMPU_REGION_READ_WRITE ( 1UL << 1UL ) -#define tskMPU_REGION_EXECUTE_NEVER ( 1UL << 2UL ) -#define tskMPU_REGION_NORMAL_MEMORY ( 1UL << 3UL ) -#define tskMPU_REGION_DEVICE_MEMORY ( 1UL << 4UL ) - -/* MPU region permissions stored in MPU settings to - * authorize access requests. */ -#define tskMPU_READ_PERMISSION ( 1UL << 0UL ) -#define tskMPU_WRITE_PERMISSION ( 1UL << 1UL ) - -/* The direct to task notification feature used to have only a single - * notification per task. Now there is an array of notifications per task that - * is dimensioned by configTASK_NOTIFICATION_ARRAY_ENTRIES. For backward - * compatibility, any use of the original direct to task notification defaults - * to using the first index in the array. */ -#define tskDEFAULT_INDEX_TO_NOTIFY ( 0 ) - -/** - * task. h - * - * Type by which tasks are referenced. For example, a call to xTaskCreate - * returns (via a pointer parameter) an TaskHandle_t variable that can then - * be used as a parameter to vTaskDelete to delete the task. - * - * \defgroup TaskHandle_t TaskHandle_t - * \ingroup Tasks - */ -struct tskTaskControlBlock; /* The old naming convention is used to prevent - breaking kernel aware debuggers. */ -typedef struct tskTaskControlBlock * TaskHandle_t; -typedef const struct tskTaskControlBlock * ConstTaskHandle_t; - -/* - * Defines the prototype to which the application task hook function must - * conform. - */ -typedef BaseType_t ( *TaskHookFunction_t )( void * ); - -/* Task states returned by eTaskGetState. */ -typedef enum -{ - eRunning = 0, /* A task is querying the state of itself, so must be running. - */ - eReady, /* The task being queried is in a ready or pending ready list. */ - eBlocked, /* The task being queried is in the Blocked state. */ - eSuspended, /* The task being queried is in the Suspended state, or is in - the Blocked state with an infinite time out. */ - eDeleted, /* The task being queried has been deleted, but its TCB has not - yet been freed. */ - eInvalid /* Used as an 'invalid state' value. */ -} eTaskState; - -/* Actions that can be performed when vTaskNotify() is called. */ -typedef enum -{ - eNoAction = 0, /* Notify the task without updating its notify value. */ - eSetBits, /* Set bits in the task's notification value. */ - eIncrement, /* Increment the task's notification value. */ - eSetValueWithOverwrite, /* Set the task's notification value to a specific - value even if the previous value has not yet been - read by the task. */ - eSetValueWithoutOverwrite /* Set the task's notification value if the - previous value has been read by the task. */ -} eNotifyAction; - -/* - * Used internally only. - */ -typedef struct xTIME_OUT -{ - BaseType_t xOverflowCount; - TickType_t xTimeOnEntering; -} TimeOut_t; - -/* - * Defines the memory ranges allocated to the task when an MPU is used. - */ -typedef struct xMEMORY_REGION -{ - void * pvBaseAddress; - uint32_t ulLengthInBytes; - uint32_t ulParameters; -} MemoryRegion_t; - -/* - * Parameters required to create an MPU protected task. - */ -typedef struct xTASK_PARAMETERS -{ - TaskFunction_t pvTaskCode; - const char * pcName; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - configSTACK_DEPTH_TYPE usStackDepth; - void * pvParameters; - UBaseType_t uxPriority; - StackType_t * puxStackBuffer; - MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ]; -#if( ( portUSING_MPU_WRAPPERS == 1 ) && \ - ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - StaticTask_t * const pxTaskBuffer; -#endif -} TaskParameters_t; - -/* Used with the uxTaskGetSystemState() function to return the state of each - * task in the system. */ -typedef struct xTASK_STATUS -{ - TaskHandle_t xHandle; /* The handle of the task to which the rest of the - information in the structure relates. */ - const char * pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - UBaseType_t xTaskNumber; /* A number unique to the task. */ - eTaskState eCurrentState; /* The state in which the task existed when the - structure was populated. */ - UBaseType_t uxCurrentPriority; /* The priority at which the task was running - (may be inherited) when the structure was - populated. */ - UBaseType_t uxBasePriority; /* The priority to which the task will return if - the task's current priority has been - inherited to avoid unbounded priority - inversion when obtaining a mutex. Only valid - if configUSE_MUTEXES is defined as 1 in - FreeRTOSConfig.h. */ - configRUN_TIME_COUNTER_TYPE - ulRunTimeCounter; /* The total run time - allocated to the task so - far, as defined by the run - time stats clock. See - https://www.FreeRTOS.org/rtos-run-time-stats.html. - Only valid when - configGENERATE_RUN_TIME_STATS - is defined as 1 in - FreeRTOSConfig.h. */ - StackType_t * pxStackBase; /* Points to the lowest address of the task's - stack area. */ -#if( ( portSTACK_GROWTH > 0 ) && ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) - StackType_t * pxTopOfStack; /* Points to the top address of the task's stack - area. */ - StackType_t * pxEndOfStack; /* Points to the end address of the task's stack - area. */ -#endif - configSTACK_DEPTH_TYPE usStackHighWaterMark; /* The minimum amount of stack - space that has remained for - the task since the task was - created. The closer this - value is to zero the closer - the task has come to - overflowing its stack. */ -#if( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - UBaseType_t uxCoreAffinityMask; /* The core affinity mask for the task */ -#endif -} TaskStatus_t; - -/* Possible return values for eTaskConfirmSleepModeStatus(). */ -typedef enum -{ - eAbortSleep = 0, /* A task has been made ready or a context switch pended - since portSUPPRESS_TICKS_AND_SLEEP() was called - abort - entering a sleep mode. */ - eStandardSleep, /* Enter a sleep mode that will not last any longer than the - expected idle time. */ -#if( INCLUDE_vTaskSuspend == 1 ) - eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe - to enter a sleep mode that can only be exited by - an external interrupt. */ -#endif /* INCLUDE_vTaskSuspend */ -} eSleepModeStatus; - -/** - * Defines the priority used by the idle task. This must not be modified. - * - * \ingroup TaskUtils - */ -#define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U ) - -/** - * Defines affinity to all available cores. - * - * \ingroup TaskUtils - */ -#define tskNO_AFFINITY ( ( UBaseType_t ) -1 ) - -/** - * task. h - * - * Macro for forcing a context switch. - * - * \defgroup taskYIELD taskYIELD - * \ingroup SchedulerControl - */ -#define taskYIELD() portYIELD() - -/** - * task. h - * - * Macro to mark the start of a critical code region. Preemptive context - * switches cannot occur when in a critical region. - * - * NOTE: This may alter the stack (depending on the portable implementation) - * so must be used with care! - * - * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL - * \ingroup SchedulerControl - */ -#define taskENTER_CRITICAL() portENTER_CRITICAL() -#if( configNUMBER_OF_CORES == 1 ) - #define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() -#else - #define taskENTER_CRITICAL_FROM_ISR() portENTER_CRITICAL_FROM_ISR() -#endif - -/** - * task. h - * - * Macro to mark the end of a critical code region. Preemptive context - * switches cannot occur when in a critical region. - * - * NOTE: This may alter the stack (depending on the portable implementation) - * so must be used with care! - * - * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL - * \ingroup SchedulerControl - */ -#define taskEXIT_CRITICAL() portEXIT_CRITICAL() -#if( configNUMBER_OF_CORES == 1 ) - #define taskEXIT_CRITICAL_FROM_ISR( x ) \ - portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) -#else - #define taskEXIT_CRITICAL_FROM_ISR( x ) portEXIT_CRITICAL_FROM_ISR( x ) -#endif - -/** - * task. h - * - * Macro to disable all maskable interrupts. - * - * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS - * \ingroup SchedulerControl - */ -#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() - -/** - * task. h - * - * Macro to enable microcontroller interrupts. - * - * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS - * \ingroup SchedulerControl - */ -#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() - -/* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is - * 0 to generate more optimal code when configASSERT() is defined as the - * constant is used in assert() statements. */ -#define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 ) -#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 ) -#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 ) - -/* Checks if core ID is valid. */ -#define taskVALID_CORE_ID( xCoreID ) \ - ( ( ( ( ( BaseType_t ) 0 <= ( xCoreID ) ) && \ - ( ( xCoreID ) < ( BaseType_t ) configNUMBER_OF_CORES ) ) ) \ - ? ( pdTRUE ) \ - : ( pdFALSE ) ) - -/*----------------------------------------------------------- - * TASK CREATION API - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * BaseType_t xTaskCreate( - * TaskFunction_t pxTaskCode, - * const char *pcName, - * configSTACK_DEPTH_TYPE usStackDepth, - * void *pvParameters, - * UBaseType_t uxPriority, - * TaskHandle_t *pxCreatedTask - * ); - * @endcode - * - * Create a new task and add it to the list of tasks that are ready to run. - * - * Internally, within the FreeRTOS implementation, tasks use two blocks of - * memory. The first block is used to hold the task's data structures. The - * second block is used by the task as its stack. If a task is created using - * xTaskCreate() then both blocks of memory are automatically dynamically - * allocated inside the xTaskCreate() function. (see - * https://www.FreeRTOS.org/a00111.html). If a task is created using - * xTaskCreateStatic() then the application writer must provide the required - * memory. xTaskCreateStatic() therefore allows a task to be created without - * using any dynamic memory allocation. - * - * See xTaskCreateStatic() for a version that does not use any dynamic memory - * allocation. - * - * xTaskCreate() can only be used to create a task that has unrestricted - * access to the entire microcontroller memory map. Systems that include MPU - * support can alternatively create an MPU constrained task using - * xTaskCreateRestricted(). - * - * @param pxTaskCode Pointer to the task entry function. Tasks - * must be implemented to never return (i.e. continuous loop). - * - * @param pcName A descriptive name for the task. This is mainly used to - * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - - * default is 16. - * - * @param usStackDepth The size of the task stack specified as the number of - * variables the stack can hold - not the number of bytes. For example, if - * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes - * will be allocated for stack storage. - * - * @param pvParameters Pointer that will be used as the parameter for the task - * being created. - * - * @param uxPriority The priority at which the task should run. Systems that - * include MPU support can optionally create tasks in a privileged (system) - * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For - * example, to create a privileged task at priority 2 the uxPriority parameter - * should be set to ( 2 | portPRIVILEGE_BIT ). - * - * @param pxCreatedTask Used to pass back a handle by which the created task - * can be referenced. - * - * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file projdefs.h - * - * Example usage: - * @code{c} - * // Task to be created. - * void vTaskCode( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * } - * } - * - * // Function that creates a task. - * void vOtherFunction( void ) - * { - * static uint8_t ucParameterToPass; - * TaskHandle_t xHandle = NULL; - * - * // Create the task, storing the handle. Note that the passed parameter - * ucParameterToPass - * // must exist for the lifetime of the task, so in this case is declared - * static. If it was just an - * // an automatic stack variable it might no longer exist, or at least have - * been corrupted, by the time - * // the new task attempts to access it. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, - * tskIDLE_PRIORITY, &xHandle ); configASSERT( xHandle ); - * - * // Use the handle to delete the task. - * if( xHandle != NULL ) - * { - * vTaskDelete( xHandle ); - * } - * } - * @endcode - * \defgroup xTaskCreate xTaskCreate - * \ingroup Tasks - */ -#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 ) PRIVILEGED_FUNCTION; -#endif - -#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && \ - ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) -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 ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, - * const char *pcName, - * uint32_t ulStackDepth, - * void *pvParameters, - * UBaseType_t uxPriority, - * StackType_t *puxStackBuffer, - * StaticTask_t *pxTaskBuffer ); - * @endcode - * - * Create a new task and add it to the list of tasks that are ready to run. - * - * Internally, within the FreeRTOS implementation, tasks use two blocks of - * memory. The first block is used to hold the task's data structures. The - * second block is used by the task as its stack. If a task is created using - * xTaskCreate() then both blocks of memory are automatically dynamically - * allocated inside the xTaskCreate() function. (see - * https://www.FreeRTOS.org/a00111.html). If a task is created using - * xTaskCreateStatic() then the application writer must provide the required - * memory. xTaskCreateStatic() therefore allows a task to be created without - * using any dynamic memory allocation. - * - * @param pxTaskCode Pointer to the task entry function. Tasks - * must be implemented to never return (i.e. continuous loop). - * - * @param pcName A descriptive name for the task. This is mainly used to - * facilitate debugging. The maximum length of the string is defined by - * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h. - * - * @param ulStackDepth The size of the task stack specified as the number of - * variables the stack can hold - not the number of bytes. For example, if - * the stack is 32-bits wide and ulStackDepth is defined as 100 then 400 bytes - * will be allocated for stack storage. - * - * @param pvParameters Pointer that will be used as the parameter for the task - * being created. - * - * @param uxPriority The priority at which the task will run. - * - * @param puxStackBuffer Must point to a StackType_t array that has at least - * ulStackDepth indexes - the array will then be used as the task's stack, - * removing the need for the stack to be allocated dynamically. - * - * @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will - * then be used to hold the task's data structures, removing the need for the - * memory to be allocated dynamically. - * - * @return If neither puxStackBuffer nor pxTaskBuffer are NULL, then the task - * will be created and a handle to the created task is returned. If either - * puxStackBuffer or pxTaskBuffer are NULL then the task will not be created and - * NULL is returned. - * - * Example usage: - * @code{c} - * - * // Dimensions of the buffer that the task being created will use as its - stack. - * // NOTE: This is the number of words the stack will hold, not the number of - * // bytes. For example, if each stack item is 32-bits, and this is set to - 100, - * // then 400 bytes (100 * 32-bits) will be allocated. - #define STACK_SIZE 200 - * - * // Structure that will hold the TCB of the task being created. - * StaticTask_t xTaskBuffer; - * - * // Buffer that the task being created will use as its stack. Note this is - * // an array of StackType_t variables. The size of StackType_t is dependent - on - * // the RTOS port. - * StackType_t xStack[ STACK_SIZE ]; - * - * // Function that implements the task being created. - * void vTaskCode( void * pvParameters ) - * { - * // The parameter value is expected to be 1 as 1 is passed in the - * // pvParameters value in the call to xTaskCreateStatic(). - * configASSERT( ( uint32_t ) pvParameters == 1UL ); - * - * for( ;; ) - * { - * // Task code goes here. - * } - * } - * - * // Function that creates a task. - * void vOtherFunction( void ) - * { - * TaskHandle_t xHandle = NULL; - * - * // Create the task without using any dynamic memory allocation. - * xHandle = xTaskCreateStatic( - * vTaskCode, // Function that implements the task. - * "NAME", // Text name for the task. - * STACK_SIZE, // Stack size in words, not bytes. - * ( void * ) 1, // Parameter passed into the task. - * tskIDLE_PRIORITY,// Priority at which the task is created. - * xStack, // Array to use as the task's stack. - * &xTaskBuffer ); // Variable to hold the task's data - structure. - * - * // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have - * // been created, and xHandle will be the task's handle. Use the handle - * // to suspend the task. - * vTaskSuspend( xHandle ); - * } - * @endcode - * \defgroup xTaskCreateStatic xTaskCreateStatic - * \ingroup Tasks - */ -#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 ) PRIVILEGED_FUNCTION; -#endif /* configSUPPORT_STATIC_ALLOCATION */ - -#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && \ - ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) -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 ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, - * TaskHandle_t *pxCreatedTask ); - * @endcode - * - * Only available when configSUPPORT_DYNAMIC_ALLOCATION is set to 1. - * - * xTaskCreateRestricted() should only be used in systems that include an MPU - * implementation. - * - * Create a new task and add it to the list of tasks that are ready to run. - * The function parameters define the memory regions and associated access - * permissions allocated to the task. - * - * See xTaskCreateRestrictedStatic() for a version that does not use any - * dynamic memory allocation. - * - * @param pxTaskDefinition Pointer to a structure that contains a member - * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API - * documentation) plus an optional stack buffer and the memory region - * definitions. - * - * @param pxCreatedTask Used to pass back a handle by which the created task - * can be referenced. - * - * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file projdefs.h - * - * Example usage: - * @code{c} - * // Create an TaskParameters_t structure that defines the task to be created. - * static const TaskParameters_t xCheckTaskParameters = - * { - * vATask, // pvTaskCode - the function that implements the task. - * "ATask", // pcName - just a text name for the task to assist debugging. - * 100, // usStackDepth - the stack size DEFINED IN WORDS. - * NULL, // pvParameters - passed into the task function as the function - * parameters. ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set - * the portPRIVILEGE_BIT if the task should run in a privileged state. - * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack. - * - * // xRegions - Allocate up to three separate memory regions for access by - * // the task, with appropriate access permissions. Different processors have - * // different memory alignment requirements - refer to the FreeRTOS - * documentation - * // for full information. - * { - * // Base address Length Parameters - * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE }, - * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY }, - * { cPrivilegedOnlyAccessArray, 128, - * portMPU_REGION_PRIVILEGED_READ_WRITE } - * } - * }; - * - * int main( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task from the const structure defined above. The task handle - * // is requested (the second parameter is not NULL) but in this case just for - * // demonstration purposes as its not actually used. - * xTaskCreateRestricted( &xRegTest1Parameters, &xHandle ); - * - * // Start the scheduler. - * vTaskStartScheduler(); - * - * // Will only get here if there was insufficient memory to create the idle - * // and/or timer task. - * for( ;; ); - * } - * @endcode - * \defgroup xTaskCreateRestricted xTaskCreateRestricted - * \ingroup Tasks - */ -#if( portUSING_MPU_WRAPPERS == 1 ) -BaseType_t xTaskCreateRestricted( - const TaskParameters_t * const pxTaskDefinition, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configNUMBER_OF_CORES > 1 ) && \ - ( configUSE_CORE_AFFINITY == 1 ) ) -BaseType_t xTaskCreateRestrictedAffinitySet( - const TaskParameters_t * const pxTaskDefinition, - UBaseType_t uxCoreAffinityMask, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * BaseType_t xTaskCreateRestrictedStatic( TaskParameters_t *pxTaskDefinition, - * TaskHandle_t *pxCreatedTask ); - * @endcode - * - * Only available when configSUPPORT_STATIC_ALLOCATION is set to 1. - * - * xTaskCreateRestrictedStatic() should only be used in systems that include an - * MPU implementation. - * - * Internally, within the FreeRTOS implementation, tasks use two blocks of - * memory. The first block is used to hold the task's data structures. The - * second block is used by the task as its stack. If a task is created using - * xTaskCreateRestricted() then the stack is provided by the application writer, - * and the memory used to hold the task's data structure is automatically - * dynamically allocated inside the xTaskCreateRestricted() function. If a task - * is created using xTaskCreateRestrictedStatic() then the application writer - * must provide the memory used to hold the task's data structures too. - * xTaskCreateRestrictedStatic() therefore allows a memory protected task to be - * created without using any dynamic memory allocation. - * - * @param pxTaskDefinition Pointer to a structure that contains a member - * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API - * documentation) plus an optional stack buffer and the memory region - * definitions. If configSUPPORT_STATIC_ALLOCATION is set to 1 the structure - * contains an additional member, which is used to point to a variable of type - * StaticTask_t - which is then used to hold the task's data structure. - * - * @param pxCreatedTask Used to pass back a handle by which the created task - * can be referenced. - * - * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file projdefs.h - * - * Example usage: - * @code{c} - * // Create an TaskParameters_t structure that defines the task to be created. - * // The StaticTask_t variable is only included in the structure when - * // configSUPPORT_STATIC_ALLOCATION is set to 1. The PRIVILEGED_DATA macro - * can - * // be used to force the variable into the RTOS kernel's privileged data area. - * static PRIVILEGED_DATA StaticTask_t xTaskBuffer; - * static const TaskParameters_t xCheckTaskParameters = - * { - * vATask, // pvTaskCode - the function that implements the task. - * "ATask", // pcName - just a text name for the task to assist debugging. - * 100, // usStackDepth - the stack size DEFINED IN WORDS. - * NULL, // pvParameters - passed into the task function as the function - * parameters. ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set - * the portPRIVILEGE_BIT if the task should run in a privileged state. - * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack. - * - * // xRegions - Allocate up to three separate memory regions for access by - * // the task, with appropriate access permissions. Different processors have - * // different memory alignment requirements - refer to the FreeRTOS - * documentation - * // for full information. - * { - * // Base address Length Parameters - * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE }, - * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY }, - * { cPrivilegedOnlyAccessArray, 128, - * portMPU_REGION_PRIVILEGED_READ_WRITE } - * } - * - * &xTaskBuffer; // Holds the task's data structure. - * }; - * - * int main( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task from the const structure defined above. The task handle - * // is requested (the second parameter is not NULL) but in this case just for - * // demonstration purposes as its not actually used. - * xTaskCreateRestrictedStatic( &xRegTest1Parameters, &xHandle ); - * - * // Start the scheduler. - * vTaskStartScheduler(); - * - * // Will only get here if there was insufficient memory to create the idle - * // and/or timer task. - * for( ;; ); - * } - * @endcode - * \defgroup xTaskCreateRestrictedStatic xTaskCreateRestrictedStatic - * \ingroup Tasks - */ -#if( ( portUSING_MPU_WRAPPERS == 1 ) && \ - ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) -BaseType_t xTaskCreateRestrictedStatic( - const TaskParameters_t * const pxTaskDefinition, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -#if( ( portUSING_MPU_WRAPPERS == 1 ) && \ - ( configSUPPORT_STATIC_ALLOCATION == 1 ) && \ - ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) -BaseType_t xTaskCreateRestrictedStaticAffinitySet( - const TaskParameters_t * const pxTaskDefinition, - UBaseType_t uxCoreAffinityMask, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * - * const pxRegions ); - * @endcode - * - * Memory regions are assigned to a restricted task when the task is created by - * a call to xTaskCreateRestricted(). These regions can be redefined using - * vTaskAllocateMPURegions(). - * - * @param xTask The handle of the task being updated. - * - * @param[in] pxRegions A pointer to a MemoryRegion_t structure that contains - * the new memory region definitions. - * - * Example usage: - * @code{c} - * // Define an array of MemoryRegion_t structures that configures an MPU region - * // allowing read/write access for 1024 bytes starting at the beginning of the - * // ucOneKByte array. The other two of the maximum 3 definable regions are - * // unused so set to zero. - * static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] = - * { - * // Base address Length Parameters - * { ucOneKByte, 1024, portMPU_REGION_READ_WRITE }, - * { 0, 0, 0 }, - * { 0, 0, 0 } - * }; - * - * void vATask( void *pvParameters ) - * { - * // This task was created such that it has access to certain regions of - * // memory as defined by the MPU configuration. At some point it is - * // desired that these MPU regions are replaced with that defined in the - * // xAltRegions const struct above. Use a call to vTaskAllocateMPURegions() - * // for this purpose. NULL is used as the task handle to indicate that this - * // function should modify the MPU regions of the calling task. - * vTaskAllocateMPURegions( NULL, xAltRegions ); - * - * // Now the task can continue its function, but from this point on can only - * // access its stack and the ucOneKByte array (unless any other statically - * // defined or shared regions have been declared elsewhere). - * } - * @endcode - * \defgroup vTaskAllocateMPURegions vTaskAllocateMPURegions - * \ingroup Tasks - */ -void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, - const MemoryRegion_t * const pxRegions ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskDelete( TaskHandle_t xTaskToDelete ); - * @endcode - * - * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Remove a task from the RTOS real time kernel's management. The task being - * deleted will be removed from all ready, blocked, suspended and event lists. - * - * NOTE: The idle task is responsible for freeing the kernel allocated - * memory from tasks that have been deleted. It is therefore important that - * the idle task is not starved of microcontroller processing time if your - * application makes any calls to vTaskDelete (). Memory allocated by the - * task code is not automatically freed, and should be freed before the task - * is deleted. - * - * See the demo application file death.c for sample code that utilises - * vTaskDelete (). - * - * @param xTaskToDelete The handle of the task to be deleted. Passing NULL will - * cause the calling task to be deleted. - * - * Example usage: - * @code{c} - * void vOtherFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create the task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // Use the handle to delete the task. - * vTaskDelete( xHandle ); - * } - * @endcode - * \defgroup vTaskDelete vTaskDelete - * \ingroup Tasks - */ -void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- - * TASK CONTROL API - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * void vTaskDelay( const TickType_t xTicksToDelay ); - * @endcode - * - * Delay a task for a given number of ticks. The actual time that the - * task remains blocked depends on the tick rate. The constant - * portTICK_PERIOD_MS can be used to calculate real time from the tick - * rate - with the resolution of one tick period. - * - * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * - * vTaskDelay() specifies a time at which the task wishes to unblock relative to - * the time at which vTaskDelay() is called. For example, specifying a block - * period of 100 ticks will cause the task to unblock 100 ticks after - * vTaskDelay() is called. vTaskDelay() does not therefore provide a good - * method of controlling the frequency of a periodic task as the path taken - * through the code, as well as other task and interrupt activity, will affect - * the frequency at which vTaskDelay() gets called and therefore the time at - * which the task next executes. See xTaskDelayUntil() for an alternative API - * function designed to facilitate fixed frequency execution. It does this by - * specifying an absolute time (rather than a relative time) at which the - * calling task should unblock. - * - * @param xTicksToDelay The amount of time, in tick periods, that - * the calling task should block. - * - * Example usage: - * - * void vTaskFunction( void * pvParameters ) - * { - * // Block for 500ms. - * const TickType_t xDelay = 500 / portTICK_PERIOD_MS; - * - * for( ;; ) - * { - * // Simply toggle the LED every 500ms, blocking between each toggle. - * vToggleLED(); - * vTaskDelay( xDelay ); - * } - * } - * - * \defgroup vTaskDelay vTaskDelay - * \ingroup TaskCtrl - */ -void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * BaseType_t xTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t - * xTimeIncrement ); - * @endcode - * - * INCLUDE_xTaskDelayUntil must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Delay a task until a specified time. This function can be used by periodic - * tasks to ensure a constant execution frequency. - * - * This function differs from vTaskDelay () in one important aspect: vTaskDelay - * () will cause a task to block for the specified number of ticks from the time - * vTaskDelay () is called. It is therefore difficult to use vTaskDelay () by - * itself to generate a fixed execution frequency as the time between a task - * starting to execute and that task calling vTaskDelay () may not be fixed [the - * task may take a different path though the code between calls, or may get - * interrupted or preempted a different number of times each time it executes]. - * - * Whereas vTaskDelay () specifies a wake time relative to the time at which the - * function is called, xTaskDelayUntil () specifies the absolute (exact) time at - * which it wishes to unblock. - * - * The macro pdMS_TO_TICKS() can be used to calculate the number of ticks from a - * time specified in milliseconds with a resolution of one tick period. - * - * @param pxPreviousWakeTime Pointer to a variable that holds the time at which - * the task was last unblocked. The variable must be initialised with the - * current time prior to its first use (see the example below). Following this - * the variable is automatically updated within xTaskDelayUntil (). - * - * @param xTimeIncrement The cycle time period. The task will be unblocked at - * time *pxPreviousWakeTime + xTimeIncrement. Calling xTaskDelayUntil with the - * same xTimeIncrement parameter value will cause the task to execute with - * a fixed interface period. - * - * @return Value which can be used to check whether the task was actually - * delayed. Will be pdTRUE if the task way delayed and pdFALSE otherwise. A - * task will not be delayed if the next expected wake time is in the past. - * - * Example usage: - * @code{c} - * // Perform an action every 10 ticks. - * void vTaskFunction( void * pvParameters ) - * { - * TickType_t xLastWakeTime; - * const TickType_t xFrequency = 10; - * BaseType_t xWasDelayed; - * - * // Initialise the xLastWakeTime variable with the current time. - * xLastWakeTime = xTaskGetTickCount (); - * for( ;; ) - * { - * // Wait for the next cycle. - * xWasDelayed = xTaskDelayUntil( &xLastWakeTime, xFrequency ); - * - * // Perform action here. xWasDelayed value can be used to determine - * // whether a deadline was missed if the code here took too long. - * } - * } - * @endcode - * \defgroup xTaskDelayUntil xTaskDelayUntil - * \ingroup TaskCtrl - */ -BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, - const TickType_t xTimeIncrement ) - PRIVILEGED_FUNCTION; - -/* - * vTaskDelayUntil() is the older version of xTaskDelayUntil() and does not - * return a value. - */ -#define vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ) \ - do \ - { \ - ( void ) xTaskDelayUntil( ( pxPreviousWakeTime ), \ - ( xTimeIncrement ) ); \ - } while( 0 ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskAbortDelay( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this - * function to be available. - * - * A task will enter the Blocked state when it is waiting for an event. The - * event it is waiting for can be a temporal event (waiting for a time), such - * as when vTaskDelay() is called, or an event on an object, such as when - * xQueueReceive() or ulTaskNotifyTake() is called. If the handle of a task - * that is in the Blocked state is used in a call to xTaskAbortDelay() then the - * task will leave the Blocked state, and return from whichever function call - * placed the task into the Blocked state. - * - * There is no 'FromISR' version of this function as an interrupt would need to - * know which object a task was blocked on in order to know which actions to - * take. For example, if the task was blocked on a queue the interrupt handler - * would then need to know if the queue was locked. - * - * @param xTask The handle of the task to remove from the Blocked state. - * - * @return If the task referenced by xTask was not in the Blocked state then - * pdFAIL is returned. Otherwise pdPASS is returned. - * - * \defgroup xTaskAbortDelay xTaskAbortDelay - * \ingroup TaskCtrl - */ -BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Obtain the priority of any task. - * - * @param xTask Handle of the task to be queried. Passing a NULL - * handle results in the priority of the calling task being returned. - * - * @return The priority of xTask. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to obtain the priority of the created task. - * // It was created with tskIDLE_PRIORITY, but may have changed - * // it itself. - * if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY ) - * { - * // The task has changed it's priority. - * } - * - * // ... - * - * // Is our priority higher than the created task? - * if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) ) - * { - * // Our priority (obtained using NULL handle) is higher. - * } - * } - * @endcode - * \defgroup uxTaskPriorityGet uxTaskPriorityGet - * \ingroup TaskCtrl - */ -UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ); - * @endcode - * - * A version of uxTaskPriorityGet() that can be used from an ISR. - */ -UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * eTaskState eTaskGetState( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Obtain the state of any task. States are encoded by the eTaskState - * enumerated type. - * - * @param xTask Handle of the task to be queried. - * - * @return The state of xTask at the time the function was called. Note the - * state of the task might change between the function being called, and the - * functions return value being tested by the calling task. - */ -eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t - * xGetFreeStackSpace, eTaskState eState ); - * @endcode - * - * configUSE_TRACE_FACILITY must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Populates a TaskStatus_t structure with information about a task. - * - * @param xTask Handle of the task being queried. If xTask is NULL then - * information will be returned about the calling task. - * - * @param pxTaskStatus A pointer to the TaskStatus_t structure that will be - * filled with information about the task referenced by the handle passed using - * the xTask parameter. - * - * @param xGetFreeStackSpace The TaskStatus_t structure contains a member to - * report the stack high water mark of the task being queried. Calculating the - * stack high water mark takes a relatively long time, and can make the system - * temporarily unresponsive - so the xGetFreeStackSpace parameter is provided to - * allow the high water mark checking to be skipped. The high watermark value - * will only be written to the TaskStatus_t structure if xGetFreeStackSpace is - * not set to pdFALSE; - * - * @param eState The TaskStatus_t structure contains a member to report the - * state of the task being queried. Obtaining the task state is not as fast as - * a simple assignment - so the eState parameter is provided to allow the state - * information to be omitted from the TaskStatus_t structure. To obtain state - * information then set eState to eInvalid - otherwise the value passed in - * eState will be reported as the task state in the TaskStatus_t structure. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * TaskStatus_t xTaskDetails; - * - * // Obtain the handle of a task from its name. - * xHandle = xTaskGetHandle( "Task_Name" ); - * - * // Check the handle is not NULL. - * configASSERT( xHandle ); - * - * // Use the handle to obtain further information about the task. - * vTaskGetInfo( xHandle, - * &xTaskDetails, - * pdTRUE, // Include the high water mark in xTaskDetails. - * eInvalid ); // Include the task state in xTaskDetails. - * } - * @endcode - * \defgroup vTaskGetInfo vTaskGetInfo - * \ingroup TaskCtrl - */ -void vTaskGetInfo( TaskHandle_t xTask, - TaskStatus_t * pxTaskStatus, - BaseType_t xGetFreeStackSpace, - eTaskState eState ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ); - * @endcode - * - * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Set the priority of any task. - * - * A context switch will occur before the function returns if the priority - * being set is higher than the currently executing task. - * - * @param xTask Handle to the task for which the priority is being set. - * Passing a NULL handle results in the priority of the calling task being set. - * - * @param uxNewPriority The priority to which the task will be set. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to raise the priority of the created task. - * vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 ); - * - * // ... - * - * // Use a NULL handle to raise our priority to the same value. - * vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 ); - * } - * @endcode - * \defgroup vTaskPrioritySet vTaskPrioritySet - * \ingroup TaskCtrl - */ -void vTaskPrioritySet( TaskHandle_t xTask, - UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskSuspend( TaskHandle_t xTaskToSuspend ); - * @endcode - * - * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Suspend any task. When suspended a task will never get any microcontroller - * processing time, no matter what its priority. - * - * Calls to vTaskSuspend are not accumulative - - * i.e. calling vTaskSuspend () twice on the same task still only requires one - * call to vTaskResume () to ready the suspended task. - * - * @param xTaskToSuspend Handle to the task being suspended. Passing a NULL - * handle will cause the calling task to be suspended. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to suspend the created task. - * vTaskSuspend( xHandle ); - * - * // ... - * - * // The created task will not run during this period, unless - * // another task calls vTaskResume( xHandle ). - * - * //... - * - * - * // Suspend ourselves. - * vTaskSuspend( NULL ); - * - * // We cannot get here unless another task calls vTaskResume - * // with our handle as the parameter. - * } - * @endcode - * \defgroup vTaskSuspend vTaskSuspend - * \ingroup TaskCtrl - */ -void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskResume( TaskHandle_t xTaskToResume ); - * @endcode - * - * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Resumes a suspended task. - * - * A task that has been suspended by one or more calls to vTaskSuspend () - * will be made available for running again by a single call to - * vTaskResume (). - * - * @param xTaskToResume Handle to the task being readied. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to suspend the created task. - * vTaskSuspend( xHandle ); - * - * // ... - * - * // The created task will not run during this period, unless - * // another task calls vTaskResume( xHandle ). - * - * //... - * - * - * // Resume the suspended task ourselves. - * vTaskResume( xHandle ); - * - * // The created task will once again get microcontroller processing - * // time in accordance with its priority within the system. - * } - * @endcode - * \defgroup vTaskResume vTaskResume - * \ingroup TaskCtrl - */ -void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void xTaskResumeFromISR( TaskHandle_t xTaskToResume ); - * @endcode - * - * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * An implementation of vTaskResume() that can be called from within an ISR. - * - * A task that has been suspended by one or more calls to vTaskSuspend () - * will be made available for running again by a single call to - * xTaskResumeFromISR (). - * - * xTaskResumeFromISR() should not be used to synchronise a task with an - * interrupt if there is a chance that the interrupt could arrive prior to the - * task being suspended - as this can lead to interrupts being missed. Use of a - * semaphore as a synchronisation mechanism would avoid this eventuality. - * - * @param xTaskToResume Handle to the task being readied. - * - * @return pdTRUE if resuming the task should result in a context switch, - * otherwise pdFALSE. This is used by the ISR to determine if a context switch - * may be required following the ISR. - * - * \defgroup vTaskResumeFromISR vTaskResumeFromISR - * \ingroup TaskCtrl - */ -BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; - -#if( configUSE_CORE_AFFINITY == 1 ) - -/** - * @brief Sets the core affinity mask for a task. - * - * It sets the cores on which a task can run. configUSE_CORE_AFFINITY must - * be defined as 1 for this function to be available. - * - * @param xTask The handle of the task to set the core affinity mask for. - * Passing NULL will set the core affinity mask for the calling task. - * - * @param uxCoreAffinityMask A bitwise value that indicates the cores on - * which the task can run. Cores are numbered from 0 to configNUMBER_OF_CORES - * - 1. For example, to ensure that a task can run on core 0 and core 1, set - * uxCoreAffinityMask to 0x03. - * - * Example usage: - * - * // The function that creates task. - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * UBaseType_t uxCoreAffinityMask; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &( - * xHandle ) ); - * - * // Define the core affinity mask such that this task can only run - * // on core 0 and core 2. - * uxCoreAffinityMask = ( ( 1 << 0 ) | ( 1 << 2 ) ); - * - * //Set the core affinity mask for the task. - * vTaskCoreAffinitySet( xHandle, uxCoreAffinityMask ); - * } - */ -void vTaskCoreAffinitySet( const TaskHandle_t xTask, - UBaseType_t uxCoreAffinityMask ); -#endif - -#if( configUSE_CORE_AFFINITY == 1 ) - -/** - * @brief Gets the core affinity mask for a task. - * - * configUSE_CORE_AFFINITY must be defined as 1 for this function to be - * available. - * - * @param xTask The handle of the task to get the core affinity mask for. - * Passing NULL will get the core affinity mask for the calling task. - * - * @return The core affinity mask which is a bitwise value that indicates - * the cores on which a task can run. Cores are numbered from 0 to - * configNUMBER_OF_CORES - 1. For example, if a task can run on core 0 and core - * 1, the core affinity mask is 0x03. - * - * Example usage: - * - * // Task handle of the networking task - it is populated elsewhere. - * TaskHandle_t xNetworkingTaskHandle; - * - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * UBaseType_t uxNetworkingCoreAffinityMask; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &( - * xHandle ) ); - * - * //Get the core affinity mask for the networking task. - * uxNetworkingCoreAffinityMask = vTaskCoreAffinityGet( - * xNetworkingTaskHandle ); - * - * // Here is a hypothetical scenario, just for the example. Assume that we - * // have 2 cores - Core 0 and core 1. We want to pin the application task - * to - * // the core different than the networking task to ensure that the - * // application task does not interfere with networking. - * if( ( uxNetworkingCoreAffinityMask & ( 1 << 0 ) ) != 0 ) - * { - * // The networking task can run on core 0, pin our task to core 1. - * vTaskCoreAffinitySet( xHandle, ( 1 << 1 ) ); - * } - * else - * { - * // Otherwise, pin our task to core 0. - * vTaskCoreAffinitySet( xHandle, ( 1 << 0 ) ); - * } - * } - */ -UBaseType_t vTaskCoreAffinityGet( ConstTaskHandle_t xTask ); -#endif - -#if( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - -/** - * @brief Disables preemption for a task. - * - * @param xTask The handle of the task to disable preemption. Passing NULL - * disables preemption for the calling task. - * - * Example usage: - * - * void vTaskCode( void *pvParameters ) - * { - * // Silence warnings about unused parameters. - * ( void ) pvParameters; - * - * for( ;; ) - * { - * // ... Perform some function here. - * - * // Disable preemption for this task. - * vTaskPreemptionDisable( NULL ); - * - * // The task will not be preempted when it is executing in this - * portion ... - * - * // ... until the preemption is enabled again. - * vTaskPreemptionEnable( NULL ); - * - * // The task can be preempted when it is executing in this portion. - * } - * } - */ -void vTaskPreemptionDisable( const TaskHandle_t xTask ); -#endif - -#if( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - -/** - * @brief Enables preemption for a task. - * - * @param xTask The handle of the task to enable preemption. Passing NULL - * enables preemption for the calling task. - * - * Example usage: - * - * void vTaskCode( void *pvParameters ) - * { - * // Silence warnings about unused parameters. - * ( void ) pvParameters; - * - * for( ;; ) - * { - * // ... Perform some function here. - * - * // Disable preemption for this task. - * vTaskPreemptionDisable( NULL ); - * - * // The task will not be preempted when it is executing in this - * portion ... - * - * // ... until the preemption is enabled again. - * vTaskPreemptionEnable( NULL ); - * - * // The task can be preempted when it is executing in this portion. - * } - * } - */ -void vTaskPreemptionEnable( const TaskHandle_t xTask ); -#endif - -/*----------------------------------------------------------- - * SCHEDULER CONTROL - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * void vTaskStartScheduler( void ); - * @endcode - * - * Starts the real time kernel tick processing. After calling the kernel - * has control over which tasks are executed and when. - * - * See the demo application file main.c for an example of creating - * tasks and starting the kernel. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * // Create at least one task before starting the kernel. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); - * - * // Start the real time kernel with preemption. - * vTaskStartScheduler (); - * - * // Will not get here unless a task calls vTaskEndScheduler () - * } - * @endcode - * - * \defgroup vTaskStartScheduler vTaskStartScheduler - * \ingroup SchedulerControl - */ -void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskEndScheduler( void ); - * @endcode - * - * NOTE: At the time of writing only the x86 real mode port, which runs on a PC - * in place of DOS, implements this function. - * - * Stops the real time kernel tick. All created tasks will be automatically - * deleted and multitasking (either preemptive or cooperative) will - * stop. Execution then resumes from the point where vTaskStartScheduler () - * was called, as if vTaskStartScheduler () had just returned. - * - * See the demo application file main. c in the demo/PC directory for an - * example that uses vTaskEndScheduler (). - * - * vTaskEndScheduler () requires an exit function to be defined within the - * portable layer (see vPortEndScheduler () in port. c for the PC port). This - * performs hardware specific operations such as stopping the kernel tick. - * - * vTaskEndScheduler () will cause all of the resources allocated by the - * kernel to be freed - but will not free resources allocated by application - * tasks. - * - * Example usage: - * @code{c} - * void vTaskCode( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // At some point we want to end the real time kernel processing - * // so call ... - * vTaskEndScheduler (); - * } - * } - * - * void vAFunction( void ) - * { - * // Create at least one task before starting the kernel. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); - * - * // Start the real time kernel with preemption. - * vTaskStartScheduler (); - * - * // Will only get here when the vTaskCode () task has called - * // vTaskEndScheduler (). When we get here we are back to single task - * // execution. - * } - * @endcode - * - * \defgroup vTaskEndScheduler vTaskEndScheduler - * \ingroup SchedulerControl - */ -void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskSuspendAll( void ); - * @endcode - * - * Suspends the scheduler without disabling interrupts. Context switches will - * not occur while the scheduler is suspended. - * - * After calling vTaskSuspendAll () the calling task will continue to execute - * without risk of being swapped out until a call to xTaskResumeAll () has been - * made. - * - * API functions that have the potential to cause a context switch (for example, - * xTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler - * is suspended. - * - * Example usage: - * @code{c} - * void vTask1( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // ... - * - * // At some point the task wants to perform a long operation during - * // which it does not want to get swapped out. It cannot use - * // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the - * // operation may cause interrupts to be missed - including the - * // ticks. - * - * // Prevent the real time kernel swapping out the task. - * vTaskSuspendAll (); - * - * // Perform the operation here. There is no need to use critical - * // sections as we have all the microcontroller processing time. - * // During this time interrupts will still operate and the kernel - * // tick count will be maintained. - * - * // ... - * - * // The operation is complete. Restart the kernel. - * xTaskResumeAll (); - * } - * } - * @endcode - * \defgroup vTaskSuspendAll vTaskSuspendAll - * \ingroup SchedulerControl - */ -void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * BaseType_t xTaskResumeAll( void ); - * @endcode - * - * Resumes scheduler activity after it was suspended by a call to - * vTaskSuspendAll(). - * - * xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks - * that were previously suspended by a call to vTaskSuspend(). - * - * @return If resuming the scheduler caused a context switch then pdTRUE is - * returned, otherwise pdFALSE is returned. - * - * Example usage: - * @code{c} - * void vTask1( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // ... - * - * // At some point the task wants to perform a long operation during - * // which it does not want to get swapped out. It cannot use - * // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the - * // operation may cause interrupts to be missed - including the - * // ticks. - * - * // Prevent the real time kernel swapping out the task. - * vTaskSuspendAll (); - * - * // Perform the operation here. There is no need to use critical - * // sections as we have all the microcontroller processing time. - * // During this time interrupts will still operate and the real - * // time kernel tick count will be maintained. - * - * // ... - * - * // The operation is complete. Restart the kernel. We want to force - * // a context switch - but there is no point if resuming the scheduler - * // caused a context switch already. - * if( !xTaskResumeAll () ) - * { - * taskYIELD (); - * } - * } - * } - * @endcode - * \defgroup xTaskResumeAll xTaskResumeAll - * \ingroup SchedulerControl - */ -BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- - * TASK UTILITIES - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * TickType_t xTaskGetTickCount( void ); - * @endcode - * - * @return The count of ticks since vTaskStartScheduler was called. - * - * \defgroup xTaskGetTickCount xTaskGetTickCount - * \ingroup TaskUtils - */ -TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * TickType_t xTaskGetTickCountFromISR( void ); - * @endcode - * - * @return The count of ticks since vTaskStartScheduler was called. - * - * This is a version of xTaskGetTickCount() that is safe to be called from an - * ISR - provided that TickType_t is the natural word size of the - * microcontroller being used or interrupt nesting is either not supported or - * not being used. - * - * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR - * \ingroup TaskUtils - */ -TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * uint16_t uxTaskGetNumberOfTasks( void ); - * @endcode - * - * @return The number of tasks that the real time kernel is currently managing. - * This includes all ready, blocked and suspended tasks. A task that - * has been deleted but not yet freed by the idle task will also be - * included in the count. - * - * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks - * \ingroup TaskUtils - */ -UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * char *pcTaskGetName( TaskHandle_t xTaskToQuery ); - * @endcode - * - * @return The text (human readable) name of the task referenced by the handle - * xTaskToQuery. A task can query its own name by either passing in its own - * handle, or by setting xTaskToQuery to NULL. - * - * \defgroup pcTaskGetName pcTaskGetName - * \ingroup TaskUtils - */ -char * pcTaskGetName( TaskHandle_t xTaskToQuery ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ); - * @endcode - * - * NOTE: This function takes a relatively long time to complete and should be - * used sparingly. - * - * @return The handle of the task that has the human readable name - * pcNameToQuery. NULL is returned if no matching name is found. - * INCLUDE_xTaskGetHandle must be set to 1 in FreeRTOSConfig.h for - * pcTaskGetHandle() to be available. - * - * \defgroup pcTaskGetHandle pcTaskGetHandle - * \ingroup TaskUtils - */ -TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask, - * StackType_t ** ppuxStackBuffer, - * StaticTask_t ** ppxTaskBuffer ); - * @endcode - * - * Retrieve pointers to a statically created task's data structure - * buffer and stack buffer. These are the same buffers that are supplied - * at the time of creation. - * - * @param xTask The task for which to retrieve the buffers. - * - * @param ppuxStackBuffer Used to return a pointer to the task's stack buffer. - * - * @param ppxTaskBuffer Used to return a pointer to the task's data structure - * buffer. - * - * @return pdTRUE if buffers were retrieved, pdFALSE otherwise. - * - * \defgroup xTaskGetStaticBuffers xTaskGetStaticBuffers - * \ingroup TaskUtils - */ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) -BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask, - StackType_t ** ppuxStackBuffer, - StaticTask_t ** ppxTaskBuffer ) - PRIVILEGED_FUNCTION; -#endif /* configSUPPORT_STATIC_ALLOCATION */ - -/** - * task.h - * @code{c} - * UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for - * this function to be available. - * - * Returns the high water mark of the stack associated with xTask. That is, - * the minimum free stack space there has been (in words, so on a 32 bit machine - * a value of 1 means 4 bytes) since the task started. The smaller the returned - * number the closer the task has come to overflowing its stack. - * - * 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. - * - * @param xTask Handle of the task associated with the stack to be checked. - * Set xTask to NULL to check the stack of the calling task. - * - * @return The smallest amount of free stack space there has been (in words, so - * actual spaces on the stack rather than bytes) since the task referenced by - * xTask was created. - */ -UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskGetStackHighWaterMark2 must be set to 1 in FreeRTOSConfig.h for - * this function to be available. - * - * Returns the high water mark of the stack associated with xTask. That is, - * the minimum free stack space there has been (in words, so on a 32 bit machine - * a value of 1 means 4 bytes) since the task started. The smaller the returned - * number the closer the task has come to overflowing its stack. - * - * 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. - * - * @param xTask Handle of the task associated with the stack to be checked. - * Set xTask to NULL to check the stack of the calling task. - * - * @return The smallest amount of free stack space there has been (in words, so - * actual spaces on the stack rather than bytes) since the task referenced by - * xTask was created. - */ -configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/* When using trace macros it is sometimes necessary to include task.h before - * FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been - * defined, so the following two prototypes will cause a compilation error. This - * can be fixed by simply guarding against the inclusion of these two prototypes - * unless they are explicitly required by the configUSE_APPLICATION_TASK_TAG - * configuration constant. */ -#ifdef configUSE_APPLICATION_TASK_TAG - #if configUSE_APPLICATION_TASK_TAG == 1 - -/** - * task.h - * @code{c} - * void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t - * pxHookFunction ); - * @endcode - * - * Sets pxHookFunction to be the task hook function used by the task xTask. - * Passing xTask as NULL has the effect of setting the calling tasks hook - * function. - */ -void vTaskSetApplicationTaskTag( TaskHandle_t xTask, - TaskHookFunction_t pxHookFunction ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * void xTaskGetApplicationTaskTag( TaskHandle_t xTask ); - * @endcode - * - * Returns the pxHookFunction value assigned to the task xTask. Do not - * call from an interrupt service routine - call - * xTaskGetApplicationTaskTagFromISR() instead. - */ -TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * void xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ); - * @endcode - * - * Returns the pxHookFunction value assigned to the task xTask. Can - * be called from an interrupt service routine. - */ -TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ -#endif /* ifdef configUSE_APPLICATION_TASK_TAG */ - -#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) - -/* Each task contains an array of pointers that is dimensioned by the - * configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. The - * kernel does not use the pointers itself, so the application writer can use - * the pointers for any purpose they wish. The following two functions are - * used to set and query a pointer respectively. */ -void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, - BaseType_t xIndex, - void * pvValue ) PRIVILEGED_FUNCTION; -void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, - BaseType_t xIndex ) - PRIVILEGED_FUNCTION; - -#endif - -#if( configCHECK_FOR_STACK_OVERFLOW > 0 ) - -/** - * task.h - * @code{c} - * void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName); - * @endcode - * - * The application stack overflow hook is called when a stack overflow is - * detected for a task. - * - * Details on stack overflow detection can be found here: - * https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html - * - * @param xTask the task that just exceeded its stack boundaries. - * @param pcTaskName A character string containing the name of the offending - * task. - */ -void vApplicationStackOverflowHook( TaskHandle_t xTask, char * pcTaskName ); - -#endif - -#if( configUSE_IDLE_HOOK == 1 ) - -/** - * task.h - * @code{c} - * void vApplicationIdleHook( void ); - * @endcode - * - * The application idle hook is called by the idle task. - * This allows the application designer to add background functionality without - * the overhead of a separate task. - * NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A - * FUNCTION THAT MIGHT BLOCK. - */ -void vApplicationIdleHook( void ); - -#endif - -#if( configUSE_TICK_HOOK != 0 ) - -/** - * task.h - * @code{c} - * void vApplicationTickHook( void ); - * @endcode - * - * This hook function is called in the system tick handler after any OS work is - * completed. - */ -void vApplicationTickHook( void ); /*lint !e526 Symbol not defined as it is an - application callback. */ - -#endif - -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) - -/** - * task.h - * @code{c} - * void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, - * StackType_t ** ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) - * @endcode - * - * This function is used to provide a statically allocated block of memory to - * FreeRTOS to hold the Idle Task TCB. This function is required when - * configSUPPORT_STATIC_ALLOCATION is set. For more information see this URI: - * https://www.FreeRTOS.org/a00110.html#configSUPPORT_STATIC_ALLOCATION - * - * @param ppxIdleTaskTCBBuffer A handle to a statically allocated TCB buffer - * @param ppxIdleTaskStackBuffer A handle to a statically allocated Stack buffer - * for the idle task - * @param pulIdleTaskStackSize A pointer to the number of elements that will fit - * in the allocated stack buffer - */ -void vApplicationGetIdleTaskMemory( - StaticTask_t ** ppxIdleTaskTCBBuffer, - StackType_t ** ppxIdleTaskStackBuffer, - uint32_t * pulIdleTaskStackSize ); /*lint !e526 Symbol not defined as it is - an application callback. */ -#endif - -/** - * task.h - * @code{c} - * BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void - * *pvParameter ); - * @endcode - * - * Calls the hook function associated with xTask. Passing xTask as NULL has - * the effect of calling the Running tasks (the calling task) hook function. - * - * pvParameter is passed to the hook function for the task to interpret as it - * wants. The return value is the value returned by the task hook function - * registered by the user. - */ -BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, - void * pvParameter ) - PRIVILEGED_FUNCTION; - -/** - * xTaskGetIdleTaskHandle() is only available if - * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. - * - * Simply returns the handle of the idle task. It is not valid to call - * xTaskGetIdleTaskHandle() before the scheduler has been started. - */ -TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; - -/** - * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for - * uxTaskGetSystemState() to be available. - * - * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in - * the system. TaskStatus_t structures contain, among other things, members - * for the task handle, task name, task priority, task state, and total amount - * of run time consumed by the task. See the TaskStatus_t structure - * definition in this file for the full member list. - * - * NOTE: This function is intended for debugging use only as its use results in - * the scheduler remaining suspended for an extended period. - * - * @param pxTaskStatusArray A pointer to an array of TaskStatus_t structures. - * The array must contain at least one TaskStatus_t structure for each task - * that is under the control of the RTOS. The number of tasks under the control - * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API - * function. - * - * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray - * parameter. The size is specified as the number of indexes in the array, or - * the number of TaskStatus_t structures contained in the array, not by the - * number of bytes in the array. - * - * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in - * FreeRTOSConfig.h then *pulTotalRunTime is set by uxTaskGetSystemState() to - * the total run time (as defined by the run time stats clock, see - * https://www.FreeRTOS.org/rtos-run-time-stats.html) since the target booted. - * pulTotalRunTime can be set to NULL to omit the total run time information. - * - * @return The number of TaskStatus_t structures that were populated by - * uxTaskGetSystemState(). This should equal the number returned by the - * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed - * in the uxArraySize parameter was too small. - * - * Example usage: - * @code{c} - * // This example demonstrates how a human readable table of run time stats - * // information is generated from raw data provided by - * uxTaskGetSystemState(). - * // The human readable table is written to pcWriteBuffer - * void vTaskGetRunTimeStats( char *pcWriteBuffer ) - * { - * TaskStatus_t *pxTaskStatusArray; - * volatile UBaseType_t uxArraySize, x; - * configRUN_TIME_COUNTER_TYPE ulTotalRunTime, ulStatsAsPercentage; - * - * // Make sure the write buffer does not contain a string. - * pcWriteBuffer = 0x00; - * - * // Take a snapshot of the number of tasks in case it changes while this - * // function is executing. - * uxArraySize = uxTaskGetNumberOfTasks(); - * - * // Allocate a TaskStatus_t structure for each task. An array could be - * // allocated statically at compile time. - * pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) - * ); - * - * if( pxTaskStatusArray != NULL ) - * { - * // Generate raw status information about each task. - * uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, - * &ulTotalRunTime ); - * - * // For percentage calculations. - * ulTotalRunTime /= 100UL; - * - * // Avoid divide by zero errors. - * if( ulTotalRunTime > 0 ) - * { - * // For each populated position in the pxTaskStatusArray array, - * // format the raw data as human readable ASCII 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. - * // ulTotalRunTimeDiv100 has already been divided by 100. - * ulStatsAsPercentage = pxTaskStatusArray[ x - * ].ulRunTimeCounter / ulTotalRunTime; - * - * if( ulStatsAsPercentage > 0UL ) - * { - * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", - * pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, - * ulStatsAsPercentage ); - * } - * else - * { - * // If the percentage is zero here then the task has - * // consumed less than 1% of the total run time. - * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", - * pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter ); - * } - * - * pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); - * } - * } - * - * // The array is no longer needed, free the memory it consumes. - * vPortFree( pxTaskStatusArray ); - * } - * } - * @endcode - */ -UBaseType_t uxTaskGetSystemState( - TaskStatus_t * const pxTaskStatusArray, - const UBaseType_t uxArraySize, - configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskList( char *pcWriteBuffer ); - * @endcode - * - * configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must - * both be defined as 1 for this function to be available. See the - * configuration section of the FreeRTOS.org website for more information. - * - * NOTE 1: This function will disable interrupts for its duration. It is - * not intended for normal application runtime use but as a debug aid. - * - * Lists all the current tasks, along with their current state and stack - * usage high water mark. - * - * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or - * suspended ('S'). - * - * 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(). - * - * @param pcWriteBuffer A buffer into which the above mentioned details - * will be written, in ASCII form. This buffer is assumed to be large - * enough to contain the generated report. Approximately 40 bytes per - * task should be sufficient. - * - * \defgroup vTaskList vTaskList - * \ingroup TaskUtils - */ -void vTaskList( char * pcWriteBuffer ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * void vTaskGetRunTimeStats( char *pcWriteBuffer ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS - * must both be defined as 1 for this function to be available. The application - * must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() - * to configure a peripheral timer/counter and return the timers current count - * value respectively. The counter should be at least 10 times the frequency of - * the tick count. - * - * NOTE 1: This function will disable interrupts for its duration. It is - * not intended for normal application runtime use but as a debug aid. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * Calling vTaskGetRunTimeStats() writes the total execution time of each - * task into a buffer, both as an absolute count value and as a percentage - * of the total system execution time. - * - * NOTE 2: - * - * 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(). - * - * @param pcWriteBuffer A buffer into which the execution times will be - * written, in ASCII form. This buffer is assumed to be large enough to - * contain the generated report. Approximately 40 bytes per task should - * be sufficient. - * - * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats - * \ingroup TaskUtils - */ -void vTaskGetRunTimeStats( char * pcWriteBuffer ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask - * ); configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t - * xTask ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS must be defined as 1 for these functions to be - * available. The application must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() to configure a peripheral timer/counter and - * return the timers current count value respectively. The counter should be - * at least 10 times the frequency of the tick count. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total - * execution time of each task into a buffer, ulTaskGetRunTimeCounter() - * returns the total execution time of just one task and - * ulTaskGetRunTimePercent() returns the percentage of the CPU time used by - * just one task. - * - * @return The total run time of the given task or the percentage of the total - * run time consumed by the given task. This is the amount of time the task - * has actually been executing. The unit of time is dependent on the frequency - * configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() macros. - * - * \defgroup ulTaskGetRunTimeCounter ulTaskGetRunTimeCounter - * \ingroup TaskUtils - */ -configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; -configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ); - * configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS must be defined as 1 for these functions to be - * available. The application must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() to configure a peripheral timer/counter and - * return the timers current count value respectively. The counter should be - * at least 10 times the frequency of the tick count. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total - * execution time of each task into a buffer, ulTaskGetIdleRunTimeCounter() - * returns the total execution time of just the idle task and - * ulTaskGetIdleRunTimePercent() returns the percentage of the CPU time used by - * just the idle task. - * - * Note the amount of idle time is only a good measure of the slack time in a - * system if there are no other tasks executing at the idle priority, tickless - * idle is not used, and configIDLE_SHOULD_YIELD is set to 0. - * - * @return The total run time of the idle task or the percentage of the total - * run time consumed by the idle task. This is the amount of time the - * idle task has actually been executing. The unit of time is dependent on the - * frequency configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() macros. - * - * \defgroup ulTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter - * \ingroup TaskUtils - */ -configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ) - PRIVILEGED_FUNCTION; -configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyIndexed( TaskHandle_t xTaskToNotify, UBaseType_t - * uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction ); BaseType_t - * xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction - * eAction ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * Sends a direct to task notification to a task, with an optional value and - * action. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * A task can use xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() to - * [optionally] block to wait for a notification to be pending. The task does - * not consume any CPU time while it is in the Blocked state. - * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their - * un-indexed equivalents). If the task was already in the Blocked state to - * wait for a notification when the notification arrives then the task will - * automatically be removed from the Blocked state (unblocked) and the - * notification cleared. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotify() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling xTaskNotify() is equivalent to calling xTaskNotifyIndexed() - * with the uxIndexToNotify parameter set to 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotify() does - * not have this parameter and always sends notifications to index 0. - * - * @param ulValue Data that can be sent with the notification. How the data is - * used depends on the value of the eAction parameter. - * - * @param eAction Specifies how the notification updates the task's notification - * value, if at all. Valid values for eAction are as follows: - * - * eSetBits - - * The target notification value is bitwise ORed with ulValue. - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * eIncrement - - * The target notification value is incremented. ulValue is not used and - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * eSetValueWithOverwrite - - * The target notification value is set to the value of ulValue, even if the - * task being notified had not yet processed the previous notification at the - * same array index (the task already had a notification pending at that index). - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * eSetValueWithoutOverwrite - - * If the task being notified did not already have a notification pending at the - * same array index then the target notification value is set to ulValue and - * xTaskNotifyIndexed() will return pdPASS. If the task being notified already - * had a notification pending at the same array index then no action is - * performed and pdFAIL is returned. - * - * eNoAction - - * The task receives a notification at the specified array index without the - * notification value at that index being updated. ulValue is not used and - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * pulPreviousNotificationValue - - * Can be used to pass out the subject task's notification value before any - * bits are modified by the notify function. - * - * @return Dependent on the value of eAction. See the description of the - * eAction parameter. - * - * \defgroup xTaskNotifyIndexed xTaskNotifyIndexed - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, - UBaseType_t uxIndexToNotify, - uint32_t ulValue, - eNotifyAction eAction, - uint32_t * pulPreviousNotificationValue ) - PRIVILEGED_FUNCTION; -#define xTaskNotify( xTaskToNotify, ulValue, eAction ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - NULL ) -#define xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - NULL ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyAndQueryIndexed( TaskHandle_t xTaskToNotify, - * UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, - * uint32_t *pulPreviousNotifyValue ); BaseType_t xTaskNotifyAndQuery( - * TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t - * *pulPreviousNotifyValue ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * xTaskNotifyAndQueryIndexed() performs the same operation as - * xTaskNotifyIndexed() with the addition that it also returns the subject - * task's prior notification value (the notification value at the time the - * function is called rather than when the function returns) in the additional - * pulPreviousNotifyValue parameter. - * - * xTaskNotifyAndQuery() performs the same operation as xTaskNotify() with the - * addition that it also returns the subject task's prior notification value - * (the notification value as it was at the time the function is called, rather - * than when the function returns) in the additional pulPreviousNotifyValue - * parameter. - * - * \defgroup xTaskNotifyAndQueryIndexed xTaskNotifyAndQueryIndexed - * \ingroup TaskNotifications - */ -#define xTaskNotifyAndQuery( xTaskToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotifyValue ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotifyValue ) ) -#define xTaskNotifyAndQueryIndexed( xTaskToNotify, \ - uxIndexToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotifyValue ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotifyValue ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t - * uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t - * *pxHigherPriorityTaskWoken ); BaseType_t xTaskNotifyFromISR( TaskHandle_t - * xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t - * *pxHigherPriorityTaskWoken ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * A version of xTaskNotifyIndexed() that can be used from an interrupt service - * routine (ISR). - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] - * block to wait for a notification value to have a non-zero value. The task - * does not consume any CPU time while it is in the Blocked state. - * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their - * un-indexed equivalents). If the task was already in the Blocked state to - * wait for a notification when the notification arrives then the task will - * automatically be removed from the Blocked state (unblocked) and the - * notification cleared. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyFromISR() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling xTaskNotifyFromISR() is equivalent to calling - * xTaskNotifyIndexedFromISR() with the uxIndexToNotify parameter set to 0. - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyFromISR() - * does not have this parameter and always sends notifications to index 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param ulValue Data that can be sent with the notification. How the data is - * used depends on the value of the eAction parameter. - * - * @param eAction Specifies how the notification updates the task's notification - * value, if at all. Valid values for eAction are as follows: - * - * eSetBits - - * The task's notification value is bitwise ORed with ulValue. xTaskNotify() - * always returns pdPASS in this case. - * - * eIncrement - - * The task's notification value is incremented. ulValue is not used and - * xTaskNotify() always returns pdPASS in this case. - * - * eSetValueWithOverwrite - - * The task's notification value is set to the value of ulValue, even if the - * task being notified had not yet processed the previous notification (the - * task already had a notification pending). xTaskNotify() always returns - * pdPASS in this case. - * - * eSetValueWithoutOverwrite - - * If the task being notified did not already have a notification pending then - * the task's notification value is set to ulValue and xTaskNotify() will - * return pdPASS. If the task being notified already had a notification - * pending then no action is performed and pdFAIL is returned. - * - * eNoAction - - * The task receives a notification without its notification value being - * updated. ulValue is not used and xTaskNotify() always returns pdPASS in - * this case. - * - * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set - * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the - * task to which the notification was sent to leave the Blocked state, and the - * unblocked task has a priority higher than the currently running task. If - * xTaskNotifyFromISR() sets this value to pdTRUE then a context switch should - * be requested before the interrupt is exited. How a context switch is - * requested from an ISR is dependent on the port - see the documentation page - * for the port in use. - * - * @return Dependent on the value of eAction. See the description of the - * eAction parameter. - * - * \defgroup xTaskNotifyIndexedFromISR xTaskNotifyIndexedFromISR - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, - UBaseType_t uxIndexToNotify, - uint32_t ulValue, - eNotifyAction eAction, - uint32_t * pulPreviousNotificationValue, - BaseType_t * pxHigherPriorityTaskWoken ) - PRIVILEGED_FUNCTION; -#define xTaskNotifyFromISR( xTaskToNotify, \ - ulValue, \ - eAction, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - NULL, \ - ( pxHigherPriorityTaskWoken ) ) -#define xTaskNotifyIndexedFromISR( xTaskToNotify, \ - uxIndexToNotify, \ - ulValue, \ - eAction, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - NULL, \ - ( pxHigherPriorityTaskWoken ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify, - * UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, - * uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken - * ); BaseType_t xTaskNotifyAndQueryFromISR( TaskHandle_t xTaskToNotify, - * uint32_t ulValue, eNotifyAction eAction, uint32_t - * *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * xTaskNotifyAndQueryIndexedFromISR() performs the same operation as - * xTaskNotifyIndexedFromISR() with the addition that it also returns the - * subject task's prior notification value (the notification value at the time - * the function is called rather than at the time the function returns) in the - * additional pulPreviousNotifyValue parameter. - * - * xTaskNotifyAndQueryFromISR() performs the same operation as - * xTaskNotifyFromISR() with the addition that it also returns the subject - * task's prior notification value (the notification value at the time the - * function is called rather than at the time the function returns) in the - * additional pulPreviousNotifyValue parameter. - * - * \defgroup xTaskNotifyAndQueryIndexedFromISR xTaskNotifyAndQueryIndexedFromISR - * \ingroup TaskNotifications - */ -#define xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, \ - uxIndexToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotificationValue, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotificationValue ), \ - ( pxHigherPriorityTaskWoken ) ) -#define xTaskNotifyAndQueryFromISR( xTaskToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotificationValue, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotificationValue ), \ - ( pxHigherPriorityTaskWoken ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyWaitIndexed( UBaseType_t uxIndexToWaitOn, uint32_t - * ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t - * *pulNotificationValue, TickType_t xTicksToWait ); - * - * BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t - * ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait - * ); - * @endcode - * - * Waits for a direct to task notification to be pending at a given index within - * an array of direct to task notifications. - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this - * function to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their - * un-indexed equivalents). If the task was already in the Blocked state to - * wait for a notification when the notification arrives then the task will - * automatically be removed from the Blocked state (unblocked) and the - * notification cleared. - * - * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] - * block to wait for a notification value to have a non-zero value. The task - * does not consume any CPU time while it is in the Blocked state. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyWait() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling xTaskNotifyWait() is equivalent to calling - * xTaskNotifyWaitIndexed() with the uxIndexToWaitOn parameter set to 0. - * - * @param uxIndexToWaitOn The index within the calling task's array of - * notification values on which the calling task will wait for a notification to - * be received. uxIndexToWaitOn must be less than - * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyWait() does - * not have this parameter and always waits for notifications on index 0. - * - * @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value - * will be cleared in the calling task's notification value before the task - * checks to see if any notifications are pending, and optionally blocks if no - * notifications are pending. Setting ulBitsToClearOnEntry to ULONG_MAX (if - * limits.h is included) or 0xffffffffUL (if limits.h is not included) will have - * the effect of resetting the task's notification value to 0. Setting - * ulBitsToClearOnEntry to 0 will leave the task's notification value unchanged. - * - * @param ulBitsToClearOnExit If a notification is pending or received before - * the calling task exits the xTaskNotifyWait() function then the task's - * notification value (see the xTaskNotify() API function) is passed out using - * the pulNotificationValue parameter. Then any bits that are set in - * ulBitsToClearOnExit will be cleared in the task's notification value (note - * *pulNotificationValue is set before any bits are cleared). Setting - * ulBitsToClearOnExit to ULONG_MAX (if limits.h is included) or 0xffffffffUL - * (if limits.h is not included) will have the effect of resetting the task's - * notification value to 0 before the function exits. Setting - * ulBitsToClearOnExit to 0 will leave the task's notification value unchanged - * when the function exits (in which case the value passed out in - * pulNotificationValue will match the task's notification value). - * - * @param pulNotificationValue Used to pass the task's notification value out - * of the function. Note the value passed out will not be effected by the - * clearing of any bits caused by ulBitsToClearOnExit being non-zero. - * - * @param xTicksToWait The maximum amount of time that the task should wait in - * the Blocked state for a notification to be received, should a notification - * not already be pending when xTaskNotifyWait() was called. The task - * will not consume any processing time while it is in the Blocked state. This - * is specified in kernel ticks, the macro pdMS_TO_TICKS( value_in_ms ) can be - * used to convert a time specified in milliseconds to a time specified in - * ticks. - * - * @return If a notification was received (including notifications that were - * already pending when xTaskNotifyWait was called) then pdPASS is - * returned. Otherwise pdFAIL is returned. - * - * \defgroup xTaskNotifyWaitIndexed xTaskNotifyWaitIndexed - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, - uint32_t ulBitsToClearOnEntry, - uint32_t ulBitsToClearOnExit, - uint32_t * pulNotificationValue, - TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -#define xTaskNotifyWait( ulBitsToClearOnEntry, \ - ulBitsToClearOnExit, \ - pulNotificationValue, \ - xTicksToWait ) \ - xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, \ - ( ulBitsToClearOnEntry ), \ - ( ulBitsToClearOnExit ), \ - ( pulNotificationValue ), \ - ( xTicksToWait ) ) -#define xTaskNotifyWaitIndexed( uxIndexToWaitOn, \ - ulBitsToClearOnEntry, \ - ulBitsToClearOnExit, \ - pulNotificationValue, \ - xTicksToWait ) \ - xTaskGenericNotifyWait( ( uxIndexToWaitOn ), \ - ( ulBitsToClearOnEntry ), \ - ( ulBitsToClearOnExit ), \ - ( pulNotificationValue ), \ - ( xTicksToWait ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t - * uxIndexToNotify ); BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify ); - * @endcode - * - * Sends a direct to task notification to a particular index in the target - * task's notification array in a manner similar to giving a counting semaphore. - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * macros to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * xTaskNotifyGiveIndexed() is a helper macro intended for use when task - * notifications are used as light weight and faster binary or counting - * semaphore equivalents. Actual FreeRTOS semaphores are given using the - * xSemaphoreGive() API function, the equivalent action that instead uses a task - * notification is xTaskNotifyGiveIndexed(). - * - * When task notifications are being used as a binary or counting semaphore - * equivalent then the task being notified should wait for the notification - * using the ulTaskNotifyTakeIndexed() API function rather than the - * xTaskNotifyWaitIndexed() API function. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyGive() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling xTaskNotifyGive() is equivalent to calling - * xTaskNotifyGiveIndexed() with the uxIndexToNotify parameter set to 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyGive() - * does not have this parameter and always sends notifications to index 0. - * - * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the - * eAction parameter set to eIncrement - so pdPASS is always returned. - * - * \defgroup xTaskNotifyGiveIndexed xTaskNotifyGiveIndexed - * \ingroup TaskNotifications - */ -#define xTaskNotifyGive( xTaskToNotify ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( 0 ), \ - eIncrement, \ - NULL ) -#define xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( 0 ), \ - eIncrement, \ - NULL ) - -/** - * task. h - * @code{c} - * void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t - * uxIndexToNotify, BaseType_t *pxHigherPriorityTaskWoken ); void - * vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t - * *pxHigherPriorityTaskWoken ); - * @endcode - * - * A version of xTaskNotifyGiveIndexed() that can be called from an interrupt - * service routine (ISR). - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro - * to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * vTaskNotifyGiveIndexedFromISR() is intended for use when task notifications - * are used as light weight and faster binary or counting semaphore equivalents. - * Actual FreeRTOS semaphores are given from an ISR using the - * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses - * a task notification is vTaskNotifyGiveIndexedFromISR(). - * - * When task notifications are being used as a binary or counting semaphore - * equivalent then the task being notified should wait for the notification - * using the ulTaskNotifyTakeIndexed() API function rather than the - * xTaskNotifyWaitIndexed() API function. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyFromISR() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling xTaskNotifyGiveFromISR() is equivalent to calling - * xTaskNotifyGiveIndexedFromISR() with the uxIndexToNotify parameter set to 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. - * xTaskNotifyGiveFromISR() does not have this parameter and always sends - * notifications to index 0. - * - * @param pxHigherPriorityTaskWoken vTaskNotifyGiveFromISR() will set - * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the - * task to which the notification was sent to leave the Blocked state, and the - * unblocked task has a priority higher than the currently running task. If - * vTaskNotifyGiveFromISR() sets this value to pdTRUE then a context switch - * should be requested before the interrupt is exited. How a context switch is - * requested from an ISR is dependent on the port - see the documentation page - * for the port in use. - * - * \defgroup vTaskNotifyGiveIndexedFromISR vTaskNotifyGiveIndexedFromISR - * \ingroup TaskNotifications - */ -void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify, - UBaseType_t uxIndexToNotify, - BaseType_t * pxHigherPriorityTaskWoken ) - PRIVILEGED_FUNCTION; -#define vTaskNotifyGiveFromISR( xTaskToNotify, pxHigherPriorityTaskWoken ) \ - vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( pxHigherPriorityTaskWoken ) ) -#define vTaskNotifyGiveIndexedFromISR( xTaskToNotify, \ - uxIndexToNotify, \ - pxHigherPriorityTaskWoken ) \ - vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( pxHigherPriorityTaskWoken ) ) - -/** - * task. h - * @code{c} - * uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn, BaseType_t - * xClearCountOnExit, TickType_t xTicksToWait ); - * - * uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t - * xTicksToWait ); - * @endcode - * - * Waits for a direct to task notification on a particular index in the calling - * task's notification array in a manner similar to taking a counting semaphore. - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this - * function to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * ulTaskNotifyTakeIndexed() is intended for use when a task notification is - * used as a faster and lighter weight binary or counting semaphore alternative. - * Actual FreeRTOS semaphores are taken using the xSemaphoreTake() API function, - * the equivalent action that instead uses a task notification is - * ulTaskNotifyTakeIndexed(). - * - * When a task is using its notification value as a binary or counting semaphore - * other tasks should send notifications to it using the - * xTaskNotifyGiveIndexed() macro, or xTaskNotifyIndex() function with the - * eAction parameter set to eIncrement. - * - * ulTaskNotifyTakeIndexed() can either clear the task's notification value at - * the array index specified by the uxIndexToWaitOn parameter to zero on exit, - * in which case the notification value acts like a binary semaphore, or - * decrement the notification value on exit, in which case the notification - * value acts like a counting semaphore. - * - * A task can use ulTaskNotifyTakeIndexed() to [optionally] block to wait for - * a notification. The task does not consume any CPU time while it is in the - * Blocked state. - * - * Where as xTaskNotifyWaitIndexed() will return when a notification is pending, - * ulTaskNotifyTakeIndexed() will return when the task's notification value is - * not zero. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. ulTaskNotifyTake() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling ulTaskNotifyTake() is equivalent to calling - * ulTaskNotifyTakeIndexed() with the uxIndexToWaitOn parameter set to 0. - * - * @param uxIndexToWaitOn The index within the calling task's array of - * notification values on which the calling task will wait for a notification to - * be non-zero. uxIndexToWaitOn must be less than - * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyTake() does - * not have this parameter and always waits for notifications on index 0. - * - * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's - * notification value is decremented when the function exits. In this way the - * notification value acts like a counting semaphore. If xClearCountOnExit is - * not pdFALSE then the task's notification value is cleared to zero when the - * function exits. In this way the notification value acts like a binary - * semaphore. - * - * @param xTicksToWait The maximum amount of time that the task should wait in - * the Blocked state for the task's notification value to be greater than zero, - * should the count not already be greater than zero when - * ulTaskNotifyTake() was called. The task will not consume any processing - * time while it is in the Blocked state. This is specified in kernel ticks, - * the macro pdMS_TO_TICKS( value_in_ms ) can be used to convert a time - * specified in milliseconds to a time specified in ticks. - * - * @return The task's notification count before it is either cleared to zero or - * decremented (see the xClearCountOnExit parameter). - * - * \defgroup ulTaskNotifyTakeIndexed ulTaskNotifyTakeIndexed - * \ingroup TaskNotifications - */ -uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, - BaseType_t xClearCountOnExit, - TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -#define ulTaskNotifyTake( xClearCountOnExit, xTicksToWait ) \ - ulTaskGenericNotifyTake( ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( xClearCountOnExit ), \ - ( xTicksToWait ) ) -#define ulTaskNotifyTakeIndexed( uxIndexToWaitOn, \ - xClearCountOnExit, \ - xTicksToWait ) \ - ulTaskGenericNotifyTake( ( uxIndexToWaitOn ), \ - ( xClearCountOnExit ), \ - ( xTicksToWait ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t - * uxIndexToCLear ); - * - * BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * If a notification is sent to an index within the array of notifications then - * the notification at that index is said to be 'pending' until it is read or - * explicitly cleared by the receiving task. xTaskNotifyStateClearIndexed() - * is the function that clears a pending notification without reading the - * notification value. The notification value at the same array index is not - * altered. Set xTask to NULL to clear the notification state of the calling - * task. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyStateClear() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling xTaskNotifyStateClear() is equivalent to calling - * xTaskNotifyStateClearIndexed() with the uxIndexToNotify parameter set to 0. - * - * @param xTask The handle of the RTOS task that will have a notification state - * cleared. Set xTask to NULL to clear a notification state in the calling - * task. To obtain a task's handle create the task using xTaskCreate() and - * make use of the pxCreatedTask parameter, or create the task using - * xTaskCreateStatic() and store the returned value, or use the task's name in - * a call to xTaskGetHandle(). - * - * @param uxIndexToClear The index within the target task's array of - * notification values to act upon. For example, setting uxIndexToClear to 1 - * will clear the state of the notification at index 1 within the array. - * uxIndexToClear must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. - * ulTaskNotifyStateClear() does not have this parameter and always acts on the - * notification at index 0. - * - * @return pdTRUE if the task's notification state was set to - * eNotWaitingNotification, otherwise pdFALSE. - * - * \defgroup xTaskNotifyStateClearIndexed xTaskNotifyStateClearIndexed - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask, - UBaseType_t uxIndexToClear ) - PRIVILEGED_FUNCTION; -#define xTaskNotifyStateClear( xTask ) \ - xTaskGenericNotifyStateClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ) ) -#define xTaskNotifyStateClearIndexed( xTask, uxIndexToClear ) \ - xTaskGenericNotifyStateClear( ( xTask ), ( uxIndexToClear ) ) - -/** - * task. h - * @code{c} - * uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, UBaseType_t - * uxIndexToClear, uint32_t ulBitsToClear ); - * - * uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear - * ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * ulTaskNotifyValueClearIndexed() clears the bits specified by the - * ulBitsToClear bit mask in the notification value at array index - * uxIndexToClear of the task referenced by xTask. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. ulTaskNotifyValueClear() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling ulTaskNotifyValueClear() is equivalent to calling - * ulTaskNotifyValueClearIndexed() with the uxIndexToClear parameter set to 0. - * - * @param xTask The handle of the RTOS task that will have bits in one of its - * notification values cleared. Set xTask to NULL to clear bits in a - * notification value of the calling task. To obtain a task's handle create the - * task using xTaskCreate() and make use of the pxCreatedTask parameter, or - * create the task using xTaskCreateStatic() and store the returned value, or - * use the task's name in a call to xTaskGetHandle(). - * - * @param uxIndexToClear The index within the target task's array of - * notification values in which to clear the bits. uxIndexToClear - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. - * ulTaskNotifyValueClear() does not have this parameter and always clears bits - * in the notification value at index 0. - * - * @param ulBitsToClear Bit mask of the bits to clear in the notification value - * of xTask. Set a bit to 1 to clear the corresponding bits in the task's - * notification value. Set ulBitsToClear to 0xffffffff (UINT_MAX on 32-bit - * architectures) to clear the notification value to 0. Set ulBitsToClear to 0 - * to query the task's notification value without clearing any bits. - * - * - * @return The value of the target task's notification value before the bits - * specified by ulBitsToClear were cleared. - * \defgroup ulTaskNotifyValueClear ulTaskNotifyValueClear - * \ingroup TaskNotifications - */ -uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask, - UBaseType_t uxIndexToClear, - uint32_t ulBitsToClear ) - PRIVILEGED_FUNCTION; -#define ulTaskNotifyValueClear( xTask, ulBitsToClear ) \ - ulTaskGenericNotifyValueClear( ( xTask ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulBitsToClear ) ) -#define ulTaskNotifyValueClearIndexed( xTask, uxIndexToClear, ulBitsToClear ) \ - ulTaskGenericNotifyValueClear( ( xTask ), \ - ( uxIndexToClear ), \ - ( ulBitsToClear ) ) - -/** - * task.h - * @code{c} - * void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ); - * @endcode - * - * Capture the current time for future use with xTaskCheckForTimeOut(). - * - * @param pxTimeOut Pointer to a timeout object into which the current time - * is to be captured. The captured time includes the tick count and the number - * of times the tick count has overflowed since the system first booted. - * \defgroup vTaskSetTimeOutState vTaskSetTimeOutState - * \ingroup TaskCtrl - */ -void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * - * const pxTicksToWait ); - * @endcode - * - * Determines if pxTicksToWait ticks has passed since a time was captured - * using a call to vTaskSetTimeOutState(). The captured time includes the tick - * count and the number of times the tick count has overflowed. - * - * @param pxTimeOut The time status as captured previously using - * vTaskSetTimeOutState. If the timeout has not yet occurred, it is updated - * to reflect the current time status. - * @param pxTicksToWait The number of ticks to check for timeout i.e. if - * pxTicksToWait ticks have passed since pxTimeOut was last updated (either by - * vTaskSetTimeOutState() or xTaskCheckForTimeOut()), the timeout has occurred. - * If the timeout has not occurred, pxTicksToWait is updated to reflect the - * number of remaining ticks. - * - * @return If timeout has occurred, pdTRUE is returned. Otherwise pdFALSE is - * returned and pxTicksToWait is updated to reflect the number of remaining - * ticks. - * - * @see https://www.FreeRTOS.org/xTaskCheckForTimeOut.html - * - * Example Usage: - * @code{c} - * // Driver library function used to receive uxWantedBytes from an Rx buffer - * // that is filled by a UART interrupt. If there are not enough bytes in the - * // Rx buffer then the task enters the Blocked state until it is notified - * that - * // more data has been placed into the buffer. If there is still not enough - * // data then the task re-enters the Blocked state, and - * xTaskCheckForTimeOut() - * // is used to re-calculate the Block time to ensure the total amount of time - * // spent in the Blocked state does not exceed MAX_TIME_TO_WAIT. This - * // continues until either the buffer contains at least uxWantedBytes bytes, - * // or the total amount of time spent in the Blocked state reaches - * // MAX_TIME_TO_WAIT - at which point the task reads however many bytes are - * // available up to a maximum of uxWantedBytes. - * - * size_t xUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes ) - * { - * size_t uxReceived = 0; - * TickType_t xTicksToWait = MAX_TIME_TO_WAIT; - * TimeOut_t xTimeOut; - * - * // Initialize xTimeOut. This records the time at which this function - * // was entered. - * vTaskSetTimeOutState( &xTimeOut ); - * - * // Loop until the buffer contains the wanted number of bytes, or a - * // timeout occurs. - * while( UART_bytes_in_rx_buffer( pxUARTInstance ) < uxWantedBytes ) - * { - * // The buffer didn't contain enough data so this task is going to - * // enter the Blocked state. Adjusting xTicksToWait to account for - * // any time that has been spent in the Blocked state within this - * // function so far to ensure the total amount of time spent in the - * // Blocked state does not exceed MAX_TIME_TO_WAIT. - * if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) != pdFALSE ) - * { - * //Timed out before the wanted number of bytes were available, - * // exit the loop. - * break; - * } - * - * // Wait for a maximum of xTicksToWait ticks to be notified that the - * // receive interrupt has placed more data into the buffer. - * ulTaskNotifyTake( pdTRUE, xTicksToWait ); - * } - * - * // Attempt to read uxWantedBytes from the receive buffer into pucBuffer. - * // The actual number of bytes read (which might be less than - * // uxWantedBytes) is returned. - * uxReceived = UART_read_from_receive_buffer( pxUARTInstance, - * pucBuffer, - * uxWantedBytes ); - * - * return uxReceived; - * } - * @endcode - * \defgroup xTaskCheckForTimeOut xTaskCheckForTimeOut - * \ingroup TaskCtrl - */ -BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, - TickType_t * const pxTicksToWait ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ); - * @endcode - * - * This function corrects the tick count value after the application code has - * held interrupts disabled for an extended period resulting in tick interrupts - * having been missed. - * - * This function is similar to vTaskStepTick(), however, unlike - * vTaskStepTick(), xTaskCatchUpTicks() may move the tick count forward past a - * time at which a task should be removed from the blocked state. That means - * tasks may have to be removed from the blocked state as the tick count is - * moved. - * - * @param xTicksToCatchUp The number of tick interrupts that have been missed - * due to interrupts being disabled. Its value is not computed automatically, - * so must be computed by the application writer. - * - * @return pdTRUE if moving the tick count forward resulted in a task leaving - * the blocked state and a context switch being performed. Otherwise pdFALSE. - * - * \defgroup xTaskCatchUpTicks xTaskCatchUpTicks - * \ingroup TaskCtrl - */ -BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- - * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES - *----------------------------------------------------------*/ - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY - * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS - * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * Called from the real time kernel tick (either preemptive or cooperative), - * this increments the tick count and checks if any tasks that are blocked - * for a finite period required removing from a blocked list and placing on - * a ready list. If a non-zero value is returned then a context switch is - * required because either: - * + A task was removed from a blocked list because its timeout had expired, - * or - * + Time slicing is in use and there is a task of equal priority to the - * currently running task. - */ -BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * Removes the calling task from the ready list and places it both - * on the list of tasks waiting for a particular event, and the - * list of delayed tasks. The task will be removed from both lists - * and replaced on the ready list should either the event occur (and - * there be no higher priority tasks waiting on the same event) or - * the delay period expires. - * - * The 'unordered' version replaces the event list item value with the - * xItemValue value, and inserts the list item at the end of the list. - * - * The 'ordered' version uses the existing event list item value (which is the - * owning task's priority) to insert the list item into the event list in task - * priority order. - * - * @param pxEventList The list containing tasks that are blocked waiting - * for the event to occur. - * - * @param xItemValue The item value to use for the event list item when the - * event list is not ordered by task priority. - * - * @param xTicksToWait The maximum amount of time that the task should wait - * for the event to occur. This is specified in kernel ticks, the constant - * portTICK_PERIOD_MS can be used to convert kernel ticks into a real time - * period. - */ -void vTaskPlaceOnEventList( List_t * const pxEventList, - const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, - const TickType_t xItemValue, - const TickType_t xTicksToWait ) - PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * This function performs nearly the same function as vTaskPlaceOnEventList(). - * The difference being that this function does not permit tasks to block - * indefinitely, whereas vTaskPlaceOnEventList() does. - * - */ -void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, - TickType_t xTicksToWait, - const BaseType_t xWaitIndefinitely ) - PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * Removes a task from both the specified event list and the list of blocked - * tasks, and places it on a ready queue. - * - * xTaskRemoveFromEventList()/vTaskRemoveFromUnorderedEventList() will be called - * if either an event occurs to unblock a task, or the block timeout period - * expires. - * - * xTaskRemoveFromEventList() is used when the event list is in task priority - * order. It removes the list item from the head of the event list as that will - * have the highest priority owning task of all the tasks on the event list. - * vTaskRemoveFromUnorderedEventList() is used when the event list is not - * ordered and the event list items hold something other than the owning tasks - * priority. In this case the event list item value is updated to the value - * passed in the xItemValue parameter. - * - * @return pdTRUE if the task being removed has a higher priority than the task - * making the call, otherwise pdFALSE. - */ -BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) - PRIVILEGED_FUNCTION; -void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, - const TickType_t xItemValue ) - PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY - * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS - * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * Sets the pointer to the current TCB to the TCB of the highest priority task - * that is ready to run. - */ -#if( configNUMBER_OF_CORES == 1 ) -portDONT_DISCARD void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; -#else -portDONT_DISCARD void vTaskSwitchContext( BaseType_t xCoreID ) - PRIVILEGED_FUNCTION; -#endif - -/* - * THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY - * THE EVENT BITS MODULE. - */ -TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION; - -/* - * Return the handle of the calling task. - */ -TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; - -/* - * Return the handle of the task running on specified core. - */ -TaskHandle_t xTaskGetCurrentTaskHandleCPU( BaseType_t xCoreID ) - PRIVILEGED_FUNCTION; - -/* - * Shortcut used by the queue implementation to prevent unnecessary call to - * taskYIELD(); - */ -void vTaskMissedYield( void ) PRIVILEGED_FUNCTION; - -/* - * Returns the scheduler state as taskSCHEDULER_RUNNING, - * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. - */ -BaseType_t xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION; - -/* - * Raises the priority of the mutex holder to that of the calling task should - * the mutex holder have a priority less than the calling task. - */ -BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) - PRIVILEGED_FUNCTION; - -/* - * Set the priority of a task back to its proper priority in the case that it - * inherited a higher priority while it was holding a semaphore. - */ -BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) - PRIVILEGED_FUNCTION; - -/* - * If a higher priority task attempting to obtain a mutex caused a lower - * priority task to inherit the higher priority task's priority - but the higher - * priority task then timed out without obtaining the mutex, then the lower - * priority task will disinherit the priority again - but only down as far as - * the highest priority task that is still waiting for the mutex (if there were - * more than one task waiting for the mutex). - */ -void vTaskPriorityDisinheritAfterTimeout( - TaskHandle_t const pxMutexHolder, - UBaseType_t uxHighestPriorityWaitingTask ) PRIVILEGED_FUNCTION; - -/* - * Get the uxTaskNumber assigned to the task referenced by the xTask parameter. - */ -UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/* - * Set the uxTaskNumber of the task referenced by the xTask parameter to - * uxHandle. - */ -void vTaskSetTaskNumber( TaskHandle_t xTask, - const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION; - -/* - * Only available when configUSE_TICKLESS_IDLE is set to 1. - * If tickless mode is being used, or a low power mode is implemented, then - * the tick interrupt will not execute during idle periods. When this is the - * case, the tick count value maintained by the scheduler needs to be kept up - * to date with the actual execution time by being skipped forward by a time - * equal to the idle period. - */ -void vTaskStepTick( TickType_t xTicksToJump ) PRIVILEGED_FUNCTION; - -/* - * Only available when configUSE_TICKLESS_IDLE is set to 1. - * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port - * specific sleep function to determine if it is ok to proceed with the sleep, - * and if it is ok to proceed, if it is ok to sleep indefinitely. - * - * This function is necessary because portSUPPRESS_TICKS_AND_SLEEP() is only - * called with the scheduler suspended, not from within a critical section. It - * is therefore possible for an interrupt to request a context switch between - * portSUPPRESS_TICKS_AND_SLEEP() and the low power mode actually being - * entered. eTaskConfirmSleepModeStatus() should be called from a short - * critical section between the timer being stopped and the sleep mode being - * entered to ensure it is ok to proceed into the sleep mode. - */ -eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION; - -/* - * For internal use only. Increment the mutex held count when a mutex is - * taken and return the handle of the task that has taken the mutex. - */ -TaskHandle_t pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION; - -/* - * For internal use only. Same as vTaskSetTimeOutState(), but without a - * critical section. - */ -void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) - PRIVILEGED_FUNCTION; - -/* - * For internal use only. Same as portYIELD_WITHIN_API() in single core - * FreeRTOS. For SMP this is not defined by the port. - */ -void vTaskYieldWithinAPI( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when portCRITICAL_NESTING_IN_TCB is set to 1 - * or configNUMBER_OF_CORES is greater than 1. This function can be used in the - * implementation of portENTER_CRITICAL if port wants to maintain critical - * nesting count in TCB in single core FreeRTOS. It should be used in the - * implementation of portENTER_CRITICAL if port is running a multiple core - * FreeRTOS. - */ -void vTaskEnterCritical( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when portCRITICAL_NESTING_IN_TCB is set to 1 - * or configNUMBER_OF_CORES is greater than 1. This function can be used in the - * implementation of portEXIT_CRITICAL if port wants to maintain critical - * nesting count in TCB in single core FreeRTOS. It should be used in the - * implementation of portEXIT_CRITICAL if port is running a multiple core - * FreeRTOS. - */ -void vTaskExitCritical( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when configNUMBER_OF_CORES is greater than 1. - * This function should be used in the implementation of - * portENTER_CRITICAL_FROM_ISR if port is running a multiple core FreeRTOS. - */ -UBaseType_t vTaskEnterCriticalFromISR( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when configNUMBER_OF_CORES is greater than 1. - * This function should be used in the implementation of - * portEXIT_CRITICAL_FROM_ISR if port is running a multiple core FreeRTOS. - */ -void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus ); - -#if( portUSING_MPU_WRAPPERS == 1 ) - -/* - * For internal use only. Get MPU settings associated with a task. - */ -xMPU_SETTINGS * xTaskGetMPUSettings( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -#endif /* portUSING_MPU_WRAPPERS */ - -/* *INDENT-OFF* */ -#ifdef __cplusplus -} -#endif -/* *INDENT-ON* */ -#endif /* INC_TASK_H */ diff --git a/formatting/goodFiles/include/task.h b/formatting/goodFiles/include/task.h deleted file mode 100644 index 3edd544f..00000000 --- a/formatting/goodFiles/include/task.h +++ /dev/null @@ -1,3761 +0,0 @@ -/* - * FreeRTOS Kernel - * 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 - * - */ - -#ifndef INC_TASK_H -#define INC_TASK_H - -#ifndef INC_FREERTOS_H - #error \ - "include FreeRTOS.h must appear in source files before include task.h" -#endif - -#include "list.h" - -/* *INDENT-OFF* */ -#ifdef __cplusplus -extern "C" { -#endif -/* *INDENT-ON* */ - -/*----------------------------------------------------------- - * MACROS AND DEFINITIONS - *----------------------------------------------------------*/ - -/* - * If tskKERNEL_VERSION_NUMBER ends with + it represents the version in - * development after the numbered release. - * - * The tskKERNEL_VERSION_MAJOR, tskKERNEL_VERSION_MINOR, tskKERNEL_VERSION_BUILD - * values will reflect the last released version number. - */ -#define tskKERNEL_VERSION_NUMBER "V10.4.4+" -#define tskKERNEL_VERSION_MAJOR 10 -#define tskKERNEL_VERSION_MINOR 4 -#define tskKERNEL_VERSION_BUILD 4 - -/* MPU region parameters passed in ulParameters - * of MemoryRegion_t struct. */ -#define tskMPU_REGION_READ_ONLY ( 1UL << 0UL ) -#define tskMPU_REGION_READ_WRITE ( 1UL << 1UL ) -#define tskMPU_REGION_EXECUTE_NEVER ( 1UL << 2UL ) -#define tskMPU_REGION_NORMAL_MEMORY ( 1UL << 3UL ) -#define tskMPU_REGION_DEVICE_MEMORY ( 1UL << 4UL ) - -/* MPU region permissions stored in MPU settings to - * authorize access requests. */ -#define tskMPU_READ_PERMISSION ( 1UL << 0UL ) -#define tskMPU_WRITE_PERMISSION ( 1UL << 1UL ) - -/* The direct to task notification feature used to have only a single - * notification per task. Now there is an array of notifications per task that - * is dimensioned by configTASK_NOTIFICATION_ARRAY_ENTRIES. For backward - * compatibility, any use of the original direct to task notification defaults - * to using the first index in the array. */ -#define tskDEFAULT_INDEX_TO_NOTIFY ( 0 ) - -/** - * task. h - * - * Type by which tasks are referenced. For example, a call to xTaskCreate - * returns (via a pointer parameter) an TaskHandle_t variable that can then - * be used as a parameter to vTaskDelete to delete the task. - * - * \defgroup TaskHandle_t TaskHandle_t - * \ingroup Tasks - */ -struct tskTaskControlBlock; /* The old naming convention is used to prevent - breaking kernel aware debuggers. */ -typedef struct tskTaskControlBlock * TaskHandle_t; -typedef const struct tskTaskControlBlock * ConstTaskHandle_t; - -/* - * Defines the prototype to which the application task hook function must - * conform. - */ -typedef BaseType_t ( *TaskHookFunction_t )( void * ); - -/* Task states returned by eTaskGetState. */ -typedef enum -{ - eRunning = 0, /* A task is querying the state of itself, so must be running. - */ - eReady, /* The task being queried is in a ready or pending ready list. */ - eBlocked, /* The task being queried is in the Blocked state. */ - eSuspended, /* The task being queried is in the Suspended state, or is in - the Blocked state with an infinite time out. */ - eDeleted, /* The task being queried has been deleted, but its TCB has not - yet been freed. */ - eInvalid /* Used as an 'invalid state' value. */ -} eTaskState; - -/* Actions that can be performed when vTaskNotify() is called. */ -typedef enum -{ - eNoAction = 0, /* Notify the task without updating its notify value. */ - eSetBits, /* Set bits in the task's notification value. */ - eIncrement, /* Increment the task's notification value. */ - eSetValueWithOverwrite, /* Set the task's notification value to a specific - value even if the previous value has not yet been - read by the task. */ - eSetValueWithoutOverwrite /* Set the task's notification value if the - previous value has been read by the task. */ -} eNotifyAction; - -/* - * Used internally only. - */ -typedef struct xTIME_OUT -{ - BaseType_t xOverflowCount; - TickType_t xTimeOnEntering; -} TimeOut_t; - -/* - * Defines the memory ranges allocated to the task when an MPU is used. - */ -typedef struct xMEMORY_REGION -{ - void * pvBaseAddress; - uint32_t ulLengthInBytes; - uint32_t ulParameters; -} MemoryRegion_t; - -/* - * Parameters required to create an MPU protected task. - */ -typedef struct xTASK_PARAMETERS -{ - TaskFunction_t pvTaskCode; - const char * pcName; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - configSTACK_DEPTH_TYPE usStackDepth; - void * pvParameters; - UBaseType_t uxPriority; - StackType_t * puxStackBuffer; - MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ]; -#if( ( portUSING_MPU_WRAPPERS == 1 ) && \ - ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - StaticTask_t * const pxTaskBuffer; -#endif -} TaskParameters_t; - -/* Used with the uxTaskGetSystemState() function to return the state of each - * task in the system. */ -typedef struct xTASK_STATUS -{ - TaskHandle_t xHandle; /* The handle of the task to which the rest of the - information in the structure relates. */ - const char * pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - UBaseType_t xTaskNumber; /* A number unique to the task. */ - eTaskState eCurrentState; /* The state in which the task existed when the - structure was populated. */ - UBaseType_t uxCurrentPriority; /* The priority at which the task was running - (may be inherited) when the structure was - populated. */ - UBaseType_t uxBasePriority; /* The priority to which the task will return if - the task's current priority has been - inherited to avoid unbounded priority - inversion when obtaining a mutex. Only valid - if configUSE_MUTEXES is defined as 1 in - FreeRTOSConfig.h. */ - configRUN_TIME_COUNTER_TYPE - ulRunTimeCounter; /* The total run time - allocated to the task so - far, as defined by the run - time stats clock. See - https://www.FreeRTOS.org/rtos-run-time-stats.html. - Only valid when - configGENERATE_RUN_TIME_STATS - is defined as 1 in - FreeRTOSConfig.h. */ - StackType_t * pxStackBase; /* Points to the lowest address of the task's - stack area. */ -#if( ( portSTACK_GROWTH > 0 ) && ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) - StackType_t * pxTopOfStack; /* Points to the top address of the task's stack - area. */ - StackType_t * pxEndOfStack; /* Points to the end address of the task's stack - area. */ -#endif - configSTACK_DEPTH_TYPE usStackHighWaterMark; /* The minimum amount of stack - space that has remained for - the task since the task was - created. The closer this - value is to zero the closer - the task has come to - overflowing its stack. */ -#if( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - UBaseType_t uxCoreAffinityMask; /* The core affinity mask for the task */ -#endif -} TaskStatus_t; - -/* Possible return values for eTaskConfirmSleepModeStatus(). */ -typedef enum -{ - eAbortSleep = 0, /* A task has been made ready or a context switch pended - since portSUPPRESS_TICKS_AND_SLEEP() was called - abort - entering a sleep mode. */ - eStandardSleep, /* Enter a sleep mode that will not last any longer than the - expected idle time. */ -#if( INCLUDE_vTaskSuspend == 1 ) - eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe - to enter a sleep mode that can only be exited by - an external interrupt. */ -#endif /* INCLUDE_vTaskSuspend */ -} eSleepModeStatus; - -/** - * Defines the priority used by the idle task. This must not be modified. - * - * \ingroup TaskUtils - */ -#define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U ) - -/** - * Defines affinity to all available cores. - * - * \ingroup TaskUtils - */ -#define tskNO_AFFINITY ( ( UBaseType_t ) -1 ) - -/** - * task. h - * - * Macro for forcing a context switch. - * - * \defgroup taskYIELD taskYIELD - * \ingroup SchedulerControl - */ -#define taskYIELD() portYIELD() - -/** - * task. h - * - * Macro to mark the start of a critical code region. Preemptive context - * switches cannot occur when in a critical region. - * - * NOTE: This may alter the stack (depending on the portable implementation) - * so must be used with care! - * - * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL - * \ingroup SchedulerControl - */ -#define taskENTER_CRITICAL() portENTER_CRITICAL() -#if( configNUMBER_OF_CORES == 1 ) - #define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() -#else - #define taskENTER_CRITICAL_FROM_ISR() portENTER_CRITICAL_FROM_ISR() -#endif - -/** - * task. h - * - * Macro to mark the end of a critical code region. Preemptive context - * switches cannot occur when in a critical region. - * - * NOTE: This may alter the stack (depending on the portable implementation) - * so must be used with care! - * - * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL - * \ingroup SchedulerControl - */ -#define taskEXIT_CRITICAL() portEXIT_CRITICAL() -#if( configNUMBER_OF_CORES == 1 ) - #define taskEXIT_CRITICAL_FROM_ISR( x ) \ - portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) -#else - #define taskEXIT_CRITICAL_FROM_ISR( x ) portEXIT_CRITICAL_FROM_ISR( x ) -#endif - -/** - * task. h - * - * Macro to disable all maskable interrupts. - * - * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS - * \ingroup SchedulerControl - */ -#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() - -/** - * task. h - * - * Macro to enable microcontroller interrupts. - * - * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS - * \ingroup SchedulerControl - */ -#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() - -/* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is - * 0 to generate more optimal code when configASSERT() is defined as the - * constant is used in assert() statements. */ -#define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 ) -#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 ) -#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 ) - -/* Checks if core ID is valid. */ -#define taskVALID_CORE_ID( xCoreID ) \ - ( ( ( ( ( BaseType_t ) 0 <= ( xCoreID ) ) && \ - ( ( xCoreID ) < ( BaseType_t ) configNUMBER_OF_CORES ) ) ) \ - ? ( pdTRUE ) \ - : ( pdFALSE ) ) - -/*----------------------------------------------------------- - * TASK CREATION API - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * BaseType_t xTaskCreate( - * TaskFunction_t pxTaskCode, - * const char *pcName, - * configSTACK_DEPTH_TYPE usStackDepth, - * void *pvParameters, - * UBaseType_t uxPriority, - * TaskHandle_t *pxCreatedTask - * ); - * @endcode - * - * Create a new task and add it to the list of tasks that are ready to run. - * - * Internally, within the FreeRTOS implementation, tasks use two blocks of - * memory. The first block is used to hold the task's data structures. The - * second block is used by the task as its stack. If a task is created using - * xTaskCreate() then both blocks of memory are automatically dynamically - * allocated inside the xTaskCreate() function. (see - * https://www.FreeRTOS.org/a00111.html). If a task is created using - * xTaskCreateStatic() then the application writer must provide the required - * memory. xTaskCreateStatic() therefore allows a task to be created without - * using any dynamic memory allocation. - * - * See xTaskCreateStatic() for a version that does not use any dynamic memory - * allocation. - * - * xTaskCreate() can only be used to create a task that has unrestricted - * access to the entire microcontroller memory map. Systems that include MPU - * support can alternatively create an MPU constrained task using - * xTaskCreateRestricted(). - * - * @param pxTaskCode Pointer to the task entry function. Tasks - * must be implemented to never return (i.e. continuous loop). - * - * @param pcName A descriptive name for the task. This is mainly used to - * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - - * default is 16. - * - * @param usStackDepth The size of the task stack specified as the number of - * variables the stack can hold - not the number of bytes. For example, if - * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes - * will be allocated for stack storage. - * - * @param pvParameters Pointer that will be used as the parameter for the task - * being created. - * - * @param uxPriority The priority at which the task should run. Systems that - * include MPU support can optionally create tasks in a privileged (system) - * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For - * example, to create a privileged task at priority 2 the uxPriority parameter - * should be set to ( 2 | portPRIVILEGE_BIT ). - * - * @param pxCreatedTask Used to pass back a handle by which the created task - * can be referenced. - * - * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file projdefs.h - * - * Example usage: - * @code{c} - * // Task to be created. - * void vTaskCode( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * } - * } - * - * // Function that creates a task. - * void vOtherFunction( void ) - * { - * static uint8_t ucParameterToPass; - * TaskHandle_t xHandle = NULL; - * - * // Create the task, storing the handle. Note that the passed parameter - * ucParameterToPass - * // must exist for the lifetime of the task, so in this case is declared - * static. If it was just an - * // an automatic stack variable it might no longer exist, or at least have - * been corrupted, by the time - * // the new task attempts to access it. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, - * tskIDLE_PRIORITY, &xHandle ); configASSERT( xHandle ); - * - * // Use the handle to delete the task. - * if( xHandle != NULL ) - * { - * vTaskDelete( xHandle ); - * } - * } - * @endcode - * \defgroup xTaskCreate xTaskCreate - * \ingroup Tasks - */ -#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 ) PRIVILEGED_FUNCTION; -#endif - -#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && \ - ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) -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 ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, - * const char *pcName, - * uint32_t ulStackDepth, - * void *pvParameters, - * UBaseType_t uxPriority, - * StackType_t *puxStackBuffer, - * StaticTask_t *pxTaskBuffer ); - * @endcode - * - * Create a new task and add it to the list of tasks that are ready to run. - * - * Internally, within the FreeRTOS implementation, tasks use two blocks of - * memory. The first block is used to hold the task's data structures. The - * second block is used by the task as its stack. If a task is created using - * xTaskCreate() then both blocks of memory are automatically dynamically - * allocated inside the xTaskCreate() function. (see - * https://www.FreeRTOS.org/a00111.html). If a task is created using - * xTaskCreateStatic() then the application writer must provide the required - * memory. xTaskCreateStatic() therefore allows a task to be created without - * using any dynamic memory allocation. - * - * @param pxTaskCode Pointer to the task entry function. Tasks - * must be implemented to never return (i.e. continuous loop). - * - * @param pcName A descriptive name for the task. This is mainly used to - * facilitate debugging. The maximum length of the string is defined by - * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h. - * - * @param ulStackDepth The size of the task stack specified as the number of - * variables the stack can hold - not the number of bytes. For example, if - * the stack is 32-bits wide and ulStackDepth is defined as 100 then 400 bytes - * will be allocated for stack storage. - * - * @param pvParameters Pointer that will be used as the parameter for the task - * being created. - * - * @param uxPriority The priority at which the task will run. - * - * @param puxStackBuffer Must point to a StackType_t array that has at least - * ulStackDepth indexes - the array will then be used as the task's stack, - * removing the need for the stack to be allocated dynamically. - * - * @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will - * then be used to hold the task's data structures, removing the need for the - * memory to be allocated dynamically. - * - * @return If neither puxStackBuffer nor pxTaskBuffer are NULL, then the task - * will be created and a handle to the created task is returned. If either - * puxStackBuffer or pxTaskBuffer are NULL then the task will not be created and - * NULL is returned. - * - * Example usage: - * @code{c} - * - * // Dimensions of the buffer that the task being created will use as its - stack. - * // NOTE: This is the number of words the stack will hold, not the number of - * // bytes. For example, if each stack item is 32-bits, and this is set to - 100, - * // then 400 bytes (100 * 32-bits) will be allocated. - #define STACK_SIZE 200 - * - * // Structure that will hold the TCB of the task being created. - * StaticTask_t xTaskBuffer; - * - * // Buffer that the task being created will use as its stack. Note this is - * // an array of StackType_t variables. The size of StackType_t is dependent - on - * // the RTOS port. - * StackType_t xStack[ STACK_SIZE ]; - * - * // Function that implements the task being created. - * void vTaskCode( void * pvParameters ) - * { - * // The parameter value is expected to be 1 as 1 is passed in the - * // pvParameters value in the call to xTaskCreateStatic(). - * configASSERT( ( uint32_t ) pvParameters == 1UL ); - * - * for( ;; ) - * { - * // Task code goes here. - * } - * } - * - * // Function that creates a task. - * void vOtherFunction( void ) - * { - * TaskHandle_t xHandle = NULL; - * - * // Create the task without using any dynamic memory allocation. - * xHandle = xTaskCreateStatic( - * vTaskCode, // Function that implements the task. - * "NAME", // Text name for the task. - * STACK_SIZE, // Stack size in words, not bytes. - * ( void * ) 1, // Parameter passed into the task. - * tskIDLE_PRIORITY,// Priority at which the task is created. - * xStack, // Array to use as the task's stack. - * &xTaskBuffer ); // Variable to hold the task's data - structure. - * - * // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have - * // been created, and xHandle will be the task's handle. Use the handle - * // to suspend the task. - * vTaskSuspend( xHandle ); - * } - * @endcode - * \defgroup xTaskCreateStatic xTaskCreateStatic - * \ingroup Tasks - */ -#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 ) PRIVILEGED_FUNCTION; -#endif /* configSUPPORT_STATIC_ALLOCATION */ - -#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && \ - ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) -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 ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, - * TaskHandle_t *pxCreatedTask ); - * @endcode - * - * Only available when configSUPPORT_DYNAMIC_ALLOCATION is set to 1. - * - * xTaskCreateRestricted() should only be used in systems that include an MPU - * implementation. - * - * Create a new task and add it to the list of tasks that are ready to run. - * The function parameters define the memory regions and associated access - * permissions allocated to the task. - * - * See xTaskCreateRestrictedStatic() for a version that does not use any - * dynamic memory allocation. - * - * @param pxTaskDefinition Pointer to a structure that contains a member - * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API - * documentation) plus an optional stack buffer and the memory region - * definitions. - * - * @param pxCreatedTask Used to pass back a handle by which the created task - * can be referenced. - * - * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file projdefs.h - * - * Example usage: - * @code{c} - * // Create an TaskParameters_t structure that defines the task to be created. - * static const TaskParameters_t xCheckTaskParameters = - * { - * vATask, // pvTaskCode - the function that implements the task. - * "ATask", // pcName - just a text name for the task to assist debugging. - * 100, // usStackDepth - the stack size DEFINED IN WORDS. - * NULL, // pvParameters - passed into the task function as the function - * parameters. ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set - * the portPRIVILEGE_BIT if the task should run in a privileged state. - * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack. - * - * // xRegions - Allocate up to three separate memory regions for access by - * // the task, with appropriate access permissions. Different processors have - * // different memory alignment requirements - refer to the FreeRTOS - * documentation - * // for full information. - * { - * // Base address Length Parameters - * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE }, - * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY }, - * { cPrivilegedOnlyAccessArray, 128, - * portMPU_REGION_PRIVILEGED_READ_WRITE } - * } - * }; - * - * int main( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task from the const structure defined above. The task handle - * // is requested (the second parameter is not NULL) but in this case just for - * // demonstration purposes as its not actually used. - * xTaskCreateRestricted( &xRegTest1Parameters, &xHandle ); - * - * // Start the scheduler. - * vTaskStartScheduler(); - * - * // Will only get here if there was insufficient memory to create the idle - * // and/or timer task. - * for( ;; ); - * } - * @endcode - * \defgroup xTaskCreateRestricted xTaskCreateRestricted - * \ingroup Tasks - */ -#if( portUSING_MPU_WRAPPERS == 1 ) -BaseType_t xTaskCreateRestricted( - const TaskParameters_t * const pxTaskDefinition, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configNUMBER_OF_CORES > 1 ) && \ - ( configUSE_CORE_AFFINITY == 1 ) ) -BaseType_t xTaskCreateRestrictedAffinitySet( - const TaskParameters_t * const pxTaskDefinition, - UBaseType_t uxCoreAffinityMask, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * BaseType_t xTaskCreateRestrictedStatic( TaskParameters_t *pxTaskDefinition, - * TaskHandle_t *pxCreatedTask ); - * @endcode - * - * Only available when configSUPPORT_STATIC_ALLOCATION is set to 1. - * - * xTaskCreateRestrictedStatic() should only be used in systems that include an - * MPU implementation. - * - * Internally, within the FreeRTOS implementation, tasks use two blocks of - * memory. The first block is used to hold the task's data structures. The - * second block is used by the task as its stack. If a task is created using - * xTaskCreateRestricted() then the stack is provided by the application writer, - * and the memory used to hold the task's data structure is automatically - * dynamically allocated inside the xTaskCreateRestricted() function. If a task - * is created using xTaskCreateRestrictedStatic() then the application writer - * must provide the memory used to hold the task's data structures too. - * xTaskCreateRestrictedStatic() therefore allows a memory protected task to be - * created without using any dynamic memory allocation. - * - * @param pxTaskDefinition Pointer to a structure that contains a member - * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API - * documentation) plus an optional stack buffer and the memory region - * definitions. If configSUPPORT_STATIC_ALLOCATION is set to 1 the structure - * contains an additional member, which is used to point to a variable of type - * StaticTask_t - which is then used to hold the task's data structure. - * - * @param pxCreatedTask Used to pass back a handle by which the created task - * can be referenced. - * - * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file projdefs.h - * - * Example usage: - * @code{c} - * // Create an TaskParameters_t structure that defines the task to be created. - * // The StaticTask_t variable is only included in the structure when - * // configSUPPORT_STATIC_ALLOCATION is set to 1. The PRIVILEGED_DATA macro - * can - * // be used to force the variable into the RTOS kernel's privileged data area. - * static PRIVILEGED_DATA StaticTask_t xTaskBuffer; - * static const TaskParameters_t xCheckTaskParameters = - * { - * vATask, // pvTaskCode - the function that implements the task. - * "ATask", // pcName - just a text name for the task to assist debugging. - * 100, // usStackDepth - the stack size DEFINED IN WORDS. - * NULL, // pvParameters - passed into the task function as the function - * parameters. ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set - * the portPRIVILEGE_BIT if the task should run in a privileged state. - * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack. - * - * // xRegions - Allocate up to three separate memory regions for access by - * // the task, with appropriate access permissions. Different processors have - * // different memory alignment requirements - refer to the FreeRTOS - * documentation - * // for full information. - * { - * // Base address Length Parameters - * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE }, - * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY }, - * { cPrivilegedOnlyAccessArray, 128, - * portMPU_REGION_PRIVILEGED_READ_WRITE } - * } - * - * &xTaskBuffer; // Holds the task's data structure. - * }; - * - * int main( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task from the const structure defined above. The task handle - * // is requested (the second parameter is not NULL) but in this case just for - * // demonstration purposes as its not actually used. - * xTaskCreateRestrictedStatic( &xRegTest1Parameters, &xHandle ); - * - * // Start the scheduler. - * vTaskStartScheduler(); - * - * // Will only get here if there was insufficient memory to create the idle - * // and/or timer task. - * for( ;; ); - * } - * @endcode - * \defgroup xTaskCreateRestrictedStatic xTaskCreateRestrictedStatic - * \ingroup Tasks - */ -#if( ( portUSING_MPU_WRAPPERS == 1 ) && \ - ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) -BaseType_t xTaskCreateRestrictedStatic( - const TaskParameters_t * const pxTaskDefinition, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -#if( ( portUSING_MPU_WRAPPERS == 1 ) && \ - ( configSUPPORT_STATIC_ALLOCATION == 1 ) && \ - ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) -BaseType_t xTaskCreateRestrictedStaticAffinitySet( - const TaskParameters_t * const pxTaskDefinition, - UBaseType_t uxCoreAffinityMask, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * - * const pxRegions ); - * @endcode - * - * Memory regions are assigned to a restricted task when the task is created by - * a call to xTaskCreateRestricted(). These regions can be redefined using - * vTaskAllocateMPURegions(). - * - * @param xTask The handle of the task being updated. - * - * @param[in] pxRegions A pointer to a MemoryRegion_t structure that contains - * the new memory region definitions. - * - * Example usage: - * @code{c} - * // Define an array of MemoryRegion_t structures that configures an MPU region - * // allowing read/write access for 1024 bytes starting at the beginning of the - * // ucOneKByte array. The other two of the maximum 3 definable regions are - * // unused so set to zero. - * static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] = - * { - * // Base address Length Parameters - * { ucOneKByte, 1024, portMPU_REGION_READ_WRITE }, - * { 0, 0, 0 }, - * { 0, 0, 0 } - * }; - * - * void vATask( void *pvParameters ) - * { - * // This task was created such that it has access to certain regions of - * // memory as defined by the MPU configuration. At some point it is - * // desired that these MPU regions are replaced with that defined in the - * // xAltRegions const struct above. Use a call to vTaskAllocateMPURegions() - * // for this purpose. NULL is used as the task handle to indicate that this - * // function should modify the MPU regions of the calling task. - * vTaskAllocateMPURegions( NULL, xAltRegions ); - * - * // Now the task can continue its function, but from this point on can only - * // access its stack and the ucOneKByte array (unless any other statically - * // defined or shared regions have been declared elsewhere). - * } - * @endcode - * \defgroup vTaskAllocateMPURegions vTaskAllocateMPURegions - * \ingroup Tasks - */ -void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, - const MemoryRegion_t * const pxRegions ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskDelete( TaskHandle_t xTaskToDelete ); - * @endcode - * - * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Remove a task from the RTOS real time kernel's management. The task being - * deleted will be removed from all ready, blocked, suspended and event lists. - * - * NOTE: The idle task is responsible for freeing the kernel allocated - * memory from tasks that have been deleted. It is therefore important that - * the idle task is not starved of microcontroller processing time if your - * application makes any calls to vTaskDelete (). Memory allocated by the - * task code is not automatically freed, and should be freed before the task - * is deleted. - * - * See the demo application file death.c for sample code that utilises - * vTaskDelete (). - * - * @param xTaskToDelete The handle of the task to be deleted. Passing NULL will - * cause the calling task to be deleted. - * - * Example usage: - * @code{c} - * void vOtherFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create the task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // Use the handle to delete the task. - * vTaskDelete( xHandle ); - * } - * @endcode - * \defgroup vTaskDelete vTaskDelete - * \ingroup Tasks - */ -void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- - * TASK CONTROL API - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * void vTaskDelay( const TickType_t xTicksToDelay ); - * @endcode - * - * Delay a task for a given number of ticks. The actual time that the - * task remains blocked depends on the tick rate. The constant - * portTICK_PERIOD_MS can be used to calculate real time from the tick - * rate - with the resolution of one tick period. - * - * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * - * vTaskDelay() specifies a time at which the task wishes to unblock relative to - * the time at which vTaskDelay() is called. For example, specifying a block - * period of 100 ticks will cause the task to unblock 100 ticks after - * vTaskDelay() is called. vTaskDelay() does not therefore provide a good - * method of controlling the frequency of a periodic task as the path taken - * through the code, as well as other task and interrupt activity, will affect - * the frequency at which vTaskDelay() gets called and therefore the time at - * which the task next executes. See xTaskDelayUntil() for an alternative API - * function designed to facilitate fixed frequency execution. It does this by - * specifying an absolute time (rather than a relative time) at which the - * calling task should unblock. - * - * @param xTicksToDelay The amount of time, in tick periods, that - * the calling task should block. - * - * Example usage: - * - * void vTaskFunction( void * pvParameters ) - * { - * // Block for 500ms. - * const TickType_t xDelay = 500 / portTICK_PERIOD_MS; - * - * for( ;; ) - * { - * // Simply toggle the LED every 500ms, blocking between each toggle. - * vToggleLED(); - * vTaskDelay( xDelay ); - * } - * } - * - * \defgroup vTaskDelay vTaskDelay - * \ingroup TaskCtrl - */ -void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * BaseType_t xTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t - * xTimeIncrement ); - * @endcode - * - * INCLUDE_xTaskDelayUntil must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Delay a task until a specified time. This function can be used by periodic - * tasks to ensure a constant execution frequency. - * - * This function differs from vTaskDelay () in one important aspect: vTaskDelay - * () will cause a task to block for the specified number of ticks from the time - * vTaskDelay () is called. It is therefore difficult to use vTaskDelay () by - * itself to generate a fixed execution frequency as the time between a task - * starting to execute and that task calling vTaskDelay () may not be fixed [the - * task may take a different path though the code between calls, or may get - * interrupted or preempted a different number of times each time it executes]. - * - * Whereas vTaskDelay () specifies a wake time relative to the time at which the - * function is called, xTaskDelayUntil () specifies the absolute (exact) time at - * which it wishes to unblock. - * - * The macro pdMS_TO_TICKS() can be used to calculate the number of ticks from a - * time specified in milliseconds with a resolution of one tick period. - * - * @param pxPreviousWakeTime Pointer to a variable that holds the time at which - * the task was last unblocked. The variable must be initialised with the - * current time prior to its first use (see the example below). Following this - * the variable is automatically updated within xTaskDelayUntil (). - * - * @param xTimeIncrement The cycle time period. The task will be unblocked at - * time *pxPreviousWakeTime + xTimeIncrement. Calling xTaskDelayUntil with the - * same xTimeIncrement parameter value will cause the task to execute with - * a fixed interface period. - * - * @return Value which can be used to check whether the task was actually - * delayed. Will be pdTRUE if the task way delayed and pdFALSE otherwise. A - * task will not be delayed if the next expected wake time is in the past. - * - * Example usage: - * @code{c} - * // Perform an action every 10 ticks. - * void vTaskFunction( void * pvParameters ) - * { - * TickType_t xLastWakeTime; - * const TickType_t xFrequency = 10; - * BaseType_t xWasDelayed; - * - * // Initialise the xLastWakeTime variable with the current time. - * xLastWakeTime = xTaskGetTickCount (); - * for( ;; ) - * { - * // Wait for the next cycle. - * xWasDelayed = xTaskDelayUntil( &xLastWakeTime, xFrequency ); - * - * // Perform action here. xWasDelayed value can be used to determine - * // whether a deadline was missed if the code here took too long. - * } - * } - * @endcode - * \defgroup xTaskDelayUntil xTaskDelayUntil - * \ingroup TaskCtrl - */ -BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, - const TickType_t xTimeIncrement ) - PRIVILEGED_FUNCTION; - -/* - * vTaskDelayUntil() is the older version of xTaskDelayUntil() and does not - * return a value. - */ -#define vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ) \ - do \ - { \ - ( void ) xTaskDelayUntil( ( pxPreviousWakeTime ), \ - ( xTimeIncrement ) ); \ - } while( 0 ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskAbortDelay( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this - * function to be available. - * - * A task will enter the Blocked state when it is waiting for an event. The - * event it is waiting for can be a temporal event (waiting for a time), such - * as when vTaskDelay() is called, or an event on an object, such as when - * xQueueReceive() or ulTaskNotifyTake() is called. If the handle of a task - * that is in the Blocked state is used in a call to xTaskAbortDelay() then the - * task will leave the Blocked state, and return from whichever function call - * placed the task into the Blocked state. - * - * There is no 'FromISR' version of this function as an interrupt would need to - * know which object a task was blocked on in order to know which actions to - * take. For example, if the task was blocked on a queue the interrupt handler - * would then need to know if the queue was locked. - * - * @param xTask The handle of the task to remove from the Blocked state. - * - * @return If the task referenced by xTask was not in the Blocked state then - * pdFAIL is returned. Otherwise pdPASS is returned. - * - * \defgroup xTaskAbortDelay xTaskAbortDelay - * \ingroup TaskCtrl - */ -BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Obtain the priority of any task. - * - * @param xTask Handle of the task to be queried. Passing a NULL - * handle results in the priority of the calling task being returned. - * - * @return The priority of xTask. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to obtain the priority of the created task. - * // It was created with tskIDLE_PRIORITY, but may have changed - * // it itself. - * if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY ) - * { - * // The task has changed it's priority. - * } - * - * // ... - * - * // Is our priority higher than the created task? - * if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) ) - * { - * // Our priority (obtained using NULL handle) is higher. - * } - * } - * @endcode - * \defgroup uxTaskPriorityGet uxTaskPriorityGet - * \ingroup TaskCtrl - */ -UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ); - * @endcode - * - * A version of uxTaskPriorityGet() that can be used from an ISR. - */ -UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * eTaskState eTaskGetState( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Obtain the state of any task. States are encoded by the eTaskState - * enumerated type. - * - * @param xTask Handle of the task to be queried. - * - * @return The state of xTask at the time the function was called. Note the - * state of the task might change between the function being called, and the - * functions return value being tested by the calling task. - */ -eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t - * xGetFreeStackSpace, eTaskState eState ); - * @endcode - * - * configUSE_TRACE_FACILITY must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Populates a TaskStatus_t structure with information about a task. - * - * @param xTask Handle of the task being queried. If xTask is NULL then - * information will be returned about the calling task. - * - * @param pxTaskStatus A pointer to the TaskStatus_t structure that will be - * filled with information about the task referenced by the handle passed using - * the xTask parameter. - * - * @param xGetFreeStackSpace The TaskStatus_t structure contains a member to - * report the stack high water mark of the task being queried. Calculating the - * stack high water mark takes a relatively long time, and can make the system - * temporarily unresponsive - so the xGetFreeStackSpace parameter is provided to - * allow the high water mark checking to be skipped. The high watermark value - * will only be written to the TaskStatus_t structure if xGetFreeStackSpace is - * not set to pdFALSE; - * - * @param eState The TaskStatus_t structure contains a member to report the - * state of the task being queried. Obtaining the task state is not as fast as - * a simple assignment - so the eState parameter is provided to allow the state - * information to be omitted from the TaskStatus_t structure. To obtain state - * information then set eState to eInvalid - otherwise the value passed in - * eState will be reported as the task state in the TaskStatus_t structure. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * TaskStatus_t xTaskDetails; - * - * // Obtain the handle of a task from its name. - * xHandle = xTaskGetHandle( "Task_Name" ); - * - * // Check the handle is not NULL. - * configASSERT( xHandle ); - * - * // Use the handle to obtain further information about the task. - * vTaskGetInfo( xHandle, - * &xTaskDetails, - * pdTRUE, // Include the high water mark in xTaskDetails. - * eInvalid ); // Include the task state in xTaskDetails. - * } - * @endcode - * \defgroup vTaskGetInfo vTaskGetInfo - * \ingroup TaskCtrl - */ -void vTaskGetInfo( TaskHandle_t xTask, - TaskStatus_t * pxTaskStatus, - BaseType_t xGetFreeStackSpace, - eTaskState eState ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ); - * @endcode - * - * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Set the priority of any task. - * - * A context switch will occur before the function returns if the priority - * being set is higher than the currently executing task. - * - * @param xTask Handle to the task for which the priority is being set. - * Passing a NULL handle results in the priority of the calling task being set. - * - * @param uxNewPriority The priority to which the task will be set. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to raise the priority of the created task. - * vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 ); - * - * // ... - * - * // Use a NULL handle to raise our priority to the same value. - * vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 ); - * } - * @endcode - * \defgroup vTaskPrioritySet vTaskPrioritySet - * \ingroup TaskCtrl - */ -void vTaskPrioritySet( TaskHandle_t xTask, - UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskSuspend( TaskHandle_t xTaskToSuspend ); - * @endcode - * - * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Suspend any task. When suspended a task will never get any microcontroller - * processing time, no matter what its priority. - * - * Calls to vTaskSuspend are not accumulative - - * i.e. calling vTaskSuspend () twice on the same task still only requires one - * call to vTaskResume () to ready the suspended task. - * - * @param xTaskToSuspend Handle to the task being suspended. Passing a NULL - * handle will cause the calling task to be suspended. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to suspend the created task. - * vTaskSuspend( xHandle ); - * - * // ... - * - * // The created task will not run during this period, unless - * // another task calls vTaskResume( xHandle ). - * - * //... - * - * - * // Suspend ourselves. - * vTaskSuspend( NULL ); - * - * // We cannot get here unless another task calls vTaskResume - * // with our handle as the parameter. - * } - * @endcode - * \defgroup vTaskSuspend vTaskSuspend - * \ingroup TaskCtrl - */ -void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskResume( TaskHandle_t xTaskToResume ); - * @endcode - * - * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Resumes a suspended task. - * - * A task that has been suspended by one or more calls to vTaskSuspend () - * will be made available for running again by a single call to - * vTaskResume (). - * - * @param xTaskToResume Handle to the task being readied. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, - * &xHandle ); - * - * // ... - * - * // Use the handle to suspend the created task. - * vTaskSuspend( xHandle ); - * - * // ... - * - * // The created task will not run during this period, unless - * // another task calls vTaskResume( xHandle ). - * - * //... - * - * - * // Resume the suspended task ourselves. - * vTaskResume( xHandle ); - * - * // The created task will once again get microcontroller processing - * // time in accordance with its priority within the system. - * } - * @endcode - * \defgroup vTaskResume vTaskResume - * \ingroup TaskCtrl - */ -void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void xTaskResumeFromISR( TaskHandle_t xTaskToResume ); - * @endcode - * - * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * An implementation of vTaskResume() that can be called from within an ISR. - * - * A task that has been suspended by one or more calls to vTaskSuspend () - * will be made available for running again by a single call to - * xTaskResumeFromISR (). - * - * xTaskResumeFromISR() should not be used to synchronise a task with an - * interrupt if there is a chance that the interrupt could arrive prior to the - * task being suspended - as this can lead to interrupts being missed. Use of a - * semaphore as a synchronisation mechanism would avoid this eventuality. - * - * @param xTaskToResume Handle to the task being readied. - * - * @return pdTRUE if resuming the task should result in a context switch, - * otherwise pdFALSE. This is used by the ISR to determine if a context switch - * may be required following the ISR. - * - * \defgroup vTaskResumeFromISR vTaskResumeFromISR - * \ingroup TaskCtrl - */ -BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; - -#if( configUSE_CORE_AFFINITY == 1 ) - -/** - * @brief Sets the core affinity mask for a task. - * - * It sets the cores on which a task can run. configUSE_CORE_AFFINITY must - * be defined as 1 for this function to be available. - * - * @param xTask The handle of the task to set the core affinity mask for. - * Passing NULL will set the core affinity mask for the calling task. - * - * @param uxCoreAffinityMask A bitwise value that indicates the cores on - * which the task can run. Cores are numbered from 0 to configNUMBER_OF_CORES - * - 1. For example, to ensure that a task can run on core 0 and core 1, set - * uxCoreAffinityMask to 0x03. - * - * Example usage: - * - * // The function that creates task. - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * UBaseType_t uxCoreAffinityMask; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &( - * xHandle ) ); - * - * // Define the core affinity mask such that this task can only run - * // on core 0 and core 2. - * uxCoreAffinityMask = ( ( 1 << 0 ) | ( 1 << 2 ) ); - * - * //Set the core affinity mask for the task. - * vTaskCoreAffinitySet( xHandle, uxCoreAffinityMask ); - * } - */ -void vTaskCoreAffinitySet( const TaskHandle_t xTask, - UBaseType_t uxCoreAffinityMask ); -#endif - -#if( configUSE_CORE_AFFINITY == 1 ) - -/** - * @brief Gets the core affinity mask for a task. - * - * configUSE_CORE_AFFINITY must be defined as 1 for this function to be - * available. - * - * @param xTask The handle of the task to get the core affinity mask for. - * Passing NULL will get the core affinity mask for the calling task. - * - * @return The core affinity mask which is a bitwise value that indicates - * the cores on which a task can run. Cores are numbered from 0 to - * configNUMBER_OF_CORES - 1. For example, if a task can run on core 0 and core - * 1, the core affinity mask is 0x03. - * - * Example usage: - * - * // Task handle of the networking task - it is populated elsewhere. - * TaskHandle_t xNetworkingTaskHandle; - * - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * UBaseType_t uxNetworkingCoreAffinityMask; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &( - * xHandle ) ); - * - * //Get the core affinity mask for the networking task. - * uxNetworkingCoreAffinityMask = vTaskCoreAffinityGet( - * xNetworkingTaskHandle ); - * - * // Here is a hypothetical scenario, just for the example. Assume that we - * // have 2 cores - Core 0 and core 1. We want to pin the application task - * to - * // the core different than the networking task to ensure that the - * // application task does not interfere with networking. - * if( ( uxNetworkingCoreAffinityMask & ( 1 << 0 ) ) != 0 ) - * { - * // The networking task can run on core 0, pin our task to core 1. - * vTaskCoreAffinitySet( xHandle, ( 1 << 1 ) ); - * } - * else - * { - * // Otherwise, pin our task to core 0. - * vTaskCoreAffinitySet( xHandle, ( 1 << 0 ) ); - * } - * } - */ -UBaseType_t vTaskCoreAffinityGet( ConstTaskHandle_t xTask ); -#endif - -#if( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - -/** - * @brief Disables preemption for a task. - * - * @param xTask The handle of the task to disable preemption. Passing NULL - * disables preemption for the calling task. - * - * Example usage: - * - * void vTaskCode( void *pvParameters ) - * { - * // Silence warnings about unused parameters. - * ( void ) pvParameters; - * - * for( ;; ) - * { - * // ... Perform some function here. - * - * // Disable preemption for this task. - * vTaskPreemptionDisable( NULL ); - * - * // The task will not be preempted when it is executing in this - * portion ... - * - * // ... until the preemption is enabled again. - * vTaskPreemptionEnable( NULL ); - * - * // The task can be preempted when it is executing in this portion. - * } - * } - */ -void vTaskPreemptionDisable( const TaskHandle_t xTask ); -#endif - -#if( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - -/** - * @brief Enables preemption for a task. - * - * @param xTask The handle of the task to enable preemption. Passing NULL - * enables preemption for the calling task. - * - * Example usage: - * - * void vTaskCode( void *pvParameters ) - * { - * // Silence warnings about unused parameters. - * ( void ) pvParameters; - * - * for( ;; ) - * { - * // ... Perform some function here. - * - * // Disable preemption for this task. - * vTaskPreemptionDisable( NULL ); - * - * // The task will not be preempted when it is executing in this - * portion ... - * - * // ... until the preemption is enabled again. - * vTaskPreemptionEnable( NULL ); - * - * // The task can be preempted when it is executing in this portion. - * } - * } - */ -void vTaskPreemptionEnable( const TaskHandle_t xTask ); -#endif - -/*----------------------------------------------------------- - * SCHEDULER CONTROL - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * void vTaskStartScheduler( void ); - * @endcode - * - * Starts the real time kernel tick processing. After calling the kernel - * has control over which tasks are executed and when. - * - * See the demo application file main.c for an example of creating - * tasks and starting the kernel. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * // Create at least one task before starting the kernel. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); - * - * // Start the real time kernel with preemption. - * vTaskStartScheduler (); - * - * // Will not get here unless a task calls vTaskEndScheduler () - * } - * @endcode - * - * \defgroup vTaskStartScheduler vTaskStartScheduler - * \ingroup SchedulerControl - */ -void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskEndScheduler( void ); - * @endcode - * - * NOTE: At the time of writing only the x86 real mode port, which runs on a PC - * in place of DOS, implements this function. - * - * Stops the real time kernel tick. All created tasks will be automatically - * deleted and multitasking (either preemptive or cooperative) will - * stop. Execution then resumes from the point where vTaskStartScheduler () - * was called, as if vTaskStartScheduler () had just returned. - * - * See the demo application file main. c in the demo/PC directory for an - * example that uses vTaskEndScheduler (). - * - * vTaskEndScheduler () requires an exit function to be defined within the - * portable layer (see vPortEndScheduler () in port. c for the PC port). This - * performs hardware specific operations such as stopping the kernel tick. - * - * vTaskEndScheduler () will cause all of the resources allocated by the - * kernel to be freed - but will not free resources allocated by application - * tasks. - * - * Example usage: - * @code{c} - * void vTaskCode( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // At some point we want to end the real time kernel processing - * // so call ... - * vTaskEndScheduler (); - * } - * } - * - * void vAFunction( void ) - * { - * // Create at least one task before starting the kernel. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); - * - * // Start the real time kernel with preemption. - * vTaskStartScheduler (); - * - * // Will only get here when the vTaskCode () task has called - * // vTaskEndScheduler (). When we get here we are back to single task - * // execution. - * } - * @endcode - * - * \defgroup vTaskEndScheduler vTaskEndScheduler - * \ingroup SchedulerControl - */ -void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskSuspendAll( void ); - * @endcode - * - * Suspends the scheduler without disabling interrupts. Context switches will - * not occur while the scheduler is suspended. - * - * After calling vTaskSuspendAll () the calling task will continue to execute - * without risk of being swapped out until a call to xTaskResumeAll () has been - * made. - * - * API functions that have the potential to cause a context switch (for example, - * xTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler - * is suspended. - * - * Example usage: - * @code{c} - * void vTask1( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // ... - * - * // At some point the task wants to perform a long operation during - * // which it does not want to get swapped out. It cannot use - * // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the - * // operation may cause interrupts to be missed - including the - * // ticks. - * - * // Prevent the real time kernel swapping out the task. - * vTaskSuspendAll (); - * - * // Perform the operation here. There is no need to use critical - * // sections as we have all the microcontroller processing time. - * // During this time interrupts will still operate and the kernel - * // tick count will be maintained. - * - * // ... - * - * // The operation is complete. Restart the kernel. - * xTaskResumeAll (); - * } - * } - * @endcode - * \defgroup vTaskSuspendAll vTaskSuspendAll - * \ingroup SchedulerControl - */ -void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * BaseType_t xTaskResumeAll( void ); - * @endcode - * - * Resumes scheduler activity after it was suspended by a call to - * vTaskSuspendAll(). - * - * xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks - * that were previously suspended by a call to vTaskSuspend(). - * - * @return If resuming the scheduler caused a context switch then pdTRUE is - * returned, otherwise pdFALSE is returned. - * - * Example usage: - * @code{c} - * void vTask1( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // ... - * - * // At some point the task wants to perform a long operation during - * // which it does not want to get swapped out. It cannot use - * // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the - * // operation may cause interrupts to be missed - including the - * // ticks. - * - * // Prevent the real time kernel swapping out the task. - * vTaskSuspendAll (); - * - * // Perform the operation here. There is no need to use critical - * // sections as we have all the microcontroller processing time. - * // During this time interrupts will still operate and the real - * // time kernel tick count will be maintained. - * - * // ... - * - * // The operation is complete. Restart the kernel. We want to force - * // a context switch - but there is no point if resuming the scheduler - * // caused a context switch already. - * if( !xTaskResumeAll () ) - * { - * taskYIELD (); - * } - * } - * } - * @endcode - * \defgroup xTaskResumeAll xTaskResumeAll - * \ingroup SchedulerControl - */ -BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- - * TASK UTILITIES - *----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * TickType_t xTaskGetTickCount( void ); - * @endcode - * - * @return The count of ticks since vTaskStartScheduler was called. - * - * \defgroup xTaskGetTickCount xTaskGetTickCount - * \ingroup TaskUtils - */ -TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * TickType_t xTaskGetTickCountFromISR( void ); - * @endcode - * - * @return The count of ticks since vTaskStartScheduler was called. - * - * This is a version of xTaskGetTickCount() that is safe to be called from an - * ISR - provided that TickType_t is the natural word size of the - * microcontroller being used or interrupt nesting is either not supported or - * not being used. - * - * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR - * \ingroup TaskUtils - */ -TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * uint16_t uxTaskGetNumberOfTasks( void ); - * @endcode - * - * @return The number of tasks that the real time kernel is currently managing. - * This includes all ready, blocked and suspended tasks. A task that - * has been deleted but not yet freed by the idle task will also be - * included in the count. - * - * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks - * \ingroup TaskUtils - */ -UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * char *pcTaskGetName( TaskHandle_t xTaskToQuery ); - * @endcode - * - * @return The text (human readable) name of the task referenced by the handle - * xTaskToQuery. A task can query its own name by either passing in its own - * handle, or by setting xTaskToQuery to NULL. - * - * \defgroup pcTaskGetName pcTaskGetName - * \ingroup TaskUtils - */ -char * pcTaskGetName( TaskHandle_t xTaskToQuery ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ); - * @endcode - * - * NOTE: This function takes a relatively long time to complete and should be - * used sparingly. - * - * @return The handle of the task that has the human readable name - * pcNameToQuery. NULL is returned if no matching name is found. - * INCLUDE_xTaskGetHandle must be set to 1 in FreeRTOSConfig.h for - * pcTaskGetHandle() to be available. - * - * \defgroup pcTaskGetHandle pcTaskGetHandle - * \ingroup TaskUtils - */ -TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask, - * StackType_t ** ppuxStackBuffer, - * StaticTask_t ** ppxTaskBuffer ); - * @endcode - * - * Retrieve pointers to a statically created task's data structure - * buffer and stack buffer. These are the same buffers that are supplied - * at the time of creation. - * - * @param xTask The task for which to retrieve the buffers. - * - * @param ppuxStackBuffer Used to return a pointer to the task's stack buffer. - * - * @param ppxTaskBuffer Used to return a pointer to the task's data structure - * buffer. - * - * @return pdTRUE if buffers were retrieved, pdFALSE otherwise. - * - * \defgroup xTaskGetStaticBuffers xTaskGetStaticBuffers - * \ingroup TaskUtils - */ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) -BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask, - StackType_t ** ppuxStackBuffer, - StaticTask_t ** ppxTaskBuffer ) - PRIVILEGED_FUNCTION; -#endif /* configSUPPORT_STATIC_ALLOCATION */ - -/** - * task.h - * @code{c} - * UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for - * this function to be available. - * - * Returns the high water mark of the stack associated with xTask. That is, - * the minimum free stack space there has been (in words, so on a 32 bit machine - * a value of 1 means 4 bytes) since the task started. The smaller the returned - * number the closer the task has come to overflowing its stack. - * - * 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. - * - * @param xTask Handle of the task associated with the stack to be checked. - * Set xTask to NULL to check the stack of the calling task. - * - * @return The smallest amount of free stack space there has been (in words, so - * actual spaces on the stack rather than bytes) since the task referenced by - * xTask was created. - */ -UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskGetStackHighWaterMark2 must be set to 1 in FreeRTOSConfig.h for - * this function to be available. - * - * Returns the high water mark of the stack associated with xTask. That is, - * the minimum free stack space there has been (in words, so on a 32 bit machine - * a value of 1 means 4 bytes) since the task started. The smaller the returned - * number the closer the task has come to overflowing its stack. - * - * 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. - * - * @param xTask Handle of the task associated with the stack to be checked. - * Set xTask to NULL to check the stack of the calling task. - * - * @return The smallest amount of free stack space there has been (in words, so - * actual spaces on the stack rather than bytes) since the task referenced by - * xTask was created. - */ -configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/* When using trace macros it is sometimes necessary to include task.h before - * FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been - * defined, so the following two prototypes will cause a compilation error. This - * can be fixed by simply guarding against the inclusion of these two prototypes - * unless they are explicitly required by the configUSE_APPLICATION_TASK_TAG - * configuration constant. */ -#ifdef configUSE_APPLICATION_TASK_TAG - #if configUSE_APPLICATION_TASK_TAG == 1 - -/** - * task.h - * @code{c} - * void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t - * pxHookFunction ); - * @endcode - * - * Sets pxHookFunction to be the task hook function used by the task xTask. - * Passing xTask as NULL has the effect of setting the calling tasks hook - * function. - */ -void vTaskSetApplicationTaskTag( TaskHandle_t xTask, - TaskHookFunction_t pxHookFunction ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * void xTaskGetApplicationTaskTag( TaskHandle_t xTask ); - * @endcode - * - * Returns the pxHookFunction value assigned to the task xTask. Do not - * call from an interrupt service routine - call - * xTaskGetApplicationTaskTagFromISR() instead. - */ -TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * void xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ); - * @endcode - * - * Returns the pxHookFunction value assigned to the task xTask. Can - * be called from an interrupt service routine. - */ -TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ -#endif /* ifdef configUSE_APPLICATION_TASK_TAG */ - -#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) - -/* Each task contains an array of pointers that is dimensioned by the - * configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. The - * kernel does not use the pointers itself, so the application writer can use - * the pointers for any purpose they wish. The following two functions are - * used to set and query a pointer respectively. */ -void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, - BaseType_t xIndex, - void * pvValue ) PRIVILEGED_FUNCTION; -void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, - BaseType_t xIndex ) - PRIVILEGED_FUNCTION; - -#endif - -#if( configCHECK_FOR_STACK_OVERFLOW > 0 ) - -/** - * task.h - * @code{c} - * void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName); - * @endcode - * - * The application stack overflow hook is called when a stack overflow is - * detected for a task. - * - * Details on stack overflow detection can be found here: - * https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html - * - * @param xTask the task that just exceeded its stack boundaries. - * @param pcTaskName A character string containing the name of the offending - * task. - */ -void vApplicationStackOverflowHook( TaskHandle_t xTask, char * pcTaskName ); - -#endif - -#if( configUSE_IDLE_HOOK == 1 ) - -/** - * task.h - * @code{c} - * void vApplicationIdleHook( void ); - * @endcode - * - * The application idle hook is called by the idle task. - * This allows the application designer to add background functionality without - * the overhead of a separate task. - * NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A - * FUNCTION THAT MIGHT BLOCK. - */ -void vApplicationIdleHook( void ); - -#endif - -#if( configUSE_TICK_HOOK != 0 ) - -/** - * task.h - * @code{c} - * void vApplicationTickHook( void ); - * @endcode - * - * This hook function is called in the system tick handler after any OS work is - * completed. - */ -void vApplicationTickHook( void ); /*lint !e526 Symbol not defined as it is an - application callback. */ - -#endif - -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) - -/** - * task.h - * @code{c} - * void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, - * StackType_t ** ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) - * @endcode - * - * This function is used to provide a statically allocated block of memory to - * FreeRTOS to hold the Idle Task TCB. This function is required when - * configSUPPORT_STATIC_ALLOCATION is set. For more information see this URI: - * https://www.FreeRTOS.org/a00110.html#configSUPPORT_STATIC_ALLOCATION - * - * @param ppxIdleTaskTCBBuffer A handle to a statically allocated TCB buffer - * @param ppxIdleTaskStackBuffer A handle to a statically allocated Stack buffer - * for the idle task - * @param pulIdleTaskStackSize A pointer to the number of elements that will fit - * in the allocated stack buffer - */ -void vApplicationGetIdleTaskMemory( - StaticTask_t ** ppxIdleTaskTCBBuffer, - StackType_t ** ppxIdleTaskStackBuffer, - uint32_t * pulIdleTaskStackSize ); /*lint !e526 Symbol not defined as it is - an application callback. */ -#endif - -/** - * task.h - * @code{c} - * BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void - * *pvParameter ); - * @endcode - * - * Calls the hook function associated with xTask. Passing xTask as NULL has - * the effect of calling the Running tasks (the calling task) hook function. - * - * pvParameter is passed to the hook function for the task to interpret as it - * wants. The return value is the value returned by the task hook function - * registered by the user. - */ -BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, - void * pvParameter ) - PRIVILEGED_FUNCTION; - -/** - * xTaskGetIdleTaskHandle() is only available if - * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. - * - * Simply returns the handle of the idle task. It is not valid to call - * xTaskGetIdleTaskHandle() before the scheduler has been started. - */ -TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; - -/** - * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for - * uxTaskGetSystemState() to be available. - * - * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in - * the system. TaskStatus_t structures contain, among other things, members - * for the task handle, task name, task priority, task state, and total amount - * of run time consumed by the task. See the TaskStatus_t structure - * definition in this file for the full member list. - * - * NOTE: This function is intended for debugging use only as its use results in - * the scheduler remaining suspended for an extended period. - * - * @param pxTaskStatusArray A pointer to an array of TaskStatus_t structures. - * The array must contain at least one TaskStatus_t structure for each task - * that is under the control of the RTOS. The number of tasks under the control - * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API - * function. - * - * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray - * parameter. The size is specified as the number of indexes in the array, or - * the number of TaskStatus_t structures contained in the array, not by the - * number of bytes in the array. - * - * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in - * FreeRTOSConfig.h then *pulTotalRunTime is set by uxTaskGetSystemState() to - * the total run time (as defined by the run time stats clock, see - * https://www.FreeRTOS.org/rtos-run-time-stats.html) since the target booted. - * pulTotalRunTime can be set to NULL to omit the total run time information. - * - * @return The number of TaskStatus_t structures that were populated by - * uxTaskGetSystemState(). This should equal the number returned by the - * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed - * in the uxArraySize parameter was too small. - * - * Example usage: - * @code{c} - * // This example demonstrates how a human readable table of run time stats - * // information is generated from raw data provided by - * uxTaskGetSystemState(). - * // The human readable table is written to pcWriteBuffer - * void vTaskGetRunTimeStats( char *pcWriteBuffer ) - * { - * TaskStatus_t *pxTaskStatusArray; - * volatile UBaseType_t uxArraySize, x; - * configRUN_TIME_COUNTER_TYPE ulTotalRunTime, ulStatsAsPercentage; - * - * // Make sure the write buffer does not contain a string. - * pcWriteBuffer = 0x00; - * - * // Take a snapshot of the number of tasks in case it changes while this - * // function is executing. - * uxArraySize = uxTaskGetNumberOfTasks(); - * - * // Allocate a TaskStatus_t structure for each task. An array could be - * // allocated statically at compile time. - * pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) - * ); - * - * if( pxTaskStatusArray != NULL ) - * { - * // Generate raw status information about each task. - * uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, - * &ulTotalRunTime ); - * - * // For percentage calculations. - * ulTotalRunTime /= 100UL; - * - * // Avoid divide by zero errors. - * if( ulTotalRunTime > 0 ) - * { - * // For each populated position in the pxTaskStatusArray array, - * // format the raw data as human readable ASCII 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. - * // ulTotalRunTimeDiv100 has already been divided by 100. - * ulStatsAsPercentage = pxTaskStatusArray[ x - * ].ulRunTimeCounter / ulTotalRunTime; - * - * if( ulStatsAsPercentage > 0UL ) - * { - * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", - * pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, - * ulStatsAsPercentage ); - * } - * else - * { - * // If the percentage is zero here then the task has - * // consumed less than 1% of the total run time. - * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", - * pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter ); - * } - * - * pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); - * } - * } - * - * // The array is no longer needed, free the memory it consumes. - * vPortFree( pxTaskStatusArray ); - * } - * } - * @endcode - */ -UBaseType_t uxTaskGetSystemState( - TaskStatus_t * const pxTaskStatusArray, - const UBaseType_t uxArraySize, - configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskList( char *pcWriteBuffer ); - * @endcode - * - * configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must - * both be defined as 1 for this function to be available. See the - * configuration section of the FreeRTOS.org website for more information. - * - * NOTE 1: This function will disable interrupts for its duration. It is - * not intended for normal application runtime use but as a debug aid. - * - * Lists all the current tasks, along with their current state and stack - * usage high water mark. - * - * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or - * suspended ('S'). - * - * 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(). - * - * @param pcWriteBuffer A buffer into which the above mentioned details - * will be written, in ASCII form. This buffer is assumed to be large - * enough to contain the generated report. Approximately 40 bytes per - * task should be sufficient. - * - * \defgroup vTaskList vTaskList - * \ingroup TaskUtils - */ -void vTaskList( char * pcWriteBuffer ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * void vTaskGetRunTimeStats( char *pcWriteBuffer ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS - * must both be defined as 1 for this function to be available. The application - * must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() - * to configure a peripheral timer/counter and return the timers current count - * value respectively. The counter should be at least 10 times the frequency of - * the tick count. - * - * NOTE 1: This function will disable interrupts for its duration. It is - * not intended for normal application runtime use but as a debug aid. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * Calling vTaskGetRunTimeStats() writes the total execution time of each - * task into a buffer, both as an absolute count value and as a percentage - * of the total system execution time. - * - * NOTE 2: - * - * 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(). - * - * @param pcWriteBuffer A buffer into which the execution times will be - * written, in ASCII form. This buffer is assumed to be large enough to - * contain the generated report. Approximately 40 bytes per task should - * be sufficient. - * - * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats - * \ingroup TaskUtils - */ -void vTaskGetRunTimeStats( char * pcWriteBuffer ) - PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for - strings and single characters only. */ - -/** - * task. h - * @code{c} - * configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask - * ); configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t - * xTask ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS must be defined as 1 for these functions to be - * available. The application must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() to configure a peripheral timer/counter and - * return the timers current count value respectively. The counter should be - * at least 10 times the frequency of the tick count. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total - * execution time of each task into a buffer, ulTaskGetRunTimeCounter() - * returns the total execution time of just one task and - * ulTaskGetRunTimePercent() returns the percentage of the CPU time used by - * just one task. - * - * @return The total run time of the given task or the percentage of the total - * run time consumed by the given task. This is the amount of time the task - * has actually been executing. The unit of time is dependent on the frequency - * configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() macros. - * - * \defgroup ulTaskGetRunTimeCounter ulTaskGetRunTimeCounter - * \ingroup TaskUtils - */ -configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; -configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t xTask ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ); - * configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS must be defined as 1 for these functions to be - * available. The application must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() to configure a peripheral timer/counter and - * return the timers current count value respectively. The counter should be - * at least 10 times the frequency of the tick count. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total - * execution time of each task into a buffer, ulTaskGetIdleRunTimeCounter() - * returns the total execution time of just the idle task and - * ulTaskGetIdleRunTimePercent() returns the percentage of the CPU time used by - * just the idle task. - * - * Note the amount of idle time is only a good measure of the slack time in a - * system if there are no other tasks executing at the idle priority, tickless - * idle is not used, and configIDLE_SHOULD_YIELD is set to 0. - * - * @return The total run time of the idle task or the percentage of the total - * run time consumed by the idle task. This is the amount of time the - * idle task has actually been executing. The unit of time is dependent on the - * frequency configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() macros. - * - * \defgroup ulTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter - * \ingroup TaskUtils - */ -configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ) - PRIVILEGED_FUNCTION; -configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ) - PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyIndexed( TaskHandle_t xTaskToNotify, UBaseType_t - * uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction ); BaseType_t - * xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction - * eAction ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * Sends a direct to task notification to a task, with an optional value and - * action. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * A task can use xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() to - * [optionally] block to wait for a notification to be pending. The task does - * not consume any CPU time while it is in the Blocked state. - * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their - * un-indexed equivalents). If the task was already in the Blocked state to - * wait for a notification when the notification arrives then the task will - * automatically be removed from the Blocked state (unblocked) and the - * notification cleared. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotify() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling xTaskNotify() is equivalent to calling xTaskNotifyIndexed() - * with the uxIndexToNotify parameter set to 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotify() does - * not have this parameter and always sends notifications to index 0. - * - * @param ulValue Data that can be sent with the notification. How the data is - * used depends on the value of the eAction parameter. - * - * @param eAction Specifies how the notification updates the task's notification - * value, if at all. Valid values for eAction are as follows: - * - * eSetBits - - * The target notification value is bitwise ORed with ulValue. - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * eIncrement - - * The target notification value is incremented. ulValue is not used and - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * eSetValueWithOverwrite - - * The target notification value is set to the value of ulValue, even if the - * task being notified had not yet processed the previous notification at the - * same array index (the task already had a notification pending at that index). - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * eSetValueWithoutOverwrite - - * If the task being notified did not already have a notification pending at the - * same array index then the target notification value is set to ulValue and - * xTaskNotifyIndexed() will return pdPASS. If the task being notified already - * had a notification pending at the same array index then no action is - * performed and pdFAIL is returned. - * - * eNoAction - - * The task receives a notification at the specified array index without the - * notification value at that index being updated. ulValue is not used and - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * pulPreviousNotificationValue - - * Can be used to pass out the subject task's notification value before any - * bits are modified by the notify function. - * - * @return Dependent on the value of eAction. See the description of the - * eAction parameter. - * - * \defgroup xTaskNotifyIndexed xTaskNotifyIndexed - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, - UBaseType_t uxIndexToNotify, - uint32_t ulValue, - eNotifyAction eAction, - uint32_t * pulPreviousNotificationValue ) - PRIVILEGED_FUNCTION; -#define xTaskNotify( xTaskToNotify, ulValue, eAction ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - NULL ) -#define xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - NULL ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyAndQueryIndexed( TaskHandle_t xTaskToNotify, - * UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, - * uint32_t *pulPreviousNotifyValue ); BaseType_t xTaskNotifyAndQuery( - * TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t - * *pulPreviousNotifyValue ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * xTaskNotifyAndQueryIndexed() performs the same operation as - * xTaskNotifyIndexed() with the addition that it also returns the subject - * task's prior notification value (the notification value at the time the - * function is called rather than when the function returns) in the additional - * pulPreviousNotifyValue parameter. - * - * xTaskNotifyAndQuery() performs the same operation as xTaskNotify() with the - * addition that it also returns the subject task's prior notification value - * (the notification value as it was at the time the function is called, rather - * than when the function returns) in the additional pulPreviousNotifyValue - * parameter. - * - * \defgroup xTaskNotifyAndQueryIndexed xTaskNotifyAndQueryIndexed - * \ingroup TaskNotifications - */ -#define xTaskNotifyAndQuery( xTaskToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotifyValue ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotifyValue ) ) -#define xTaskNotifyAndQueryIndexed( xTaskToNotify, \ - uxIndexToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotifyValue ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotifyValue ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t - * uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t - * *pxHigherPriorityTaskWoken ); BaseType_t xTaskNotifyFromISR( TaskHandle_t - * xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t - * *pxHigherPriorityTaskWoken ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * A version of xTaskNotifyIndexed() that can be used from an interrupt service - * routine (ISR). - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] - * block to wait for a notification value to have a non-zero value. The task - * does not consume any CPU time while it is in the Blocked state. - * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their - * un-indexed equivalents). If the task was already in the Blocked state to - * wait for a notification when the notification arrives then the task will - * automatically be removed from the Blocked state (unblocked) and the - * notification cleared. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyFromISR() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling xTaskNotifyFromISR() is equivalent to calling - * xTaskNotifyIndexedFromISR() with the uxIndexToNotify parameter set to 0. - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyFromISR() - * does not have this parameter and always sends notifications to index 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param ulValue Data that can be sent with the notification. How the data is - * used depends on the value of the eAction parameter. - * - * @param eAction Specifies how the notification updates the task's notification - * value, if at all. Valid values for eAction are as follows: - * - * eSetBits - - * The task's notification value is bitwise ORed with ulValue. xTaskNotify() - * always returns pdPASS in this case. - * - * eIncrement - - * The task's notification value is incremented. ulValue is not used and - * xTaskNotify() always returns pdPASS in this case. - * - * eSetValueWithOverwrite - - * The task's notification value is set to the value of ulValue, even if the - * task being notified had not yet processed the previous notification (the - * task already had a notification pending). xTaskNotify() always returns - * pdPASS in this case. - * - * eSetValueWithoutOverwrite - - * If the task being notified did not already have a notification pending then - * the task's notification value is set to ulValue and xTaskNotify() will - * return pdPASS. If the task being notified already had a notification - * pending then no action is performed and pdFAIL is returned. - * - * eNoAction - - * The task receives a notification without its notification value being - * updated. ulValue is not used and xTaskNotify() always returns pdPASS in - * this case. - * - * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set - * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the - * task to which the notification was sent to leave the Blocked state, and the - * unblocked task has a priority higher than the currently running task. If - * xTaskNotifyFromISR() sets this value to pdTRUE then a context switch should - * be requested before the interrupt is exited. How a context switch is - * requested from an ISR is dependent on the port - see the documentation page - * for the port in use. - * - * @return Dependent on the value of eAction. See the description of the - * eAction parameter. - * - * \defgroup xTaskNotifyIndexedFromISR xTaskNotifyIndexedFromISR - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, - UBaseType_t uxIndexToNotify, - uint32_t ulValue, - eNotifyAction eAction, - uint32_t * pulPreviousNotificationValue, - BaseType_t * pxHigherPriorityTaskWoken ) - PRIVILEGED_FUNCTION; -#define xTaskNotifyFromISR( xTaskToNotify, \ - ulValue, \ - eAction, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - NULL, \ - ( pxHigherPriorityTaskWoken ) ) -#define xTaskNotifyIndexedFromISR( xTaskToNotify, \ - uxIndexToNotify, \ - ulValue, \ - eAction, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - NULL, \ - ( pxHigherPriorityTaskWoken ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify, - * UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, - * uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken - * ); BaseType_t xTaskNotifyAndQueryFromISR( TaskHandle_t xTaskToNotify, - * uint32_t ulValue, eNotifyAction eAction, uint32_t - * *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * xTaskNotifyAndQueryIndexedFromISR() performs the same operation as - * xTaskNotifyIndexedFromISR() with the addition that it also returns the - * subject task's prior notification value (the notification value at the time - * the function is called rather than at the time the function returns) in the - * additional pulPreviousNotifyValue parameter. - * - * xTaskNotifyAndQueryFromISR() performs the same operation as - * xTaskNotifyFromISR() with the addition that it also returns the subject - * task's prior notification value (the notification value at the time the - * function is called rather than at the time the function returns) in the - * additional pulPreviousNotifyValue parameter. - * - * \defgroup xTaskNotifyAndQueryIndexedFromISR xTaskNotifyAndQueryIndexedFromISR - * \ingroup TaskNotifications - */ -#define xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, \ - uxIndexToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotificationValue, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotificationValue ), \ - ( pxHigherPriorityTaskWoken ) ) -#define xTaskNotifyAndQueryFromISR( xTaskToNotify, \ - ulValue, \ - eAction, \ - pulPreviousNotificationValue, \ - pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulValue ), \ - ( eAction ), \ - ( pulPreviousNotificationValue ), \ - ( pxHigherPriorityTaskWoken ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyWaitIndexed( UBaseType_t uxIndexToWaitOn, uint32_t - * ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t - * *pulNotificationValue, TickType_t xTicksToWait ); - * - * BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t - * ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait - * ); - * @endcode - * - * Waits for a direct to task notification to be pending at a given index within - * an array of direct to task notifications. - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this - * function to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their - * un-indexed equivalents). If the task was already in the Blocked state to - * wait for a notification when the notification arrives then the task will - * automatically be removed from the Blocked state (unblocked) and the - * notification cleared. - * - * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] - * block to wait for a notification value to have a non-zero value. The task - * does not consume any CPU time while it is in the Blocked state. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyWait() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling xTaskNotifyWait() is equivalent to calling - * xTaskNotifyWaitIndexed() with the uxIndexToWaitOn parameter set to 0. - * - * @param uxIndexToWaitOn The index within the calling task's array of - * notification values on which the calling task will wait for a notification to - * be received. uxIndexToWaitOn must be less than - * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyWait() does - * not have this parameter and always waits for notifications on index 0. - * - * @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value - * will be cleared in the calling task's notification value before the task - * checks to see if any notifications are pending, and optionally blocks if no - * notifications are pending. Setting ulBitsToClearOnEntry to ULONG_MAX (if - * limits.h is included) or 0xffffffffUL (if limits.h is not included) will have - * the effect of resetting the task's notification value to 0. Setting - * ulBitsToClearOnEntry to 0 will leave the task's notification value unchanged. - * - * @param ulBitsToClearOnExit If a notification is pending or received before - * the calling task exits the xTaskNotifyWait() function then the task's - * notification value (see the xTaskNotify() API function) is passed out using - * the pulNotificationValue parameter. Then any bits that are set in - * ulBitsToClearOnExit will be cleared in the task's notification value (note - * *pulNotificationValue is set before any bits are cleared). Setting - * ulBitsToClearOnExit to ULONG_MAX (if limits.h is included) or 0xffffffffUL - * (if limits.h is not included) will have the effect of resetting the task's - * notification value to 0 before the function exits. Setting - * ulBitsToClearOnExit to 0 will leave the task's notification value unchanged - * when the function exits (in which case the value passed out in - * pulNotificationValue will match the task's notification value). - * - * @param pulNotificationValue Used to pass the task's notification value out - * of the function. Note the value passed out will not be effected by the - * clearing of any bits caused by ulBitsToClearOnExit being non-zero. - * - * @param xTicksToWait The maximum amount of time that the task should wait in - * the Blocked state for a notification to be received, should a notification - * not already be pending when xTaskNotifyWait() was called. The task - * will not consume any processing time while it is in the Blocked state. This - * is specified in kernel ticks, the macro pdMS_TO_TICKS( value_in_ms ) can be - * used to convert a time specified in milliseconds to a time specified in - * ticks. - * - * @return If a notification was received (including notifications that were - * already pending when xTaskNotifyWait was called) then pdPASS is - * returned. Otherwise pdFAIL is returned. - * - * \defgroup xTaskNotifyWaitIndexed xTaskNotifyWaitIndexed - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, - uint32_t ulBitsToClearOnEntry, - uint32_t ulBitsToClearOnExit, - uint32_t * pulNotificationValue, - TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -#define xTaskNotifyWait( ulBitsToClearOnEntry, \ - ulBitsToClearOnExit, \ - pulNotificationValue, \ - xTicksToWait ) \ - xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, \ - ( ulBitsToClearOnEntry ), \ - ( ulBitsToClearOnExit ), \ - ( pulNotificationValue ), \ - ( xTicksToWait ) ) -#define xTaskNotifyWaitIndexed( uxIndexToWaitOn, \ - ulBitsToClearOnEntry, \ - ulBitsToClearOnExit, \ - pulNotificationValue, \ - xTicksToWait ) \ - xTaskGenericNotifyWait( ( uxIndexToWaitOn ), \ - ( ulBitsToClearOnEntry ), \ - ( ulBitsToClearOnExit ), \ - ( pulNotificationValue ), \ - ( xTicksToWait ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t - * uxIndexToNotify ); BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify ); - * @endcode - * - * Sends a direct to task notification to a particular index in the target - * task's notification array in a manner similar to giving a counting semaphore. - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * macros to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * xTaskNotifyGiveIndexed() is a helper macro intended for use when task - * notifications are used as light weight and faster binary or counting - * semaphore equivalents. Actual FreeRTOS semaphores are given using the - * xSemaphoreGive() API function, the equivalent action that instead uses a task - * notification is xTaskNotifyGiveIndexed(). - * - * When task notifications are being used as a binary or counting semaphore - * equivalent then the task being notified should wait for the notification - * using the ulTaskNotifyTakeIndexed() API function rather than the - * xTaskNotifyWaitIndexed() API function. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyGive() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling xTaskNotifyGive() is equivalent to calling - * xTaskNotifyGiveIndexed() with the uxIndexToNotify parameter set to 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyGive() - * does not have this parameter and always sends notifications to index 0. - * - * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the - * eAction parameter set to eIncrement - so pdPASS is always returned. - * - * \defgroup xTaskNotifyGiveIndexed xTaskNotifyGiveIndexed - * \ingroup TaskNotifications - */ -#define xTaskNotifyGive( xTaskToNotify ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( 0 ), \ - eIncrement, \ - NULL ) -#define xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify ) \ - xTaskGenericNotify( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( 0 ), \ - eIncrement, \ - NULL ) - -/** - * task. h - * @code{c} - * void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t - * uxIndexToNotify, BaseType_t *pxHigherPriorityTaskWoken ); void - * vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t - * *pxHigherPriorityTaskWoken ); - * @endcode - * - * A version of xTaskNotifyGiveIndexed() that can be called from an interrupt - * service routine (ISR). - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro - * to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * vTaskNotifyGiveIndexedFromISR() is intended for use when task notifications - * are used as light weight and faster binary or counting semaphore equivalents. - * Actual FreeRTOS semaphores are given from an ISR using the - * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses - * a task notification is vTaskNotifyGiveIndexedFromISR(). - * - * When task notifications are being used as a binary or counting semaphore - * equivalent then the task being notified should wait for the notification - * using the ulTaskNotifyTakeIndexed() API function rather than the - * xTaskNotifyWaitIndexed() API function. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyFromISR() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling xTaskNotifyGiveFromISR() is equivalent to calling - * xTaskNotifyGiveIndexedFromISR() with the uxIndexToNotify parameter set to 0. - * - * @param xTaskToNotify The handle of the task being notified. The handle to a - * task can be returned from the xTaskCreate() API function used to create the - * task, and the handle of the currently running task can be obtained by calling - * xTaskGetCurrentTaskHandle(). - * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. - * xTaskNotifyGiveFromISR() does not have this parameter and always sends - * notifications to index 0. - * - * @param pxHigherPriorityTaskWoken vTaskNotifyGiveFromISR() will set - * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the - * task to which the notification was sent to leave the Blocked state, and the - * unblocked task has a priority higher than the currently running task. If - * vTaskNotifyGiveFromISR() sets this value to pdTRUE then a context switch - * should be requested before the interrupt is exited. How a context switch is - * requested from an ISR is dependent on the port - see the documentation page - * for the port in use. - * - * \defgroup vTaskNotifyGiveIndexedFromISR vTaskNotifyGiveIndexedFromISR - * \ingroup TaskNotifications - */ -void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify, - UBaseType_t uxIndexToNotify, - BaseType_t * pxHigherPriorityTaskWoken ) - PRIVILEGED_FUNCTION; -#define vTaskNotifyGiveFromISR( xTaskToNotify, pxHigherPriorityTaskWoken ) \ - vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( pxHigherPriorityTaskWoken ) ) -#define vTaskNotifyGiveIndexedFromISR( xTaskToNotify, \ - uxIndexToNotify, \ - pxHigherPriorityTaskWoken ) \ - vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), \ - ( uxIndexToNotify ), \ - ( pxHigherPriorityTaskWoken ) ) - -/** - * task. h - * @code{c} - * uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn, BaseType_t - * xClearCountOnExit, TickType_t xTicksToWait ); - * - * uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t - * xTicksToWait ); - * @endcode - * - * Waits for a direct to task notification on a particular index in the calling - * task's notification array in a manner similar to taking a counting semaphore. - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this - * function to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * Events can be sent to a task using an intermediary object. Examples of such - * objects are queues, semaphores, mutexes and event groups. Task notifications - * are a method of sending an event directly to a task without the need for such - * an intermediary object. - * - * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment one of the task's notification values. In - * that way task notifications can be used to send data to a task, or be used as - * light weight and fast binary or counting semaphores. - * - * ulTaskNotifyTakeIndexed() is intended for use when a task notification is - * used as a faster and lighter weight binary or counting semaphore alternative. - * Actual FreeRTOS semaphores are taken using the xSemaphoreTake() API function, - * the equivalent action that instead uses a task notification is - * ulTaskNotifyTakeIndexed(). - * - * When a task is using its notification value as a binary or counting semaphore - * other tasks should send notifications to it using the - * xTaskNotifyGiveIndexed() macro, or xTaskNotifyIndex() function with the - * eAction parameter set to eIncrement. - * - * ulTaskNotifyTakeIndexed() can either clear the task's notification value at - * the array index specified by the uxIndexToWaitOn parameter to zero on exit, - * in which case the notification value acts like a binary semaphore, or - * decrement the notification value on exit, in which case the notification - * value acts like a counting semaphore. - * - * A task can use ulTaskNotifyTakeIndexed() to [optionally] block to wait for - * a notification. The task does not consume any CPU time while it is in the - * Blocked state. - * - * Where as xTaskNotifyWaitIndexed() will return when a notification is pending, - * ulTaskNotifyTakeIndexed() will return when the task's notification value is - * not zero. - * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. ulTaskNotifyTake() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling ulTaskNotifyTake() is equivalent to calling - * ulTaskNotifyTakeIndexed() with the uxIndexToWaitOn parameter set to 0. - * - * @param uxIndexToWaitOn The index within the calling task's array of - * notification values on which the calling task will wait for a notification to - * be non-zero. uxIndexToWaitOn must be less than - * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyTake() does - * not have this parameter and always waits for notifications on index 0. - * - * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's - * notification value is decremented when the function exits. In this way the - * notification value acts like a counting semaphore. If xClearCountOnExit is - * not pdFALSE then the task's notification value is cleared to zero when the - * function exits. In this way the notification value acts like a binary - * semaphore. - * - * @param xTicksToWait The maximum amount of time that the task should wait in - * the Blocked state for the task's notification value to be greater than zero, - * should the count not already be greater than zero when - * ulTaskNotifyTake() was called. The task will not consume any processing - * time while it is in the Blocked state. This is specified in kernel ticks, - * the macro pdMS_TO_TICKS( value_in_ms ) can be used to convert a time - * specified in milliseconds to a time specified in ticks. - * - * @return The task's notification count before it is either cleared to zero or - * decremented (see the xClearCountOnExit parameter). - * - * \defgroup ulTaskNotifyTakeIndexed ulTaskNotifyTakeIndexed - * \ingroup TaskNotifications - */ -uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, - BaseType_t xClearCountOnExit, - TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -#define ulTaskNotifyTake( xClearCountOnExit, xTicksToWait ) \ - ulTaskGenericNotifyTake( ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( xClearCountOnExit ), \ - ( xTicksToWait ) ) -#define ulTaskNotifyTakeIndexed( uxIndexToWaitOn, \ - xClearCountOnExit, \ - xTicksToWait ) \ - ulTaskGenericNotifyTake( ( uxIndexToWaitOn ), \ - ( xClearCountOnExit ), \ - ( xTicksToWait ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t - * uxIndexToCLear ); - * - * BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * If a notification is sent to an index within the array of notifications then - * the notification at that index is said to be 'pending' until it is read or - * explicitly cleared by the receiving task. xTaskNotifyStateClearIndexed() - * is the function that clears a pending notification without reading the - * notification value. The notification value at the same array index is not - * altered. Set xTask to NULL to clear the notification state of the calling - * task. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotifyStateClear() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling xTaskNotifyStateClear() is equivalent to calling - * xTaskNotifyStateClearIndexed() with the uxIndexToNotify parameter set to 0. - * - * @param xTask The handle of the RTOS task that will have a notification state - * cleared. Set xTask to NULL to clear a notification state in the calling - * task. To obtain a task's handle create the task using xTaskCreate() and - * make use of the pxCreatedTask parameter, or create the task using - * xTaskCreateStatic() and store the returned value, or use the task's name in - * a call to xTaskGetHandle(). - * - * @param uxIndexToClear The index within the target task's array of - * notification values to act upon. For example, setting uxIndexToClear to 1 - * will clear the state of the notification at index 1 within the array. - * uxIndexToClear must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. - * ulTaskNotifyStateClear() does not have this parameter and always acts on the - * notification at index 0. - * - * @return pdTRUE if the task's notification state was set to - * eNotWaitingNotification, otherwise pdFALSE. - * - * \defgroup xTaskNotifyStateClearIndexed xTaskNotifyStateClearIndexed - * \ingroup TaskNotifications - */ -BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask, - UBaseType_t uxIndexToClear ) - PRIVILEGED_FUNCTION; -#define xTaskNotifyStateClear( xTask ) \ - xTaskGenericNotifyStateClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ) ) -#define xTaskNotifyStateClearIndexed( xTask, uxIndexToClear ) \ - xTaskGenericNotifyStateClear( ( xTask ), ( uxIndexToClear ) ) - -/** - * task. h - * @code{c} - * uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, UBaseType_t - * uxIndexToClear, uint32_t ulBitsToClear ); - * - * uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear - * ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. - * - * Each task has a private array of "notification values" (or 'notifications'), - * each of which is a 32-bit unsigned integer (uint32_t). The constant - * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the - * array, and (for backward compatibility) defaults to 1 if left undefined. - * Prior to FreeRTOS V10.4.0 there was only one notification value per task. - * - * ulTaskNotifyValueClearIndexed() clears the bits specified by the - * ulBitsToClear bit mask in the notification value at array index - * uxIndexToClear of the task referenced by xTask. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. ulTaskNotifyValueClear() is the original API function, and remains - * backward compatible by always operating on the notification value at index 0 - * within the array. Calling ulTaskNotifyValueClear() is equivalent to calling - * ulTaskNotifyValueClearIndexed() with the uxIndexToClear parameter set to 0. - * - * @param xTask The handle of the RTOS task that will have bits in one of its - * notification values cleared. Set xTask to NULL to clear bits in a - * notification value of the calling task. To obtain a task's handle create the - * task using xTaskCreate() and make use of the pxCreatedTask parameter, or - * create the task using xTaskCreateStatic() and store the returned value, or - * use the task's name in a call to xTaskGetHandle(). - * - * @param uxIndexToClear The index within the target task's array of - * notification values in which to clear the bits. uxIndexToClear - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. - * ulTaskNotifyValueClear() does not have this parameter and always clears bits - * in the notification value at index 0. - * - * @param ulBitsToClear Bit mask of the bits to clear in the notification value - * of xTask. Set a bit to 1 to clear the corresponding bits in the task's - * notification value. Set ulBitsToClear to 0xffffffff (UINT_MAX on 32-bit - * architectures) to clear the notification value to 0. Set ulBitsToClear to 0 - * to query the task's notification value without clearing any bits. - * - * - * @return The value of the target task's notification value before the bits - * specified by ulBitsToClear were cleared. - * \defgroup ulTaskNotifyValueClear ulTaskNotifyValueClear - * \ingroup TaskNotifications - */ -uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask, - UBaseType_t uxIndexToClear, - uint32_t ulBitsToClear ) - PRIVILEGED_FUNCTION; -#define ulTaskNotifyValueClear( xTask, ulBitsToClear ) \ - ulTaskGenericNotifyValueClear( ( xTask ), \ - ( tskDEFAULT_INDEX_TO_NOTIFY ), \ - ( ulBitsToClear ) ) -#define ulTaskNotifyValueClearIndexed( xTask, uxIndexToClear, ulBitsToClear ) \ - ulTaskGenericNotifyValueClear( ( xTask ), \ - ( uxIndexToClear ), \ - ( ulBitsToClear ) ) - -/** - * task.h - * @code{c} - * void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ); - * @endcode - * - * Capture the current time for future use with xTaskCheckForTimeOut(). - * - * @param pxTimeOut Pointer to a timeout object into which the current time - * is to be captured. The captured time includes the tick count and the number - * of times the tick count has overflowed since the system first booted. - * \defgroup vTaskSetTimeOutState vTaskSetTimeOutState - * \ingroup TaskCtrl - */ -void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * - * const pxTicksToWait ); - * @endcode - * - * Determines if pxTicksToWait ticks has passed since a time was captured - * using a call to vTaskSetTimeOutState(). The captured time includes the tick - * count and the number of times the tick count has overflowed. - * - * @param pxTimeOut The time status as captured previously using - * vTaskSetTimeOutState. If the timeout has not yet occurred, it is updated - * to reflect the current time status. - * @param pxTicksToWait The number of ticks to check for timeout i.e. if - * pxTicksToWait ticks have passed since pxTimeOut was last updated (either by - * vTaskSetTimeOutState() or xTaskCheckForTimeOut()), the timeout has occurred. - * If the timeout has not occurred, pxTicksToWait is updated to reflect the - * number of remaining ticks. - * - * @return If timeout has occurred, pdTRUE is returned. Otherwise pdFALSE is - * returned and pxTicksToWait is updated to reflect the number of remaining - * ticks. - * - * @see https://www.FreeRTOS.org/xTaskCheckForTimeOut.html - * - * Example Usage: - * @code{c} - * // Driver library function used to receive uxWantedBytes from an Rx buffer - * // that is filled by a UART interrupt. If there are not enough bytes in the - * // Rx buffer then the task enters the Blocked state until it is notified - * that - * // more data has been placed into the buffer. If there is still not enough - * // data then the task re-enters the Blocked state, and - * xTaskCheckForTimeOut() - * // is used to re-calculate the Block time to ensure the total amount of time - * // spent in the Blocked state does not exceed MAX_TIME_TO_WAIT. This - * // continues until either the buffer contains at least uxWantedBytes bytes, - * // or the total amount of time spent in the Blocked state reaches - * // MAX_TIME_TO_WAIT - at which point the task reads however many bytes are - * // available up to a maximum of uxWantedBytes. - * - * size_t xUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes ) - * { - * size_t uxReceived = 0; - * TickType_t xTicksToWait = MAX_TIME_TO_WAIT; - * TimeOut_t xTimeOut; - * - * // Initialize xTimeOut. This records the time at which this function - * // was entered. - * vTaskSetTimeOutState( &xTimeOut ); - * - * // Loop until the buffer contains the wanted number of bytes, or a - * // timeout occurs. - * while( UART_bytes_in_rx_buffer( pxUARTInstance ) < uxWantedBytes ) - * { - * // The buffer didn't contain enough data so this task is going to - * // enter the Blocked state. Adjusting xTicksToWait to account for - * // any time that has been spent in the Blocked state within this - * // function so far to ensure the total amount of time spent in the - * // Blocked state does not exceed MAX_TIME_TO_WAIT. - * if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) != pdFALSE ) - * { - * //Timed out before the wanted number of bytes were available, - * // exit the loop. - * break; - * } - * - * // Wait for a maximum of xTicksToWait ticks to be notified that the - * // receive interrupt has placed more data into the buffer. - * ulTaskNotifyTake( pdTRUE, xTicksToWait ); - * } - * - * // Attempt to read uxWantedBytes from the receive buffer into pucBuffer. - * // The actual number of bytes read (which might be less than - * // uxWantedBytes) is returned. - * uxReceived = UART_read_from_receive_buffer( pxUARTInstance, - * pucBuffer, - * uxWantedBytes ); - * - * return uxReceived; - * } - * @endcode - * \defgroup xTaskCheckForTimeOut xTaskCheckForTimeOut - * \ingroup TaskCtrl - */ -BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, - TickType_t * const pxTicksToWait ) - PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ); - * @endcode - * - * This function corrects the tick count value after the application code has - * held interrupts disabled for an extended period resulting in tick interrupts - * having been missed. - * - * This function is similar to vTaskStepTick(), however, unlike - * vTaskStepTick(), xTaskCatchUpTicks() may move the tick count forward past a - * time at which a task should be removed from the blocked state. That means - * tasks may have to be removed from the blocked state as the tick count is - * moved. - * - * @param xTicksToCatchUp The number of tick interrupts that have been missed - * due to interrupts being disabled. Its value is not computed automatically, - * so must be computed by the application writer. - * - * @return pdTRUE if moving the tick count forward resulted in a task leaving - * the blocked state and a context switch being performed. Otherwise pdFALSE. - * - * \defgroup xTaskCatchUpTicks xTaskCatchUpTicks - * \ingroup TaskCtrl - */ -BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- - * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES - *----------------------------------------------------------*/ - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY - * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS - * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * Called from the real time kernel tick (either preemptive or cooperative), - * this increments the tick count and checks if any tasks that are blocked - * for a finite period required removing from a blocked list and placing on - * a ready list. If a non-zero value is returned then a context switch is - * required because either: - * + A task was removed from a blocked list because its timeout had expired, - * or - * + Time slicing is in use and there is a task of equal priority to the - * currently running task. - */ -BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * Removes the calling task from the ready list and places it both - * on the list of tasks waiting for a particular event, and the - * list of delayed tasks. The task will be removed from both lists - * and replaced on the ready list should either the event occur (and - * there be no higher priority tasks waiting on the same event) or - * the delay period expires. - * - * The 'unordered' version replaces the event list item value with the - * xItemValue value, and inserts the list item at the end of the list. - * - * The 'ordered' version uses the existing event list item value (which is the - * owning task's priority) to insert the list item into the event list in task - * priority order. - * - * @param pxEventList The list containing tasks that are blocked waiting - * for the event to occur. - * - * @param xItemValue The item value to use for the event list item when the - * event list is not ordered by task priority. - * - * @param xTicksToWait The maximum amount of time that the task should wait - * for the event to occur. This is specified in kernel ticks, the constant - * portTICK_PERIOD_MS can be used to convert kernel ticks into a real time - * period. - */ -void vTaskPlaceOnEventList( List_t * const pxEventList, - const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, - const TickType_t xItemValue, - const TickType_t xTicksToWait ) - PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * This function performs nearly the same function as vTaskPlaceOnEventList(). - * The difference being that this function does not permit tasks to block - * indefinitely, whereas vTaskPlaceOnEventList() does. - * - */ -void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, - TickType_t xTicksToWait, - const BaseType_t xWaitIndefinitely ) - PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * Removes a task from both the specified event list and the list of blocked - * tasks, and places it on a ready queue. - * - * xTaskRemoveFromEventList()/vTaskRemoveFromUnorderedEventList() will be called - * if either an event occurs to unblock a task, or the block timeout period - * expires. - * - * xTaskRemoveFromEventList() is used when the event list is in task priority - * order. It removes the list item from the head of the event list as that will - * have the highest priority owning task of all the tasks on the event list. - * vTaskRemoveFromUnorderedEventList() is used when the event list is not - * ordered and the event list items hold something other than the owning tasks - * priority. In this case the event list item value is updated to the value - * passed in the xItemValue parameter. - * - * @return pdTRUE if the task being removed has a higher priority than the task - * making the call, otherwise pdFALSE. - */ -BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) - PRIVILEGED_FUNCTION; -void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, - const TickType_t xItemValue ) - PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY - * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS - * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * Sets the pointer to the current TCB to the TCB of the highest priority task - * that is ready to run. - */ -#if( configNUMBER_OF_CORES == 1 ) -portDONT_DISCARD void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; -#else -portDONT_DISCARD void vTaskSwitchContext( BaseType_t xCoreID ) - PRIVILEGED_FUNCTION; -#endif - -/* - * THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY - * THE EVENT BITS MODULE. - */ -TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION; - -/* - * Return the handle of the calling task. - */ -TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; - -/* - * Return the handle of the task running on specified core. - */ -TaskHandle_t xTaskGetCurrentTaskHandleCPU( BaseType_t xCoreID ) - PRIVILEGED_FUNCTION; - -/* - * Shortcut used by the queue implementation to prevent unnecessary call to - * taskYIELD(); - */ -void vTaskMissedYield( void ) PRIVILEGED_FUNCTION; - -/* - * Returns the scheduler state as taskSCHEDULER_RUNNING, - * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. - */ -BaseType_t xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION; - -/* - * Raises the priority of the mutex holder to that of the calling task should - * the mutex holder have a priority less than the calling task. - */ -BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) - PRIVILEGED_FUNCTION; - -/* - * Set the priority of a task back to its proper priority in the case that it - * inherited a higher priority while it was holding a semaphore. - */ -BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) - PRIVILEGED_FUNCTION; - -/* - * If a higher priority task attempting to obtain a mutex caused a lower - * priority task to inherit the higher priority task's priority - but the higher - * priority task then timed out without obtaining the mutex, then the lower - * priority task will disinherit the priority again - but only down as far as - * the highest priority task that is still waiting for the mutex (if there were - * more than one task waiting for the mutex). - */ -void vTaskPriorityDisinheritAfterTimeout( - TaskHandle_t const pxMutexHolder, - UBaseType_t uxHighestPriorityWaitingTask ) PRIVILEGED_FUNCTION; - -/* - * Get the uxTaskNumber assigned to the task referenced by the xTask parameter. - */ -UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/* - * Set the uxTaskNumber of the task referenced by the xTask parameter to - * uxHandle. - */ -void vTaskSetTaskNumber( TaskHandle_t xTask, - const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION; - -/* - * Only available when configUSE_TICKLESS_IDLE is set to 1. - * If tickless mode is being used, or a low power mode is implemented, then - * the tick interrupt will not execute during idle periods. When this is the - * case, the tick count value maintained by the scheduler needs to be kept up - * to date with the actual execution time by being skipped forward by a time - * equal to the idle period. - */ -void vTaskStepTick( TickType_t xTicksToJump ) PRIVILEGED_FUNCTION; - -/* - * Only available when configUSE_TICKLESS_IDLE is set to 1. - * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port - * specific sleep function to determine if it is ok to proceed with the sleep, - * and if it is ok to proceed, if it is ok to sleep indefinitely. - * - * This function is necessary because portSUPPRESS_TICKS_AND_SLEEP() is only - * called with the scheduler suspended, not from within a critical section. It - * is therefore possible for an interrupt to request a context switch between - * portSUPPRESS_TICKS_AND_SLEEP() and the low power mode actually being - * entered. eTaskConfirmSleepModeStatus() should be called from a short - * critical section between the timer being stopped and the sleep mode being - * entered to ensure it is ok to proceed into the sleep mode. - */ -eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION; - -/* - * For internal use only. Increment the mutex held count when a mutex is - * taken and return the handle of the task that has taken the mutex. - */ -TaskHandle_t pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION; - -/* - * For internal use only. Same as vTaskSetTimeOutState(), but without a - * critical section. - */ -void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) - PRIVILEGED_FUNCTION; - -/* - * For internal use only. Same as portYIELD_WITHIN_API() in single core - * FreeRTOS. For SMP this is not defined by the port. - */ -void vTaskYieldWithinAPI( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when portCRITICAL_NESTING_IN_TCB is set to 1 - * or configNUMBER_OF_CORES is greater than 1. This function can be used in the - * implementation of portENTER_CRITICAL if port wants to maintain critical - * nesting count in TCB in single core FreeRTOS. It should be used in the - * implementation of portENTER_CRITICAL if port is running a multiple core - * FreeRTOS. - */ -void vTaskEnterCritical( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when portCRITICAL_NESTING_IN_TCB is set to 1 - * or configNUMBER_OF_CORES is greater than 1. This function can be used in the - * implementation of portEXIT_CRITICAL if port wants to maintain critical - * nesting count in TCB in single core FreeRTOS. It should be used in the - * implementation of portEXIT_CRITICAL if port is running a multiple core - * FreeRTOS. - */ -void vTaskExitCritical( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when configNUMBER_OF_CORES is greater than 1. - * This function should be used in the implementation of - * portENTER_CRITICAL_FROM_ISR if port is running a multiple core FreeRTOS. - */ -UBaseType_t vTaskEnterCriticalFromISR( void ); - -/* - * This function is only intended for use when implementing a port of the - * scheduler and is only available when configNUMBER_OF_CORES is greater than 1. - * This function should be used in the implementation of - * portEXIT_CRITICAL_FROM_ISR if port is running a multiple core FreeRTOS. - */ -void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus ); - -#if( portUSING_MPU_WRAPPERS == 1 ) - -/* - * For internal use only. Get MPU settings associated with a task. - */ -xMPU_SETTINGS * xTaskGetMPUSettings( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -#endif /* portUSING_MPU_WRAPPERS */ - -/* *INDENT-OFF* */ -#ifdef __cplusplus -} -#endif -/* *INDENT-ON* */ -#endif /* INC_TASK_H */ diff --git a/formatting/goodFiles/source/core_mqtt.c b/formatting/goodFiles/source/core_mqtt.c deleted file mode 100644 index 6c200fca..00000000 --- a/formatting/goodFiles/source/core_mqtt.c +++ /dev/null @@ -1,3515 +0,0 @@ -/* - * coreMQTT v2.1.0 - * Copyright (C) 2022 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. - */ - -/** - * @file core_mqtt.c - * @brief Implements the user-facing functions in core_mqtt.h. - */ -#include -#include - -#include "core_mqtt.h" -#include "core_mqtt_state.h" - -/* Include config defaults header to get default values of configs. */ -#include "core_mqtt_config_defaults.h" - -#include "core_mqtt_default_logging.h" - -#ifndef MQTT_PRE_SEND_HOOK - -/** - * @brief Hook called before a 'send' operation is executed. - */ - #define MQTT_PRE_SEND_HOOK( pContext ) -#endif /* !MQTT_PRE_SEND_HOOK */ - -#ifndef MQTT_POST_SEND_HOOK - -/** - * @brief Hook called after the 'send' operation is complete. - */ - #define MQTT_POST_SEND_HOOK( pContext ) -#endif /* !MQTT_POST_SEND_HOOK */ - -#ifndef MQTT_PRE_STATE_UPDATE_HOOK - -/** - * @brief Hook called just before an update to the MQTT state is made. - */ - #define MQTT_PRE_STATE_UPDATE_HOOK( pContext ) -#endif /* !MQTT_PRE_STATE_UPDATE_HOOK */ - -#ifndef MQTT_POST_STATE_UPDATE_HOOK - -/** - * @brief Hook called just after an update to the MQTT state has - * been made. - */ - #define MQTT_POST_STATE_UPDATE_HOOK( pContext ) -#endif /* !MQTT_POST_STATE_UPDATE_HOOK */ - -/** - * @brief Bytes required to encode any string length in an MQTT packet header. - * Length is always encoded in two bytes according to the MQTT specification. - */ -#define CORE_MQTT_SERIALIZED_LENGTH_FIELD_BYTES ( 2U ) - -/** - * @brief Number of vectors required to encode one topic filter in a subscribe - * request. Three vectors are required as there are three fields in the - * subscribe request namely: - * 1. Topic filter length; 2. Topic filter; and 3. QoS in this order. - */ -#define CORE_MQTT_SUBSCRIBE_PER_TOPIC_VECTOR_LENGTH ( 3U ) - -/** - * @brief Number of vectors required to encode one topic filter in an - * unsubscribe request. Two vectors are required as there are two fields in the - * unsubscribe request namely: - * 1. Topic filter length; and 2. Topic filter in this order. - */ -#define CORE_MQTT_UNSUBSCRIBE_PER_TOPIC_VECTOR_LENGTH ( 2U ) - -/*-----------------------------------------------------------*/ - -/** - * @brief Sends provided buffer to network using transport send. - * - * @brief param[in] pContext Initialized MQTT context. - * @brief param[in] pBufferToSend Buffer to be sent to network. - * @brief param[in] bytesToSend Number of bytes to be sent. - * - * @note This operation may call the transport send function - * repeatedly to send bytes over the network until either: - * 1. The requested number of bytes @a bytesToSend have been sent. - * OR - * 2. MQTT_SEND_TIMEOUT_MS milliseconds have gone by since entering this - * function. - * OR - * 3. There is an error in sending data over the network. - * - * @return Total number of bytes sent, or negative value on network error. - */ -static int32_t sendBuffer( MQTTContext_t * pContext, - const uint8_t * pBufferToSend, - size_t bytesToSend ); - -/** - * @brief Sends MQTT connect without copying the users data into any buffer. - * - * @brief param[in] pContext Initialized MQTT context. - * @brief param[in] pConnectInfo MQTT CONNECT packet information. - * @brief param[in] pWillInfo Last Will and Testament. Pass NULL if Last Will - * and Testament is not used. - * @brief param[in] remainingLength the length of the connect packet. - * - * @note This operation may call the transport send function - * repeatedly to send bytes over the network until either: - * 1. The requested number of bytes @a remainingLength have been sent. - * OR - * 2. MQTT_SEND_TIMEOUT_MS milliseconds have gone by since entering this - * function. - * OR - * 3. There is an error in sending data over the network. - * - * @return #MQTTSendFailed or #MQTTSuccess. - */ -static MQTTStatus_t sendConnectWithoutCopy( - MQTTContext_t * pContext, - const MQTTConnectInfo_t * pConnectInfo, - const MQTTPublishInfo_t * pWillInfo, - size_t remainingLength ); - -/** - * @brief Sends the vector array passed through the parameters over the network. - * - * @note The preference is given to 'writev' function if it is present in the - * transport interface. Otherwise, a send call is made repeatedly to achieve the - * result. - * - * @param[in] pContext Initialized MQTT context. - * @param[in] pIoVec The vector array to be sent. - * @param[in] ioVecCount The number of elements in the array. - * - * @note This operation may call the transport send or writev functions - * repeatedly to send bytes over the network until either: - * 1. The requested number of bytes have been sent. - * OR - * 2. MQTT_SEND_TIMEOUT_MS milliseconds have gone by since entering this - * function. - * OR - * 3. There is an error in sending data over the network. - * - * @return The total number of bytes sent or the error code as received from the - * transport interface. - */ -static int32_t sendMessageVector( MQTTContext_t * pContext, - TransportOutVector_t * pIoVec, - size_t ioVecCount ); - -/** - * @brief Add a string and its length after serializing it in a manner outlined - * by the MQTT specification. - * - * @param[in] serializedLength Array of two bytes to which the vector will - * point. The array must remain in scope until the message has been sent. - * @param[in] string The string to be serialized. - * @param[in] length The length of the string to be serialized. - * @param[in] iterator The iterator pointing to the first element in the - * transport interface IO array. - * @param[out] updatedLength This parameter will be added to with the number of - * bytes added to the vector. - * - * @return The number of vectors added. - */ -static size_t addEncodedStringToVector( - uint8_t serializedLength[ CORE_MQTT_SERIALIZED_LENGTH_FIELD_BYTES ], - const char * const string, - uint16_t length, - TransportOutVector_t * iterator, - size_t * updatedLength ); - -/** - * @brief Send MQTT SUBSCRIBE message without copying the user data into a - * buffer and directly sending it. - * - * @param[in] pContext Initialized MQTT context. - * @param[in] pSubscriptionList List of MQTT subscription info. - * @param[in] subscriptionCount The count of elements in the list. - * @param[in] packetId The packet ID of the subscribe packet - * @param[in] remainingLength The remaining length of the subscribe packet. - * - * @return #MQTTSuccess or #MQTTSendFailed. - */ -static MQTTStatus_t sendSubscribeWithoutCopy( - MQTTContext_t * pContext, - const MQTTSubscribeInfo_t * pSubscriptionList, - size_t subscriptionCount, - uint16_t packetId, - size_t remainingLength ); - -/** - * @brief Send MQTT UNSUBSCRIBE message without copying the user data into a - * buffer and directly sending it. - * - * @param[in] pContext Initialized MQTT context. - * @param[in] pSubscriptionList MQTT subscription info. - * @param[in] subscriptionCount The count of elements in the list. - * @param[in] packetId The packet ID of the unsubscribe packet. - * @param[in] remainingLength The remaining length of the unsubscribe packet. - * - * @return #MQTTSuccess or #MQTTSendFailed. - */ -static MQTTStatus_t sendUnsubscribeWithoutCopy( - MQTTContext_t * pContext, - const MQTTSubscribeInfo_t * pSubscriptionList, - size_t subscriptionCount, - uint16_t packetId, - size_t remainingLength ); - -/** - * @brief Calculate the interval between two millisecond timestamps, including - * when the later value has overflowed. - * - * @note In C, the operands are promoted to signed integers in subtraction. - * Using this function avoids the need to cast the result of subtractions back - * to uint32_t. - * - * @param[in] later The later time stamp, in milliseconds. - * @param[in] start The earlier time stamp, in milliseconds. - * - * @return later - start. - */ -static uint32_t calculateElapsedTime( uint32_t later, uint32_t start ); - -/** - * @brief Convert a byte indicating a publish ack type to an #MQTTPubAckType_t. - * - * @param[in] packetType First byte of fixed header. - * - * @return Type of ack. - */ -static MQTTPubAckType_t getAckFromPacketType( uint8_t packetType ); - -/** - * @brief Receive bytes into the network buffer. - * - * @param[in] pContext Initialized MQTT Context. - * @param[in] bytesToRecv Number of bytes to receive. - * - * @note This operation calls the transport receive function - * repeatedly to read bytes from the network until either: - * 1. The requested number of bytes @a bytesToRecv are read. - * OR - * 2. No data is received from the network for MQTT_RECV_POLLING_TIMEOUT_MS - * duration. - * - * OR - * 3. There is an error in reading from the network. - * - * - * @return Number of bytes received, or negative number on network error. - */ -static int32_t recvExact( const MQTTContext_t * pContext, size_t bytesToRecv ); - -/** - * @brief Discard a packet from the transport interface. - * - * @param[in] pContext MQTT Connection context. - * @param[in] remainingLength Remaining length of the packet to dump. - * @param[in] timeoutMs Time remaining to discard the packet. - * - * @return #MQTTRecvFailed or #MQTTNoDataAvailable. - */ -static MQTTStatus_t discardPacket( const MQTTContext_t * pContext, - size_t remainingLength, - uint32_t timeoutMs ); - -/** - * @brief Discard a packet from the MQTT buffer and the transport interface. - * - * @param[in] pContext MQTT Connection context. - * @param[in] pPacketInfo Information struct of the packet to be discarded. - * - * @return #MQTTRecvFailed or #MQTTNoDataAvailable. - */ -static MQTTStatus_t discardStoredPacket( MQTTContext_t * pContext, - const MQTTPacketInfo_t * pPacketInfo ); - -/** - * @brief Receive a packet from the transport interface. - * - * @param[in] pContext MQTT Connection context. - * @param[in] incomingPacket packet struct with remaining length. - * @param[in] remainingTimeMs Time remaining to receive the packet. - * - * @return #MQTTSuccess or #MQTTRecvFailed. - */ -static MQTTStatus_t receivePacket( const MQTTContext_t * pContext, - MQTTPacketInfo_t incomingPacket, - uint32_t remainingTimeMs ); - -/** - * @brief Get the correct ack type to send. - * - * @param[in] state Current state of publish. - * - * @return Packet Type byte of PUBACK, PUBREC, PUBREL, or PUBCOMP if one of - * those should be sent, else 0. - */ -static uint8_t getAckTypeToSend( MQTTPublishState_t state ); - -/** - * @brief Send acks for received QoS 1/2 publishes. - * - * @param[in] pContext MQTT Connection context. - * @param[in] packetId packet ID of original PUBLISH. - * @param[in] publishState Current publish state in record. - * - * @return #MQTTSuccess, #MQTTIllegalState or #MQTTSendFailed. - */ -static MQTTStatus_t sendPublishAcks( MQTTContext_t * pContext, - uint16_t packetId, - MQTTPublishState_t publishState ); - -/** - * @brief Send a keep alive PINGREQ if the keep alive interval has elapsed. - * - * @param[in] pContext Initialized MQTT Context. - * - * @return #MQTTKeepAliveTimeout if a PINGRESP is not received in time, - * #MQTTSendFailed if the PINGREQ cannot be sent, or #MQTTSuccess. - */ -static MQTTStatus_t handleKeepAlive( MQTTContext_t * pContext ); - -/** - * @brief Handle received MQTT PUBLISH packet. - * - * @param[in] pContext MQTT Connection context. - * @param[in] pIncomingPacket Incoming packet. - * - * @return MQTTSuccess, MQTTIllegalState or deserialization error. - */ -static MQTTStatus_t handleIncomingPublish( MQTTContext_t * pContext, - MQTTPacketInfo_t * pIncomingPacket ); - -/** - * @brief Handle received MQTT publish acks. - * - * @param[in] pContext MQTT Connection context. - * @param[in] pIncomingPacket Incoming packet. - * - * @return MQTTSuccess, MQTTIllegalState, or deserialization error. - */ -static MQTTStatus_t handlePublishAcks( MQTTContext_t * pContext, - MQTTPacketInfo_t * pIncomingPacket ); - -/** - * @brief Handle received MQTT ack. - * - * @param[in] pContext MQTT Connection context. - * @param[in] pIncomingPacket Incoming packet. - * @param[in] manageKeepAlive Flag indicating if PINGRESPs should not be given - * to the application - * - * @return MQTTSuccess, MQTTIllegalState, or deserialization error. - */ -static MQTTStatus_t handleIncomingAck( MQTTContext_t * pContext, - MQTTPacketInfo_t * pIncomingPacket, - bool manageKeepAlive ); - -/** - * @brief Run a single iteration of the receive loop. - * - * @param[in] pContext MQTT Connection context. - * @param[in] manageKeepAlive Flag indicating if keep alive should be handled. - * - * @return #MQTTRecvFailed if a network error occurs during reception; - * #MQTTSendFailed if a network error occurs while sending an ACK or PINGREQ; - * #MQTTBadResponse if an invalid packet is received; - * #MQTTKeepAliveTimeout if the server has not sent a PINGRESP before - * #MQTT_PINGRESP_TIMEOUT_MS milliseconds; - * #MQTTIllegalState if an incoming QoS 1/2 publish or ack causes an - * invalid transition for the internal state machine; - * #MQTTSuccess on success. - */ -static MQTTStatus_t receiveSingleIteration( MQTTContext_t * pContext, - bool manageKeepAlive ); - -/** - * @brief Validates parameters of #MQTT_Subscribe or #MQTT_Unsubscribe. - * - * @param[in] pContext Initialized MQTT context. - * @param[in] pSubscriptionList List of MQTT subscription info. - * @param[in] subscriptionCount The number of elements in pSubscriptionList. - * @param[in] packetId Packet identifier. - * - * @return #MQTTBadParameter if invalid parameters are passed; - * #MQTTSuccess otherwise. - */ -static MQTTStatus_t validateSubscribeUnsubscribeParams( - const MQTTContext_t * pContext, - const MQTTSubscribeInfo_t * pSubscriptionList, - size_t subscriptionCount, - uint16_t packetId ); - -/** - * @brief Receives a CONNACK MQTT packet. - * - * @param[in] pContext Initialized MQTT context. - * @param[in] timeoutMs Timeout for waiting for CONNACK packet. - * @param[in] cleanSession Clean session flag set by application. - * @param[out] pIncomingPacket List of MQTT subscription info. - * @param[out] pSessionPresent Whether a previous session was present. - * Only relevant if not establishing a clean session. - * - * @return #MQTTBadResponse if a bad response is received; - * #MQTTNoDataAvailable if no data available for transport recv; - * ##MQTTRecvFailed if transport recv failed; - * #MQTTSuccess otherwise. - */ -static MQTTStatus_t receiveConnack( const MQTTContext_t * pContext, - uint32_t timeoutMs, - bool cleanSession, - MQTTPacketInfo_t * pIncomingPacket, - bool * pSessionPresent ); - -/** - * @brief Resends pending acks for a re-established MQTT session, or - * clears existing state records for a clean session. - * - * @param[in] pContext Initialized MQTT context. - * @param[in] sessionPresent Session present flag received from the MQTT broker. - * - * @return #MQTTSendFailed if transport send during resend failed; - * #MQTTSuccess otherwise. - */ -static MQTTStatus_t handleSessionResumption( MQTTContext_t * pContext, - bool sessionPresent ); - -/** - * @brief Send the publish packet without copying the topic string and payload - * in the buffer. - * - * @brief param[in] pContext Initialized MQTT context. - * @brief param[in] pPublishInfo MQTT PUBLISH packet parameters. - * @brief param[in] pMqttHeader the serialized MQTT header with the header byte; - * the encoded length of the packet; and the encoded length of the topic string. - * @brief param[in] headerSize Size of the serialized PUBLISH header. - * @brief param[in] packetId Packet Id of the publish packet. - * - * @return #MQTTSendFailed if transport send during resend failed; - * #MQTTSuccess otherwise. - */ -static MQTTStatus_t sendPublishWithoutCopy( - MQTTContext_t * pContext, - const MQTTPublishInfo_t * pPublishInfo, - const uint8_t * pMqttHeader, - size_t headerSize, - uint16_t packetId ); - -/** - * @brief Function to validate #MQTT_Publish parameters. - * - * @brief param[in] pContext Initialized MQTT context. - * @brief param[in] pPublishInfo MQTT PUBLISH packet parameters. - * @brief param[in] packetId Packet Id for the MQTT PUBLISH packet. - * - * @return #MQTTBadParameter if invalid parameters are passed; - * #MQTTSuccess otherwise. - */ -static MQTTStatus_t validatePublishParams( - const MQTTContext_t * pContext, - const MQTTPublishInfo_t * pPublishInfo, - uint16_t packetId ); - -/** - * @brief Performs matching for special cases when a topic filter ends - * with a wildcard character. - * - * When the topic name has been consumed but there are remaining characters to - * to match in topic filter, this function handles the following 2 cases: - * - When the topic filter ends with "/+" or "/#" characters, but the topic - * name only ends with '/'. - * - When the topic filter ends with "/#" characters, but the topic name - * ends at the parent level. - * - * @note This function ASSUMES that the topic name been consumed in linear - * matching with the topic filer, but the topic filter has remaining characters - * to be matched. - * - * @param[in] pTopicFilter The topic filter containing the wildcard. - * @param[in] topicFilterLength Length of the topic filter being examined. - * @param[in] filterIndex Index of the topic filter being examined. - * - * @return Returns whether the topic filter and the topic name match. - */ -static bool matchEndWildcardsSpecialCases( const char * pTopicFilter, - uint16_t topicFilterLength, - uint16_t filterIndex ); - -/** - * @brief Attempt to match topic name with a topic filter starting with a - * wildcard. - * - * If the topic filter starts with a '+' (single-level) wildcard, the function - * advances the @a pNameIndex by a level in the topic name. - * If the topic filter starts with a '#' (multi-level) wildcard, the function - * concludes that both the topic name and topic filter match. - * - * @param[in] pTopicName The topic name to match. - * @param[in] topicNameLength Length of the topic name. - * @param[in] pTopicFilter The topic filter to match. - * @param[in] topicFilterLength Length of the topic filter. - * @param[in,out] pNameIndex Current index in the topic name being examined. It - * is advanced by one level for `+` wildcards. - * @param[in, out] pFilterIndex Current index in the topic filter being - * examined. It is advanced to position of '/' level separator for '+' wildcard. - * @param[out] pMatch Whether the topic filter and topic name match. - * - * @return `true` if the caller of this function should exit; `false` if the - * caller should continue parsing the topics. - */ -static bool matchWildcards( const char * pTopicName, - uint16_t topicNameLength, - const char * pTopicFilter, - uint16_t topicFilterLength, - uint16_t * pNameIndex, - uint16_t * pFilterIndex, - bool * pMatch ); - -/** - * @brief Match a topic name and topic filter allowing the use of wildcards. - * - * @param[in] pTopicName The topic name to check. - * @param[in] topicNameLength Length of the topic name. - * @param[in] pTopicFilter The topic filter to check. - * @param[in] topicFilterLength Length of topic filter. - * - * @return `true` if the topic name and topic filter match; `false` otherwise. - */ -static bool matchTopicFilter( const char * pTopicName, - uint16_t topicNameLength, - const char * pTopicFilter, - uint16_t topicFilterLength ); - -/*-----------------------------------------------------------*/ - -static bool matchEndWildcardsSpecialCases( const char * pTopicFilter, - uint16_t topicFilterLength, - uint16_t filterIndex ) -{ - bool matchFound = false; - - assert( pTopicFilter != NULL ); - assert( topicFilterLength != 0U ); - - /* Check if the topic filter has 2 remaining characters and it ends in - * "/#". This check handles the case to match filter "sport/#" with topic - * "sport". The reason is that the '#' wildcard represents the parent and - * any number of child levels in the topic name.*/ - if( ( topicFilterLength >= 3U ) && - ( filterIndex == ( topicFilterLength - 3U ) ) && - ( pTopicFilter[ filterIndex + 1U ] == '/' ) && - ( pTopicFilter[ filterIndex + 2U ] == '#' ) ) - - { - matchFound = true; - } - - /* Check if the next character is "#" or "+" and the topic filter ends in - * "/#" or "/+". This check handles the cases to match: - * - * - Topic filter "sport/+" with topic "sport/". - * - Topic filter "sport/#" with topic "sport/". - */ - if( ( filterIndex == ( topicFilterLength - 2U ) ) && - ( pTopicFilter[ filterIndex ] == '/' ) ) - { - /* Check that the last character is a wildcard. */ - matchFound = ( pTopicFilter[ filterIndex + 1U ] == '+' ) || - ( pTopicFilter[ filterIndex + 1U ] == '#' ); - } - - return matchFound; -} - -/*-----------------------------------------------------------*/ - -static bool matchWildcards( const char * pTopicName, - uint16_t topicNameLength, - const char * pTopicFilter, - uint16_t topicFilterLength, - uint16_t * pNameIndex, - uint16_t * pFilterIndex, - bool * pMatch ) -{ - bool shouldStopMatching = false; - bool locationIsValidForWildcard; - - assert( pTopicName != NULL ); - assert( topicNameLength != 0U ); - assert( pTopicFilter != NULL ); - assert( topicFilterLength != 0U ); - assert( pNameIndex != NULL ); - assert( pFilterIndex != NULL ); - assert( pMatch != NULL ); - - /* Wild card in a topic filter is only valid either at the starting position - * or when it is preceded by a '/'.*/ - locationIsValidForWildcard = ( *pFilterIndex == 0u ) || - ( pTopicFilter[ *pFilterIndex - 1U ] == '/' ); - - if( ( pTopicFilter[ *pFilterIndex ] == '+' ) && - ( locationIsValidForWildcard == true ) ) - { - bool nextLevelExistsInTopicName = false; - bool nextLevelExistsinTopicFilter = false; - - /* Move topic name index to the end of the current level. The end of the - * current level is identified by the last character before the next - * level separator '/'. */ - while( *pNameIndex < topicNameLength ) - { - /* Exit the loop if we hit the level separator. */ - if( pTopicName[ *pNameIndex ] == '/' ) - { - nextLevelExistsInTopicName = true; - break; - } - - ( *pNameIndex )++; - } - - /* Determine if the topic filter contains a child level after the - * current level represented by the '+' wildcard. */ - if( ( *pFilterIndex < ( topicFilterLength - 1U ) ) && - ( pTopicFilter[ *pFilterIndex + 1U ] == '/' ) ) - { - nextLevelExistsinTopicFilter = true; - } - - /* If the topic name contains a child level but the topic filter ends at - * the current level, then there does not exist a match. */ - if( ( nextLevelExistsInTopicName == true ) && - ( nextLevelExistsinTopicFilter == false ) ) - { - *pMatch = false; - shouldStopMatching = true; - } - - /* If the topic name and topic filter have child levels, then advance - * the filter index to the level separator in the topic filter, so that - * match can be performed in the next level. Note: The name index - * already points to the level separator in the topic name. */ - else if( nextLevelExistsInTopicName == true ) - { - ( *pFilterIndex )++; - } - else - { - /* If we have reached here, the the loop terminated on the - * ( *pNameIndex < topicNameLength) condition, which means that have - * reached past the end of the topic name, and thus, we decrement - * the index to the last character in the topic name.*/ - ( *pNameIndex )--; - } - } - - /* '#' matches everything remaining in the topic name. It must be the - * last character in a topic filter. */ - else if( ( pTopicFilter[ *pFilterIndex ] == '#' ) && - ( *pFilterIndex == ( topicFilterLength - 1U ) ) && - ( locationIsValidForWildcard == true ) ) - { - /* Subsequent characters don't need to be checked for the - * multi-level wildcard. */ - *pMatch = true; - shouldStopMatching = true; - } - else - { - /* Any character mismatch other than '+' or '#' means the topic - * name does not match the topic filter. */ - *pMatch = false; - shouldStopMatching = true; - } - - return shouldStopMatching; -} - -/*-----------------------------------------------------------*/ - -static bool matchTopicFilter( const char * pTopicName, - uint16_t topicNameLength, - const char * pTopicFilter, - uint16_t topicFilterLength ) -{ - bool matchFound = false, shouldStopMatching = false; - uint16_t nameIndex = 0, filterIndex = 0; - - assert( pTopicName != NULL ); - assert( topicNameLength != 0 ); - assert( pTopicFilter != NULL ); - assert( topicFilterLength != 0 ); - - while( ( nameIndex < topicNameLength ) && - ( filterIndex < topicFilterLength ) ) - { - /* Check if the character in the topic name matches the corresponding - * character in the topic filter string. */ - if( pTopicName[ nameIndex ] == pTopicFilter[ filterIndex ] ) - { - /* If the topic name has been consumed but the topic filter has not - * been consumed, match for special cases when the topic filter ends - * with wildcard character. */ - if( nameIndex == ( topicNameLength - 1U ) ) - { - matchFound = matchEndWildcardsSpecialCases( pTopicFilter, - topicFilterLength, - filterIndex ); - } - } - else - { - /* Check for matching wildcards. */ - shouldStopMatching = matchWildcards( pTopicName, - topicNameLength, - pTopicFilter, - topicFilterLength, - &nameIndex, - &filterIndex, - &matchFound ); - } - - if( ( matchFound == true ) || ( shouldStopMatching == true ) ) - { - break; - } - - /* Increment indexes. */ - nameIndex++; - filterIndex++; - } - - if( matchFound == false ) - { - /* If the end of both strings has been reached, they match. This - * represents the case when the topic filter contains the '+' wildcard - * at a non-starting position. For example, when matching either of - * "sport/+/player" OR "sport/hockey/+" topic filters with - * "sport/hockey/player" topic name. */ - matchFound = ( nameIndex == topicNameLength ) && - ( filterIndex == topicFilterLength ); - } - - return matchFound; -} - -/*-----------------------------------------------------------*/ - -static int32_t sendMessageVector( MQTTContext_t * pContext, - TransportOutVector_t * pIoVec, - size_t ioVecCount ) -{ - int32_t sendResult; - uint32_t startTime; - TransportOutVector_t * pIoVectIterator; - size_t vectorsToBeSent = ioVecCount; - size_t bytesToSend = 0U; - int32_t bytesSentOrError = 0; - - assert( pContext != NULL ); - assert( pIoVec != NULL ); - assert( pContext->getTime != NULL ); - /* Send must always be defined */ - assert( pContext->transportInterface.send != NULL ); - - /* Count the total number of bytes to be sent as outlined in the vector. */ - for( pIoVectIterator = pIoVec; - pIoVectIterator <= &( pIoVec[ ioVecCount - 1U ] ); - pIoVectIterator++ ) - { - bytesToSend += pIoVectIterator->iov_len; - } - - /* Reset the iterator to point to the first entry in the array. */ - pIoVectIterator = pIoVec; - - /* Note the start time. */ - startTime = pContext->getTime(); - - while( ( bytesSentOrError < ( int32_t ) bytesToSend ) && - ( bytesSentOrError >= 0 ) ) - { - if( pContext->transportInterface.writev != NULL ) - { - sendResult = pContext->transportInterface.writev( - pContext->transportInterface.pNetworkContext, - pIoVectIterator, - vectorsToBeSent ); - } - else - { - sendResult = pContext->transportInterface.send( - pContext->transportInterface.pNetworkContext, - pIoVectIterator->iov_base, - pIoVectIterator->iov_len ); - } - - if( sendResult > 0 ) - { - /* It is a bug in the application's transport send implementation if - * more bytes than expected are sent. */ - assert( sendResult <= - ( ( int32_t ) bytesToSend - bytesSentOrError ) ); - - bytesSentOrError += sendResult; - - /* Set last transmission time. */ - pContext->lastPacketTxTime = pContext->getTime(); - - LogDebug( - ( "sendMessageVector: Bytes Sent=%ld, Bytes Remaining=%lu", - ( long int ) sendResult, - ( unsigned long ) ( bytesToSend - - ( size_t ) bytesSentOrError ) ) ); - } - else if( sendResult < 0 ) - { - bytesSentOrError = sendResult; - LogError( ( - "sendMessageVector: Unable to send packet: Network Error." ) ); - } - else - { - /* MISRA Empty body */ - } - - /* Check for timeout. */ - if( calculateElapsedTime( pContext->getTime(), startTime ) > - MQTT_SEND_TIMEOUT_MS ) - { - LogError( - ( "sendMessageVector: Unable to send packet: Timed out." ) ); - break; - } - - /* Update the send pointer to the correct vector and offset. */ - while( ( pIoVectIterator <= &( pIoVec[ ioVecCount - 1U ] ) ) && - ( sendResult >= ( int32_t ) pIoVectIterator->iov_len ) ) - { - sendResult -= ( int32_t ) pIoVectIterator->iov_len; - pIoVectIterator++; - /* Update the number of vector which are yet to be sent. */ - vectorsToBeSent--; - } - - /* Some of the bytes from this vector were sent as well, update the - * length and the pointer to data in this vector. */ - if( ( sendResult > 0 ) && - ( pIoVectIterator <= &( pIoVec[ ioVecCount - 1U ] ) ) ) - { - pIoVectIterator->iov_base = ( const void * ) &( ( - ( const uint8_t * ) pIoVectIterator->iov_base )[ sendResult ] ); - pIoVectIterator->iov_len -= ( size_t ) sendResult; - } - } - - return bytesSentOrError; -} - -static int32_t sendBuffer( MQTTContext_t * pContext, - const uint8_t * pBufferToSend, - size_t bytesToSend ) -{ - int32_t sendResult; - uint32_t timeoutMs; - int32_t bytesSentOrError = 0; - const uint8_t * pIndex = pBufferToSend; - - assert( pContext != NULL ); - assert( pContext->getTime != NULL ); - assert( pContext->transportInterface.send != NULL ); - assert( pIndex != NULL ); - - /* Set the timeout. */ - timeoutMs = pContext->getTime() + MQTT_SEND_TIMEOUT_MS; - - while( ( bytesSentOrError < ( int32_t ) bytesToSend ) && - ( bytesSentOrError >= 0 ) ) - { - sendResult = pContext->transportInterface - .send( pContext->transportInterface.pNetworkContext, - pIndex, - bytesToSend - ( size_t ) bytesSentOrError ); - - if( sendResult > 0 ) - { - /* It is a bug in the application's transport send implementation if - * more bytes than expected are sent. */ - assert( sendResult <= - ( ( int32_t ) bytesToSend - bytesSentOrError ) ); - - bytesSentOrError += sendResult; - pIndex = &pIndex[ sendResult ]; - - /* Set last transmission time. */ - pContext->lastPacketTxTime = pContext->getTime(); - - LogDebug( ( "sendBuffer: Bytes Sent=%ld, Bytes Remaining=%lu", - ( long int ) sendResult, - ( unsigned long ) ( bytesToSend - - ( size_t ) bytesSentOrError ) ) ); - } - else if( sendResult < 0 ) - { - bytesSentOrError = sendResult; - LogError( ( "sendBuffer: Unable to send packet: Network Error." ) ); - } - else - { - /* MISRA Empty body */ - } - - /* Check for timeout. */ - if( pContext->getTime() >= timeoutMs ) - { - LogError( ( "sendBuffer: Unable to send packet: Timed out." ) ); - break; - } - } - - return bytesSentOrError; -} - -/*-----------------------------------------------------------*/ - -static uint32_t calculateElapsedTime( uint32_t later, uint32_t start ) -{ - return later - start; -} - -/*-----------------------------------------------------------*/ - -static MQTTPubAckType_t getAckFromPacketType( uint8_t packetType ) -{ - MQTTPubAckType_t ackType = MQTTPuback; - - switch( packetType ) - { - case MQTT_PACKET_TYPE_PUBACK: - ackType = MQTTPuback; - break; - - case MQTT_PACKET_TYPE_PUBREC: - ackType = MQTTPubrec; - break; - - case MQTT_PACKET_TYPE_PUBREL: - ackType = MQTTPubrel; - break; - - case MQTT_PACKET_TYPE_PUBCOMP: - default: - - /* This function is only called after checking the type is one of - * the above four values, so packet type must be PUBCOMP here. */ - assert( packetType == MQTT_PACKET_TYPE_PUBCOMP ); - ackType = MQTTPubcomp; - break; - } - - return ackType; -} - -/*-----------------------------------------------------------*/ - -static int32_t recvExact( const MQTTContext_t * pContext, size_t bytesToRecv ) -{ - uint8_t * pIndex = NULL; - size_t bytesRemaining = bytesToRecv; - int32_t totalBytesRecvd = 0, bytesRecvd; - uint32_t lastDataRecvTimeMs = 0U, timeSinceLastRecvMs = 0U; - TransportRecv_t recvFunc = NULL; - MQTTGetCurrentTimeFunc_t getTimeStampMs = NULL; - bool receiveError = false; - - assert( pContext != NULL ); - assert( bytesToRecv <= pContext->networkBuffer.size ); - assert( pContext->getTime != NULL ); - assert( pContext->transportInterface.recv != NULL ); - assert( pContext->networkBuffer.pBuffer != NULL ); - - pIndex = pContext->networkBuffer.pBuffer; - recvFunc = pContext->transportInterface.recv; - getTimeStampMs = pContext->getTime; - - /* Part of the MQTT packet has been read before calling this function. */ - lastDataRecvTimeMs = getTimeStampMs(); - - while( ( bytesRemaining > 0U ) && ( receiveError == false ) ) - { - bytesRecvd = recvFunc( pContext->transportInterface.pNetworkContext, - pIndex, - bytesRemaining ); - - if( bytesRecvd < 0 ) - { - LogError( ( "Network error while receiving packet: ReturnCode=%ld.", - ( long int ) bytesRecvd ) ); - totalBytesRecvd = bytesRecvd; - receiveError = true; - } - else if( bytesRecvd > 0 ) - { - /* Reset the starting time as we have received some data from the - * network. */ - lastDataRecvTimeMs = getTimeStampMs(); - - /* It is a bug in the application's transport receive implementation - * if more bytes than expected are received. To avoid a possible - * overflow in converting bytesRemaining from unsigned to signed, - * this assert must exist after the check for bytesRecvd being - * negative. */ - assert( ( size_t ) bytesRecvd <= bytesRemaining ); - - bytesRemaining -= ( size_t ) bytesRecvd; - totalBytesRecvd += ( int32_t ) bytesRecvd; - /* Increment the index. */ - pIndex = &pIndex[ bytesRecvd ]; - LogDebug( ( "BytesReceived=%ld, BytesRemaining=%lu, " - "TotalBytesReceived=%ld.", - ( long int ) bytesRecvd, - ( unsigned long ) bytesRemaining, - ( long int ) totalBytesRecvd ) ); - } - else - { - /* No bytes were read from the network. */ - timeSinceLastRecvMs = calculateElapsedTime( getTimeStampMs(), - lastDataRecvTimeMs ); - - /* Check for timeout if we have been waiting to receive any byte on - * the network. */ - if( timeSinceLastRecvMs >= MQTT_RECV_POLLING_TIMEOUT_MS ) - { - LogError( ( "Unable to receive packet: Timed out in transport " - "recv." ) ); - receiveError = true; - } - } - } - - return totalBytesRecvd; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t discardPacket( const MQTTContext_t * pContext, - size_t remainingLength, - uint32_t timeoutMs ) -{ - MQTTStatus_t status = MQTTRecvFailed; - int32_t bytesReceived = 0; - size_t bytesToReceive = 0U; - uint32_t totalBytesReceived = 0U; - uint32_t entryTimeMs = 0U; - uint32_t elapsedTimeMs = 0U; - MQTTGetCurrentTimeFunc_t getTimeStampMs = NULL; - bool receiveError = false; - - assert( pContext != NULL ); - assert( pContext->getTime != NULL ); - - bytesToReceive = pContext->networkBuffer.size; - getTimeStampMs = pContext->getTime; - - entryTimeMs = getTimeStampMs(); - - while( ( totalBytesReceived < remainingLength ) && - ( receiveError == false ) ) - { - if( ( remainingLength - totalBytesReceived ) < bytesToReceive ) - { - bytesToReceive = remainingLength - totalBytesReceived; - } - - bytesReceived = recvExact( pContext, bytesToReceive ); - - if( bytesReceived != ( int32_t ) bytesToReceive ) - { - LogError( ( "Receive error while discarding packet." - "ReceivedBytes=%ld, ExpectedBytes=%lu.", - ( long int ) bytesReceived, - ( unsigned long ) bytesToReceive ) ); - receiveError = true; - } - else - { - totalBytesReceived += ( uint32_t ) bytesReceived; - - elapsedTimeMs = calculateElapsedTime( getTimeStampMs(), - entryTimeMs ); - - /* Check for timeout. */ - if( elapsedTimeMs >= timeoutMs ) - { - LogError( ( "Time expired while discarding packet." ) ); - receiveError = true; - } - } - } - - if( totalBytesReceived == remainingLength ) - { - LogError( ( "Dumped packet. DumpedBytes=%lu.", - ( unsigned long ) totalBytesReceived ) ); - /* Packet dumped, so no data is available. */ - status = MQTTNoDataAvailable; - } - - return status; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t discardStoredPacket( MQTTContext_t * pContext, - const MQTTPacketInfo_t * pPacketInfo ) -{ - MQTTStatus_t status = MQTTRecvFailed; - int32_t bytesReceived = 0; - size_t bytesToReceive = 0U; - uint32_t totalBytesReceived = 0U; - bool receiveError = false; - size_t mqttPacketSize = 0; - size_t remainingLength; - - assert( pContext != NULL ); - assert( pPacketInfo != NULL ); - - mqttPacketSize = pPacketInfo->remainingLength + pPacketInfo->headerLength; - - /* Assert that the packet being discarded is bigger than the - * receive buffer. */ - assert( mqttPacketSize > pContext->networkBuffer.size ); - - /* Discard these many bytes at a time. */ - bytesToReceive = pContext->networkBuffer.size; - - /* Number of bytes depicted by 'index' have already been received. */ - remainingLength = mqttPacketSize - pContext->index; - - while( ( totalBytesReceived < remainingLength ) && - ( receiveError == false ) ) - { - if( ( remainingLength - totalBytesReceived ) < bytesToReceive ) - { - bytesToReceive = remainingLength - totalBytesReceived; - } - - bytesReceived = recvExact( pContext, bytesToReceive ); - - if( bytesReceived != ( int32_t ) bytesToReceive ) - { - LogError( ( "Receive error while discarding packet." - "ReceivedBytes=%ld, ExpectedBytes=%lu.", - ( long int ) bytesReceived, - ( unsigned long ) bytesToReceive ) ); - receiveError = true; - } - else - { - totalBytesReceived += ( uint32_t ) bytesReceived; - } - } - - if( totalBytesReceived == remainingLength ) - { - LogError( ( "Dumped packet. DumpedBytes=%lu.", - ( unsigned long ) totalBytesReceived ) ); - /* Packet dumped, so no data is available. */ - status = MQTTNoDataAvailable; - } - - /* Clear the buffer */ - ( void ) memset( pContext->networkBuffer.pBuffer, - 0, - pContext->networkBuffer.size ); - - /* Reset the index. */ - pContext->index = 0; - - return status; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t receivePacket( const MQTTContext_t * pContext, - MQTTPacketInfo_t incomingPacket, - uint32_t remainingTimeMs ) -{ - MQTTStatus_t status = MQTTSuccess; - int32_t bytesReceived = 0; - size_t bytesToReceive = 0U; - - assert( pContext != NULL ); - assert( pContext->networkBuffer.pBuffer != NULL ); - - if( incomingPacket.remainingLength > pContext->networkBuffer.size ) - { - LogError( ( "Incoming packet will be dumped: " - "Packet length exceeds network buffer size." - "PacketSize=%lu, NetworkBufferSize=%lu.", - ( unsigned long ) incomingPacket.remainingLength, - ( unsigned long ) pContext->networkBuffer.size ) ); - status = discardPacket( pContext, - incomingPacket.remainingLength, - remainingTimeMs ); - } - else - { - bytesToReceive = incomingPacket.remainingLength; - bytesReceived = recvExact( pContext, bytesToReceive ); - - if( bytesReceived == ( int32_t ) bytesToReceive ) - { - /* Receive successful, bytesReceived == bytesToReceive. */ - LogDebug( ( "Packet received. ReceivedBytes=%ld.", - ( long int ) bytesReceived ) ); - } - else - { - LogError( ( "Packet reception failed. ReceivedBytes=%ld, " - "ExpectedBytes=%lu.", - ( long int ) bytesReceived, - ( unsigned long ) bytesToReceive ) ); - status = MQTTRecvFailed; - } - } - - return status; -} - -/*-----------------------------------------------------------*/ - -static uint8_t getAckTypeToSend( MQTTPublishState_t state ) -{ - uint8_t packetTypeByte = 0U; - - switch( state ) - { - case MQTTPubAckSend: - packetTypeByte = MQTT_PACKET_TYPE_PUBACK; - break; - - case MQTTPubRecSend: - packetTypeByte = MQTT_PACKET_TYPE_PUBREC; - break; - - case MQTTPubRelSend: - packetTypeByte = MQTT_PACKET_TYPE_PUBREL; - break; - - case MQTTPubCompSend: - packetTypeByte = MQTT_PACKET_TYPE_PUBCOMP; - break; - - case MQTTPubAckPending: - case MQTTPubCompPending: - case MQTTPubRecPending: - case MQTTPubRelPending: - case MQTTPublishDone: - case MQTTPublishSend: - case MQTTStateNull: - default: - /* Take no action for states that do not require sending an ack. */ - break; - } - - return packetTypeByte; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t sendPublishAcks( MQTTContext_t * pContext, - uint16_t packetId, - MQTTPublishState_t publishState ) -{ - MQTTStatus_t status = MQTTSuccess; - MQTTPublishState_t newState = MQTTStateNull; - int32_t sendResult = 0; - uint8_t packetTypeByte = 0U; - MQTTPubAckType_t packetType; - MQTTFixedBuffer_t localBuffer; - uint8_t pubAckPacket[ MQTT_PUBLISH_ACK_PACKET_SIZE ]; - - localBuffer.pBuffer = pubAckPacket; - localBuffer.size = MQTT_PUBLISH_ACK_PACKET_SIZE; - - assert( pContext != NULL ); - - packetTypeByte = getAckTypeToSend( publishState ); - - if( packetTypeByte != 0U ) - { - packetType = getAckFromPacketType( packetTypeByte ); - - status = MQTT_SerializeAck( &localBuffer, packetTypeByte, packetId ); - - if( status == MQTTSuccess ) - { - MQTT_PRE_SEND_HOOK( pContext ); - - /* Here, we are not using the vector approach for efficiency. There - * is just one buffer to be sent which can be achieved with a normal - * send call. */ - sendResult = sendBuffer( pContext, - localBuffer.pBuffer, - MQTT_PUBLISH_ACK_PACKET_SIZE ); - - MQTT_POST_SEND_HOOK( pContext ); - } - - if( sendResult == ( int32_t ) MQTT_PUBLISH_ACK_PACKET_SIZE ) - { - pContext->controlPacketSent = true; - - MQTT_PRE_STATE_UPDATE_HOOK( pContext ); - - status = MQTT_UpdateStateAck( pContext, - packetId, - packetType, - MQTT_SEND, - &newState ); - - MQTT_POST_STATE_UPDATE_HOOK( pContext ); - - if( status != MQTTSuccess ) - { - LogError( ( "Failed to update state of publish %hu.", - ( unsigned short ) packetId ) ); - } - } - else - { - LogError( - ( "Failed to send ACK packet: PacketType=%02x, SentBytes=%ld, " - "PacketSize=%lu.", - ( unsigned int ) packetTypeByte, - ( long int ) sendResult, - MQTT_PUBLISH_ACK_PACKET_SIZE ) ); - status = MQTTSendFailed; - } - } - - return status; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t handleKeepAlive( MQTTContext_t * pContext ) -{ - MQTTStatus_t status = MQTTSuccess; - uint32_t now = 0U; - uint32_t packetTxTimeoutMs = 0U; - - assert( pContext != NULL ); - assert( pContext->getTime != NULL ); - - now = pContext->getTime(); - - packetTxTimeoutMs = 1000U * ( uint32_t ) pContext->keepAliveIntervalSec; - - if( PACKET_TX_TIMEOUT_MS < packetTxTimeoutMs ) - { - packetTxTimeoutMs = PACKET_TX_TIMEOUT_MS; - } - - /* If keep alive interval is 0, it is disabled. */ - if( pContext->waitingForPingResp == true ) - { - /* Has time expired? */ - if( calculateElapsedTime( now, pContext->pingReqSendTimeMs ) > - MQTT_PINGRESP_TIMEOUT_MS ) - { - status = MQTTKeepAliveTimeout; - } - } - else - { - if( ( packetTxTimeoutMs != 0U ) && - ( calculateElapsedTime( now, pContext->lastPacketTxTime ) >= - packetTxTimeoutMs ) ) - { - status = MQTT_Ping( pContext ); - } - else - { - const uint32_t timeElapsed = calculateElapsedTime( - now, - pContext->lastPacketRxTime ); - - if( ( timeElapsed != 0U ) && - ( timeElapsed >= PACKET_RX_TIMEOUT_MS ) ) - { - status = MQTT_Ping( pContext ); - } - } - } - - return status; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t handleIncomingPublish( MQTTContext_t * pContext, - MQTTPacketInfo_t * pIncomingPacket ) -{ - MQTTStatus_t status = MQTTBadParameter; - MQTTPublishState_t publishRecordState = MQTTStateNull; - uint16_t packetIdentifier = 0U; - MQTTPublishInfo_t publishInfo; - MQTTDeserializedInfo_t deserializedInfo; - bool duplicatePublish = false; - - assert( pContext != NULL ); - assert( pIncomingPacket != NULL ); - assert( pContext->appCallback != NULL ); - - status = MQTT_DeserializePublish( pIncomingPacket, - &packetIdentifier, - &publishInfo ); - LogInfo( ( "De-serialized incoming PUBLISH packet: DeserializerResult=%s.", - MQTT_Status_strerror( status ) ) ); - - if( ( status == MQTTSuccess ) && - ( pContext->incomingPublishRecords == NULL ) && - ( publishInfo.qos > MQTTQoS0 ) ) - { - LogError( - ( "Incoming publish has QoS > MQTTQoS0 but incoming " - "publish records have not been initialized. Dropping the " - "incoming publish. Please call MQTT_InitStatefulQoS to enable " - "use of QoS1 and QoS2 publishes." ) ); - status = MQTTRecvFailed; - } - - if( status == MQTTSuccess ) - { - MQTT_PRE_STATE_UPDATE_HOOK( pContext ); - - status = MQTT_UpdateStatePublish( pContext, - packetIdentifier, - MQTT_RECEIVE, - publishInfo.qos, - &publishRecordState ); - - MQTT_POST_STATE_UPDATE_HOOK( pContext ); - - if( status == MQTTSuccess ) - { - LogInfo( ( "State record updated. New state=%s.", - MQTT_State_strerror( publishRecordState ) ) ); - } - - /* Different cases in which an incoming publish with duplicate flag is - * handled are as listed below. - * 1. No collision - This is the first instance of the incoming publish - * packet received or an earlier received packet state is lost. This - * will be handled as a new incoming publish for both QoS1 and QoS2 - * publishes. - * 2. Collision - The incoming packet was received before and a state - * record is present in the state engine. For QoS1 and QoS2 publishes - * this case can happen at 2 different cases and handling is - * different. - * a. QoS1 - If a PUBACK is not successfully sent for the incoming - * publish due to a connection issue, it can result in broker - * sending out a duplicate publish with dup flag set, when a - * session is reestablished. It can result in a collision in - * state engine. This will be handled by processing the incoming - * publish as a new publish ignoring the - * #MQTTStateCollision status from the state engine. The publish - * data is not passed to the application. - * b. QoS2 - If a PUBREC is not successfully sent for the incoming - * publish or the PUBREC sent is not successfully received by the - * broker due to a connection issue, it can result in broker - * sending out a duplicate publish with dup flag set, when a - * session is reestablished. It can result in a collision in - * state engine. This will be handled by ignoring the - * #MQTTStateCollision status from the state engine. The publish - * data is not passed to the application. */ - else if( status == MQTTStateCollision ) - { - status = MQTTSuccess; - duplicatePublish = true; - - /* Calculate the state for the ack packet that needs to be sent out - * for the duplicate incoming publish. */ - publishRecordState = MQTT_CalculateStatePublish( MQTT_RECEIVE, - publishInfo.qos ); - - LogDebug( - ( "Incoming publish packet with packet id %hu already exists.", - ( unsigned short ) packetIdentifier ) ); - - if( publishInfo.dup == false ) - { - LogError( - ( "DUP flag is 0 for duplicate packet (MQTT-3.3.1.-1)." ) ); - } - } - else - { - LogError( ( "Error in updating publish state for incoming publish " - "with packet id %hu." - " Error is %s", - ( unsigned short ) packetIdentifier, - MQTT_Status_strerror( status ) ) ); - } - } - - if( status == MQTTSuccess ) - { - /* Set fields of deserialized struct. */ - deserializedInfo.packetIdentifier = packetIdentifier; - deserializedInfo.pPublishInfo = &publishInfo; - deserializedInfo.deserializationResult = status; - - /* Invoke application callback to hand the buffer over to application - * before sending acks. - * Application callback will be invoked for all publishes, except for - * duplicate incoming publishes. */ - if( duplicatePublish == false ) - { - pContext->appCallback( pContext, - pIncomingPacket, - &deserializedInfo ); - } - - /* Send PUBACK or PUBREC if necessary. */ - status = sendPublishAcks( pContext, - packetIdentifier, - publishRecordState ); - } - - return status; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t handlePublishAcks( MQTTContext_t * pContext, - MQTTPacketInfo_t * pIncomingPacket ) -{ - MQTTStatus_t status = MQTTBadResponse; - MQTTPublishState_t publishRecordState = MQTTStateNull; - uint16_t packetIdentifier; - MQTTPubAckType_t ackType; - MQTTEventCallback_t appCallback; - MQTTDeserializedInfo_t deserializedInfo; - - assert( pContext != NULL ); - assert( pIncomingPacket != NULL ); - assert( pContext->appCallback != NULL ); - - appCallback = pContext->appCallback; - - ackType = getAckFromPacketType( pIncomingPacket->type ); - status = MQTT_DeserializeAck( pIncomingPacket, &packetIdentifier, NULL ); - LogInfo( ( "Ack packet deserialized with result: %s.", - MQTT_Status_strerror( status ) ) ); - - if( status == MQTTSuccess ) - { - MQTT_PRE_STATE_UPDATE_HOOK( pContext ); - - status = MQTT_UpdateStateAck( pContext, - packetIdentifier, - ackType, - MQTT_RECEIVE, - &publishRecordState ); - - MQTT_POST_STATE_UPDATE_HOOK( pContext ); - - if( status == MQTTSuccess ) - { - LogInfo( ( "State record updated. New state=%s.", - MQTT_State_strerror( publishRecordState ) ) ); - } - else - { - LogError( ( "Updating the state engine for packet id %hu" - " failed with error %s.", - ( unsigned short ) packetIdentifier, - MQTT_Status_strerror( status ) ) ); - } - } - - if( status == MQTTSuccess ) - { - /* Set fields of deserialized struct. */ - deserializedInfo.packetIdentifier = packetIdentifier; - deserializedInfo.deserializationResult = status; - deserializedInfo.pPublishInfo = NULL; - - /* Invoke application callback to hand the buffer over to application - * before sending acks. */ - appCallback( pContext, pIncomingPacket, &deserializedInfo ); - - /* Send PUBREL or PUBCOMP if necessary. */ - status = sendPublishAcks( pContext, - packetIdentifier, - publishRecordState ); - } - - return status; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t handleIncomingAck( MQTTContext_t * pContext, - MQTTPacketInfo_t * pIncomingPacket, - bool manageKeepAlive ) -{ - MQTTStatus_t status = MQTTBadResponse; - uint16_t packetIdentifier = MQTT_PACKET_ID_INVALID; - MQTTDeserializedInfo_t deserializedInfo; - - /* We should always invoke the app callback unless we receive a PINGRESP - * and are managing keep alive, or if we receive an unknown packet. We - * initialize this to false since the callback must be invoked before - * sending any PUBREL or PUBCOMP. However, for other cases, we invoke it - * at the end to reduce the complexity of this function. */ - bool invokeAppCallback = false; - MQTTEventCallback_t appCallback = NULL; - - assert( pContext != NULL ); - assert( pIncomingPacket != NULL ); - assert( pContext->appCallback != NULL ); - - appCallback = pContext->appCallback; - - LogDebug( ( "Received packet of type %02x.", - ( unsigned int ) pIncomingPacket->type ) ); - - switch( pIncomingPacket->type ) - { - case MQTT_PACKET_TYPE_PUBACK: - case MQTT_PACKET_TYPE_PUBREC: - case MQTT_PACKET_TYPE_PUBREL: - case MQTT_PACKET_TYPE_PUBCOMP: - - /* Handle all the publish acks. The app callback is invoked here. */ - status = handlePublishAcks( pContext, pIncomingPacket ); - - break; - - case MQTT_PACKET_TYPE_PINGRESP: - status = MQTT_DeserializeAck( pIncomingPacket, - &packetIdentifier, - NULL ); - invokeAppCallback = ( status == MQTTSuccess ) && !manageKeepAlive; - - if( ( status == MQTTSuccess ) && ( manageKeepAlive == true ) ) - { - pContext->waitingForPingResp = false; - } - - break; - - case MQTT_PACKET_TYPE_SUBACK: - case MQTT_PACKET_TYPE_UNSUBACK: - /* Deserialize and give these to the app provided callback. */ - status = MQTT_DeserializeAck( pIncomingPacket, - &packetIdentifier, - NULL ); - invokeAppCallback = ( status == MQTTSuccess ) || - ( status == MQTTServerRefused ); - break; - - default: - /* Bad response from the server. */ - LogError( ( "Unexpected packet type from server: PacketType=%02x.", - ( unsigned int ) pIncomingPacket->type ) ); - status = MQTTBadResponse; - break; - } - - if( invokeAppCallback == true ) - { - /* Set fields of deserialized struct. */ - deserializedInfo.packetIdentifier = packetIdentifier; - deserializedInfo.deserializationResult = status; - deserializedInfo.pPublishInfo = NULL; - appCallback( pContext, pIncomingPacket, &deserializedInfo ); - /* In case a SUBACK indicated refusal, reset the status to continue the - * loop. */ - status = MQTTSuccess; - } - - return status; -} -/*-----------------------------------------------------------*/ - -static MQTTStatus_t receiveSingleIteration( MQTTContext_t * pContext, - bool manageKeepAlive ) -{ - MQTTStatus_t status = MQTTSuccess; - MQTTPacketInfo_t incomingPacket = { 0 }; - int32_t recvBytes; - size_t totalMQTTPacketLength = 0; - - assert( pContext != NULL ); - assert( pContext->networkBuffer.pBuffer != NULL ); - - /* Read as many bytes as possible into the network buffer. */ - recvBytes = pContext->transportInterface.recv( - pContext->transportInterface.pNetworkContext, - &( pContext->networkBuffer.pBuffer[ pContext->index ] ), - pContext->networkBuffer.size - pContext->index ); - - if( recvBytes < 0 ) - { - /* The receive function has failed. Bubble up the error up to the user. - */ - status = MQTTRecvFailed; - } - else if( ( recvBytes == 0 ) && ( pContext->index == 0U ) ) - { - /* No more bytes available since the last read and neither is anything - * in the buffer. */ - status = MQTTNoDataAvailable; - } - - /* Either something was received, or there is still data to be processed in - * the buffer, or both. */ - else - { - /* Update the number of bytes in the MQTT fixed buffer. */ - pContext->index += ( size_t ) recvBytes; - - status = MQTT_ProcessIncomingPacketTypeAndLength( - pContext->networkBuffer.pBuffer, - &( pContext->index ), - &incomingPacket ); - - totalMQTTPacketLength = incomingPacket.remainingLength + - incomingPacket.headerLength; - } - - /* No data was received, check for keep alive timeout. */ - if( recvBytes == 0 ) - { - if( manageKeepAlive == true ) - { - /* Keep the copy of the status to be reset later. */ - MQTTStatus_t statusCopy = status; - - /* Assign status so an error can be bubbled up to application, - * but reset it on success. */ - status = handleKeepAlive( pContext ); - - if( status == MQTTSuccess ) - { - /* Reset the status. */ - status = statusCopy; - } - else - { - LogError( ( "Handling of keep alive failed. Status=%s", - MQTT_Status_strerror( status ) ) ); - } - } - } - - /* Check whether there is data available before processing the packet - * further. */ - if( ( status == MQTTNeedMoreBytes ) || ( status == MQTTNoDataAvailable ) ) - { - /* Do nothing as there is nothing to be processed right now. The proper - * error code will be bubbled up to the user. */ - } - /* Any other error code. */ - else if( status != MQTTSuccess ) - { - LogError( ( "Call to receiveSingleIteration failed. Status=%s", - MQTT_Status_strerror( status ) ) ); - } - /* If the MQTT Packet size is bigger than the buffer itself. */ - else if( totalMQTTPacketLength > pContext->networkBuffer.size ) - { - /* Discard the packet from the receive buffer and drain the pending - * data from the socket buffer. */ - status = discardStoredPacket( pContext, &incomingPacket ); - } - /* If the total packet is of more length than the bytes we have available. - */ - else if( totalMQTTPacketLength > pContext->index ) - { - status = MQTTNeedMoreBytes; - } - else - { - /* MISRA else. */ - } - - /* Handle received packet. If incomplete data was read then this will not - * execute. */ - if( status == MQTTSuccess ) - { - incomingPacket - .pRemainingData = &pContext->networkBuffer - .pBuffer[ incomingPacket.headerLength ]; - - /* PUBLISH packets allow flags in the lower four bits. For other - * packet types, they are reserved. */ - if( ( incomingPacket.type & 0xF0U ) == MQTT_PACKET_TYPE_PUBLISH ) - { - status = handleIncomingPublish( pContext, &incomingPacket ); - } - else - { - status = handleIncomingAck( pContext, - &incomingPacket, - manageKeepAlive ); - } - - /* Update the index to reflect the remaining bytes in the buffer. */ - pContext->index -= totalMQTTPacketLength; - - /* Move the remaining bytes to the front of the buffer. */ - ( void ) memmove( pContext->networkBuffer.pBuffer, - &( pContext->networkBuffer - .pBuffer[ totalMQTTPacketLength ] ), - pContext->index ); - - if( status == MQTTSuccess ) - { - pContext->lastPacketRxTime = pContext->getTime(); - } - } - - if( status == MQTTNoDataAvailable ) - { - /* No data available is not an error. Reset to MQTTSuccess so the - * return code will indicate success. */ - status = MQTTSuccess; - } - - return status; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t validateSubscribeUnsubscribeParams( - const MQTTContext_t * pContext, - const MQTTSubscribeInfo_t * pSubscriptionList, - size_t subscriptionCount, - uint16_t packetId ) -{ - MQTTStatus_t status = MQTTSuccess; - size_t iterator; - - /* Validate all the parameters. */ - if( ( pContext == NULL ) || ( pSubscriptionList == NULL ) ) - { - LogError( ( "Argument cannot be NULL: pContext=%p, " - "pSubscriptionList=%p.", - ( void * ) pContext, - ( void * ) pSubscriptionList ) ); - status = MQTTBadParameter; - } - else if( subscriptionCount == 0UL ) - { - LogError( ( "Subscription count is 0." ) ); - status = MQTTBadParameter; - } - else if( packetId == 0U ) - { - LogError( ( "Packet Id for subscription packet is 0." ) ); - status = MQTTBadParameter; - } - else - { - if( pContext->incomingPublishRecords == NULL ) - { - for( iterator = 0; iterator < subscriptionCount; iterator++ ) - { - if( pSubscriptionList->qos > MQTTQoS0 ) - { - LogError( - ( "The incoming publish record list is not " - "initialised for QoS1/QoS2 records. Please call " - " MQTT_InitStatefulQoS to enable use of QoS1 and " - " QoS2 packets." ) ); - status = MQTTBadParameter; - break; - } - } - } - } - - return status; -} - -/*-----------------------------------------------------------*/ - -static size_t addEncodedStringToVector( - uint8_t serializedLength[ CORE_MQTT_SERIALIZED_LENGTH_FIELD_BYTES ], - const char * const string, - uint16_t length, - TransportOutVector_t * iterator, - size_t * updatedLength ) -{ - size_t packetLength = 0U; - TransportOutVector_t * pLocalIterator = iterator; - size_t vectorsAdded = 0U; - - /* When length is non-zero, the string must be non-NULL. */ - assert( ( length != 0U ) ? ( string != NULL ) : true ); - - serializedLength[ 0 ] = ( ( uint8_t ) ( ( length ) >> 8 ) ); - serializedLength[ 1 ] = ( ( uint8_t ) ( ( length ) &0x00ffU ) ); - - /* Add the serialized length of the string first. */ - pLocalIterator[ 0 ].iov_base = serializedLength; - pLocalIterator[ 0 ].iov_len = CORE_MQTT_SERIALIZED_LENGTH_FIELD_BYTES; - vectorsAdded++; - packetLength = CORE_MQTT_SERIALIZED_LENGTH_FIELD_BYTES; - - /* Sometimes the string can be NULL that is, of 0 length. In that case, - * only the length field should be encoded in the vector. */ - if( ( string != NULL ) && ( length != 0U ) ) - { - /* Then add the pointer to the string itself. */ - pLocalIterator[ 1 ].iov_base = string; - pLocalIterator[ 1 ].iov_len = length; - vectorsAdded++; - packetLength += length; - } - - ( *updatedLength ) = ( *updatedLength ) + packetLength; - - return vectorsAdded; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t sendSubscribeWithoutCopy( - MQTTContext_t * pContext, - const MQTTSubscribeInfo_t * pSubscriptionList, - size_t subscriptionCount, - uint16_t packetId, - size_t remainingLength ) -{ - MQTTStatus_t status = MQTTSuccess; - uint8_t * pIndex; - TransportOutVector_t pIoVector[ MQTT_SUB_UNSUB_MAX_VECTORS ]; - TransportOutVector_t * pIterator; - uint8_t - serializedTopicFieldLength[ MQTT_SUB_UNSUB_MAX_VECTORS ] - [ CORE_MQTT_SERIALIZED_LENGTH_FIELD_BYTES ]; - size_t totalPacketLength = 0U; - size_t ioVectorLength = 0U; - size_t subscriptionsSent = 0U; - size_t vectorsAdded; - size_t topicFieldLengthIndex; - - /* Maximum number of bytes required by the 'fixed' part of the SUBSCRIBE - * packet header according to the MQTT specification. - * MQTT Control Byte 0 + 1 = 1 - * Remaining length (max) + 4 = 5 - * Packet ID + 2 = 7 */ - uint8_t subscribeheader[ 7U ]; - - /* The vector array should be at least three element long as the topic - * string needs these many vector elements to be stored. */ - assert( MQTT_SUB_UNSUB_MAX_VECTORS >= - CORE_MQTT_SUBSCRIBE_PER_TOPIC_VECTOR_LENGTH ); - - pIndex = subscribeheader; - pIterator = pIoVector; - - pIndex = MQTT_SerializeSubscribeHeader( remainingLength, pIndex, packetId ); - - /* The header is to be sent first. */ - pIterator->iov_base = subscribeheader; - /* More details at: - * https://github.com/FreeRTOS/coreMQTT/blob/main/MISRA.md#rule-182 */ - /* More details at: - * https://github.com/FreeRTOS/coreMQTT/blob/main/MISRA.md#rule-108 */ - /* coverity[misra_c_2012_rule_18_2_violation] */ - /* coverity[misra_c_2012_rule_10_8_violation] */ - pIterator->iov_len = ( size_t ) ( pIndex - subscribeheader ); - totalPacketLength += pIterator->iov_len; - pIterator++; - ioVectorLength++; - - while( ( status == MQTTSuccess ) && - ( subscriptionsSent < subscriptionCount ) ) - { - /* Reset the index for next iteration. */ - topicFieldLengthIndex = 0; - - /* Check whether the subscription topic (with QoS) will fit in the - * given vector. */ - while( ( ioVectorLength <= - ( MQTT_SUB_UNSUB_MAX_VECTORS - - CORE_MQTT_SUBSCRIBE_PER_TOPIC_VECTOR_LENGTH ) ) && - ( subscriptionsSent < subscriptionCount ) ) - { - /* The topic filter and the filter length gets sent next. */ - vectorsAdded = addEncodedStringToVector( - serializedTopicFieldLength[ topicFieldLengthIndex ], - pSubscriptionList[ subscriptionsSent ].pTopicFilter, - pSubscriptionList[ subscriptionsSent ].topicFilterLength, - pIterator, - &totalPacketLength ); - - /* Update the pointer after the above operation. */ - pIterator = &pIterator[ vectorsAdded ]; - - /* Lastly, the QoS gets sent. */ - pIterator->iov_base = &( - pSubscriptionList[ subscriptionsSent ].qos ); - pIterator->iov_len = 1U; - totalPacketLength += pIterator->iov_len; - - /* Increment the pointer. */ - pIterator++; - - /* Two slots get used by the topic string length and topic string. - * One slot gets used by the quality of service. */ - ioVectorLength += vectorsAdded + 1U; - - subscriptionsSent++; - - /* The index needs to be updated for next iteration. */ - topicFieldLengthIndex++; - } - - if( sendMessageVector( pContext, pIoVector, ioVectorLength ) != - ( int32_t ) totalPacketLength ) - { - status = MQTTSendFailed; - } - - /* Update the iterator for the next potential loop iteration. */ - pIterator = pIoVector; - /* Reset the vector length for the next potential loop iteration. */ - ioVectorLength = 0U; - /* Reset the packet length for the next potential loop iteration. */ - totalPacketLength = 0U; - } - - return status; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t sendUnsubscribeWithoutCopy( - MQTTContext_t * pContext, - const MQTTSubscribeInfo_t * pSubscriptionList, - size_t subscriptionCount, - uint16_t packetId, - size_t remainingLength ) -{ - MQTTStatus_t status = MQTTSuccess; - uint8_t * pIndex; - TransportOutVector_t pIoVector[ MQTT_SUB_UNSUB_MAX_VECTORS ]; - TransportOutVector_t * pIterator; - uint8_t - serializedTopicFieldLength[ MQTT_SUB_UNSUB_MAX_VECTORS ] - [ CORE_MQTT_SERIALIZED_LENGTH_FIELD_BYTES ]; - size_t totalPacketLength = 0U; - size_t unsubscriptionsSent = 0U; - size_t ioVectorLength = 0U; - size_t vectorsAdded; - size_t topicFieldLengthIndex; - - /* Maximum number of bytes required by the 'fixed' part of the UNSUBSCRIBE - * packet header according to the MQTT specification. - * MQTT Control Byte 0 + 1 = 1 - * Remaining length (max) + 4 = 5 - * Packet ID + 2 = 7 */ - uint8_t unsubscribeheader[ 7U ]; - - /* The vector array should be at least three element long as the topic - * string needs these many vector elements to be stored. */ - assert( MQTT_SUB_UNSUB_MAX_VECTORS >= - CORE_MQTT_UNSUBSCRIBE_PER_TOPIC_VECTOR_LENGTH ); - - pIndex = unsubscribeheader; - pIterator = pIoVector; - - pIndex = MQTT_SerializeUnsubscribeHeader( remainingLength, - pIndex, - packetId ); - - /* The header is to be sent first. */ - pIterator->iov_base = unsubscribeheader; - /* More details at: - * https://github.com/FreeRTOS/coreMQTT/blob/main/MISRA.md#rule-182 */ - /* More details at: - * https://github.com/FreeRTOS/coreMQTT/blob/main/MISRA.md#rule-108 */ - /* coverity[misra_c_2012_rule_18_2_violation] */ - /* coverity[misra_c_2012_rule_10_8_violation] */ - pIterator->iov_len = ( size_t ) ( pIndex - unsubscribeheader ); - totalPacketLength += pIterator->iov_len; - pIterator++; - ioVectorLength++; - - while( ( status == MQTTSuccess ) && - ( unsubscriptionsSent < subscriptionCount ) ) - { - /* Reset the index for next iteration. */ - topicFieldLengthIndex = 0; - - /* Check whether the subscription topic will fit in the given vector. */ - while( ( ioVectorLength <= - ( MQTT_SUB_UNSUB_MAX_VECTORS - - CORE_MQTT_UNSUBSCRIBE_PER_TOPIC_VECTOR_LENGTH ) ) && - ( unsubscriptionsSent < subscriptionCount ) ) - { - /* The topic filter gets sent next. */ - vectorsAdded = addEncodedStringToVector( - serializedTopicFieldLength[ topicFieldLengthIndex ], - pSubscriptionList[ unsubscriptionsSent ].pTopicFilter, - pSubscriptionList[ unsubscriptionsSent ].topicFilterLength, - pIterator, - &totalPacketLength ); - - /* Update the iterator to point to the next empty location. */ - pIterator = &pIterator[ vectorsAdded ]; - /* Update the total count based on how many vectors were added. */ - ioVectorLength += vectorsAdded; - - unsubscriptionsSent++; - - /* Update the index for next iteration. */ - topicFieldLengthIndex++; - } - - if( sendMessageVector( pContext, pIoVector, ioVectorLength ) != - ( int32_t ) totalPacketLength ) - { - status = MQTTSendFailed; - } - - /* Update the iterator for the next potential loop iteration. */ - pIterator = pIoVector; - /* Reset the vector length for the next potential loop iteration. */ - ioVectorLength = 0U; - /* Reset the packet length for the next potential loop iteration. */ - totalPacketLength = 0U; - } - - return status; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t sendPublishWithoutCopy( - MQTTContext_t * pContext, - const MQTTPublishInfo_t * pPublishInfo, - const uint8_t * pMqttHeader, - size_t headerSize, - uint16_t packetId ) -{ - MQTTStatus_t status = MQTTSuccess; - size_t ioVectorLength; - size_t totalMessageLength; - - /* Bytes required to encode the packet ID in an MQTT header according to - * the MQTT specification. */ - uint8_t serializedPacketID[ 2U ]; - - /* Maximum number of vectors required to encode and send a publish - * packet. The breakdown is shown below. - * Fixed header (including topic string length) 0 + 1 = 1 - * Topic string + 1 = 2 - * Packet ID (only when QoS > QoS0) + 1 = 3 - * Payload + 1 = 4 */ - TransportOutVector_t pIoVector[ 4U ]; - - /* The header is sent first. */ - pIoVector[ 0U ].iov_base = pMqttHeader; - pIoVector[ 0U ].iov_len = headerSize; - totalMessageLength = headerSize; - - /* Then the topic name has to be sent. */ - pIoVector[ 1U ].iov_base = pPublishInfo->pTopicName; - pIoVector[ 1U ].iov_len = pPublishInfo->topicNameLength; - totalMessageLength += pPublishInfo->topicNameLength; - - /* The next field's index should be 2 as the first two fields - * have been filled in. */ - ioVectorLength = 2U; - - if( pPublishInfo->qos > MQTTQoS0 ) - { - /* Encode the packet ID. */ - serializedPacketID[ 0 ] = ( ( uint8_t ) ( ( packetId ) >> 8 ) ); - serializedPacketID[ 1 ] = ( ( uint8_t ) ( ( packetId ) &0x00ffU ) ); - - pIoVector[ ioVectorLength ].iov_base = serializedPacketID; - pIoVector[ ioVectorLength ].iov_len = sizeof( serializedPacketID ); - - ioVectorLength++; - totalMessageLength += sizeof( serializedPacketID ); - } - - /* Publish packets are allowed to contain no payload. */ - if( pPublishInfo->payloadLength > 0U ) - { - pIoVector[ ioVectorLength ].iov_base = pPublishInfo->pPayload; - pIoVector[ ioVectorLength ].iov_len = pPublishInfo->payloadLength; - - ioVectorLength++; - totalMessageLength += pPublishInfo->payloadLength; - } - - if( sendMessageVector( pContext, pIoVector, ioVectorLength ) != - ( int32_t ) totalMessageLength ) - { - status = MQTTSendFailed; - } - - return status; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t sendConnectWithoutCopy( - MQTTContext_t * pContext, - const MQTTConnectInfo_t * pConnectInfo, - const MQTTPublishInfo_t * pWillInfo, - size_t remainingLength ) -{ - MQTTStatus_t status = MQTTSuccess; - TransportOutVector_t * iterator; - size_t ioVectorLength = 0U; - size_t totalMessageLength = 0U; - int32_t bytesSentOrError; - uint8_t * pIndex; - uint8_t serializedClientIDLength[ 2 ]; - uint8_t serializedTopicLength[ 2 ]; - uint8_t serializedPayloadLength[ 2 ]; - uint8_t serializedUsernameLength[ 2 ]; - uint8_t serializedPasswordLength[ 2 ]; - size_t vectorsAdded; - - /* Maximum number of bytes required by the 'fixed' part of the CONNECT - * packet header according to the MQTT specification. - * MQTT Control Byte 0 + 1 = 1 - * Remaining length (max) + 4 = 5 - * Protocol Name Length + 2 = 7 - * Protocol Name (MQTT) + 4 = 11 - * Protocol level + 1 = 12 - * Connect flags + 1 = 13 - * Keep alive + 2 = 15 */ - uint8_t connectPacketHeader[ 15U ]; - - /* The maximum vectors required to encode and send a connect packet. The - * breakdown is shown below. - * Fixed header 0 + 1 = 1 - * Client ID + 2 = 3 - * Will topic + 2 = 5 - * Will payload + 2 = 7 - * Username + 2 = 9 - * Password + 2 = 11 */ - TransportOutVector_t pIoVector[ 11U ]; - - iterator = pIoVector; - pIndex = connectPacketHeader; - - /* Validate arguments. */ - if( ( pWillInfo != NULL ) && ( pWillInfo->pTopicName == NULL ) ) - { - LogError( - ( "pWillInfo->pTopicName cannot be NULL if Will is present." ) ); - status = MQTTBadParameter; - } - else - { - pIndex = MQTT_SerializeConnectFixedHeader( pIndex, - pConnectInfo, - pWillInfo, - remainingLength ); - - assert( ( pIndex - connectPacketHeader ) <= - sizeof( connectPacketHeader ) ); - - /* The header gets sent first. */ - iterator->iov_base = connectPacketHeader; - /* More details at: - * https://github.com/FreeRTOS/coreMQTT/blob/main/MISRA.md#rule-182 */ - /* More details at: - * https://github.com/FreeRTOS/coreMQTT/blob/main/MISRA.md#rule-108 */ - /* coverity[misra_c_2012_rule_18_2_violation] */ - /* coverity[misra_c_2012_rule_10_8_violation] */ - iterator->iov_len = ( size_t ) ( pIndex - connectPacketHeader ); - totalMessageLength += iterator->iov_len; - iterator++; - ioVectorLength++; - - /* Serialize the client ID. */ - vectorsAdded = addEncodedStringToVector( - serializedClientIDLength, - pConnectInfo->pClientIdentifier, - pConnectInfo->clientIdentifierLength, - iterator, - &totalMessageLength ); - - /* Update the iterator to point to the next empty slot. */ - iterator = &iterator[ vectorsAdded ]; - ioVectorLength += vectorsAdded; - - if( pWillInfo != NULL ) - { - /* Serialize the topic. */ - vectorsAdded = addEncodedStringToVector( serializedTopicLength, - pWillInfo->pTopicName, - pWillInfo->topicNameLength, - iterator, - &totalMessageLength ); - - /* Update the iterator to point to the next empty slot. */ - iterator = &iterator[ vectorsAdded ]; - ioVectorLength += vectorsAdded; - - /* Serialize the payload. Payload of last will and testament can be - * NULL. */ - vectorsAdded = addEncodedStringToVector( serializedPayloadLength, - pWillInfo->pPayload, - ( uint16_t ) pWillInfo - ->payloadLength, - iterator, - &totalMessageLength ); - - /* Update the iterator to point to the next empty slot. */ - iterator = &iterator[ vectorsAdded ]; - ioVectorLength += vectorsAdded; - } - - /* Encode the user name if provided. */ - if( pConnectInfo->pUserName != NULL ) - { - /* Serialize the user name string. */ - vectorsAdded = addEncodedStringToVector( serializedUsernameLength, - pConnectInfo->pUserName, - pConnectInfo - ->userNameLength, - iterator, - &totalMessageLength ); - - /* Update the iterator to point to the next empty slot. */ - iterator = &iterator[ vectorsAdded ]; - ioVectorLength += vectorsAdded; - } - - /* Encode the password if provided. */ - if( pConnectInfo->pPassword != NULL ) - { - /* Serialize the user name string. */ - vectorsAdded = addEncodedStringToVector( serializedPasswordLength, - pConnectInfo->pPassword, - pConnectInfo - ->passwordLength, - iterator, - &totalMessageLength ); - /* Update the iterator to point to the next empty slot. */ - iterator = &iterator[ vectorsAdded ]; - ioVectorLength += vectorsAdded; - } - - bytesSentOrError = sendMessageVector( pContext, - pIoVector, - ioVectorLength ); - - if( bytesSentOrError != ( int32_t ) totalMessageLength ) - { - status = MQTTSendFailed; - } - } - - return status; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t receiveConnack( const MQTTContext_t * pContext, - uint32_t timeoutMs, - bool cleanSession, - MQTTPacketInfo_t * pIncomingPacket, - bool * pSessionPresent ) -{ - MQTTStatus_t status = MQTTSuccess; - MQTTGetCurrentTimeFunc_t getTimeStamp = NULL; - uint32_t entryTimeMs = 0U, remainingTimeMs = 0U, timeTakenMs = 0U; - bool breakFromLoop = false; - uint16_t loopCount = 0U; - - assert( pContext != NULL ); - assert( pIncomingPacket != NULL ); - assert( pContext->getTime != NULL ); - - getTimeStamp = pContext->getTime; - - /* Get the entry time for the function. */ - entryTimeMs = getTimeStamp(); - - do - { - /* Transport read for incoming CONNACK packet type and length. - * MQTT_GetIncomingPacketTypeAndLength is a blocking call and it is - * returned after a transport receive timeout, an error, or a successful - * receive of packet type and length. */ - status = MQTT_GetIncomingPacketTypeAndLength( - pContext->transportInterface.recv, - pContext->transportInterface.pNetworkContext, - pIncomingPacket ); - - /* The loop times out based on 2 conditions. - * 1. If timeoutMs is greater than 0: - * Loop times out based on the timeout calculated by getTime() - * function. - * 2. If timeoutMs is 0: - * Loop times out based on the maximum number of retries config - * MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT. This config will control - * maximum the number of retry attempts to read the CONNACK packet. - * A value of 0 for the config will try once to read CONNACK. */ - if( timeoutMs > 0U ) - { - breakFromLoop = calculateElapsedTime( getTimeStamp(), - entryTimeMs ) >= timeoutMs; - } - else - { - breakFromLoop = loopCount >= MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT; - loopCount++; - } - - /* Loop until there is data to read or if we have exceeded the - * timeout/retries. */ - } while( ( status == MQTTNoDataAvailable ) && ( breakFromLoop == false ) ); - - if( status == MQTTSuccess ) - { - /* Time taken in this function so far. */ - timeTakenMs = calculateElapsedTime( getTimeStamp(), entryTimeMs ); - - if( timeTakenMs < timeoutMs ) - { - /* Calculate remaining time for receiving the remainder of - * the packet. */ - remainingTimeMs = timeoutMs - timeTakenMs; - } - - /* Reading the remainder of the packet by transport recv. - * Attempt to read once even if the timeout has expired. - * Invoking receivePacket with remainingTime as 0 would attempt to - * recv from network once. If using retries, the remainder of the - * CONNACK packet is tried to be read only once. Reading once would be - * good as the packet type and remaining length was already read. Hence, - * the probability of the remaining 2 bytes available to read is very - * high. */ - if( pIncomingPacket->type == MQTT_PACKET_TYPE_CONNACK ) - { - status = receivePacket( pContext, - *pIncomingPacket, - remainingTimeMs ); - } - else - { - LogError( ( "Incorrect packet type %X received while expecting" - " CONNACK(%X).", - ( unsigned int ) pIncomingPacket->type, - MQTT_PACKET_TYPE_CONNACK ) ); - status = MQTTBadResponse; - } - } - - if( status == MQTTSuccess ) - { - /* Update the packet info pointer to the buffer read. */ - pIncomingPacket->pRemainingData = pContext->networkBuffer.pBuffer; - - /* Deserialize CONNACK. */ - status = MQTT_DeserializeAck( pIncomingPacket, NULL, pSessionPresent ); - } - - /* If a clean session is requested, a session present should not be set by - * broker. */ - if( status == MQTTSuccess ) - { - if( ( cleanSession == true ) && ( *pSessionPresent == true ) ) - { - LogError( ( - "Unexpected session present flag in CONNACK response from " - "broker." - " CONNECT request with clean session was made with broker." ) ); - status = MQTTBadResponse; - } - } - - if( status == MQTTSuccess ) - { - LogDebug( ( "Received MQTT CONNACK successfully from broker." ) ); - } - else - { - LogError( ( "CONNACK recv failed with status = %s.", - MQTT_Status_strerror( status ) ) ); - } - - return status; -} - -/*-----------------------------------------------------------*/ - -static MQTTStatus_t handleSessionResumption( MQTTContext_t * pContext, - bool sessionPresent ) -{ - MQTTStatus_t status = MQTTSuccess; - MQTTStateCursor_t cursor = MQTT_STATE_CURSOR_INITIALIZER; - uint16_t packetId = MQTT_PACKET_ID_INVALID; - MQTTPublishState_t state = MQTTStateNull; - - assert( pContext != NULL ); - - /* Reset the index and clear the buffer when a new session is established. - */ - pContext->index = 0; - ( void ) memset( pContext->networkBuffer.pBuffer, - 0, - pContext->networkBuffer.size ); - - if( sessionPresent == true ) - { - /* Get the next packet ID for which a PUBREL need to be resent. */ - packetId = MQTT_PubrelToResend( pContext, &cursor, &state ); - - /* Resend all the PUBREL acks after session is reestablished. */ - while( ( packetId != MQTT_PACKET_ID_INVALID ) && - ( status == MQTTSuccess ) ) - { - status = sendPublishAcks( pContext, packetId, state ); - - packetId = MQTT_PubrelToResend( pContext, &cursor, &state ); - } - } - else - { - /* Clear any existing records if a new session is established. */ - if( pContext->outgoingPublishRecordMaxCount > 0U ) - { - ( void ) memset( pContext->outgoingPublishRecords, - 0x00, - pContext->outgoingPublishRecordMaxCount * - sizeof( *pContext->outgoingPublishRecords ) ); - } - - if( pContext->incomingPublishRecordMaxCount > 0U ) - { - ( void ) memset( pContext->incomingPublishRecords, - 0x00, - pContext->incomingPublishRecordMaxCount * - sizeof( *pContext->incomingPublishRecords ) ); - } - } - - return status; -} - -static MQTTStatus_t validatePublishParams( - const MQTTContext_t * pContext, - const MQTTPublishInfo_t * pPublishInfo, - uint16_t packetId ) -{ - MQTTStatus_t status = MQTTSuccess; - - /* Validate arguments. */ - if( ( pContext == NULL ) || ( pPublishInfo == NULL ) ) - { - LogError( ( "Argument cannot be NULL: pContext=%p, " - "pPublishInfo=%p.", - ( void * ) pContext, - ( void * ) pPublishInfo ) ); - status = MQTTBadParameter; - } - else if( ( pPublishInfo->qos != MQTTQoS0 ) && ( packetId == 0U ) ) - { - LogError( ( "Packet Id is 0 for PUBLISH with QoS=%u.", - ( unsigned int ) pPublishInfo->qos ) ); - status = MQTTBadParameter; - } - else if( ( pPublishInfo->payloadLength > 0U ) && - ( pPublishInfo->pPayload == NULL ) ) - { - LogError( ( "A nonzero payload length requires a non-NULL payload: " - "payloadLength=%lu, pPayload=%p.", - ( unsigned long ) pPublishInfo->payloadLength, - pPublishInfo->pPayload ) ); - status = MQTTBadParameter; - } - else if( ( pContext->outgoingPublishRecords == NULL ) && - ( pPublishInfo->qos > MQTTQoS0 ) ) - { - LogError( ( - "Trying to publish a QoS > MQTTQoS0 packet when outgoing publishes " - "for QoS1/QoS2 have not been enabled. Please, call " - "MQTT_InitStatefulQoS " - "to initialize and enable the use of QoS1/QoS2 publishes." ) ); - status = MQTTBadParameter; - } - else - { - /* MISRA else */ - } - - return status; -} - -/*-----------------------------------------------------------*/ - -MQTTStatus_t MQTT_Init( MQTTContext_t * pContext, - const TransportInterface_t * pTransportInterface, - MQTTGetCurrentTimeFunc_t getTimeFunction, - MQTTEventCallback_t userCallback, - const MQTTFixedBuffer_t * pNetworkBuffer ) -{ - MQTTStatus_t status = MQTTSuccess; - - /* Validate arguments. */ - if( ( pContext == NULL ) || ( pTransportInterface == NULL ) || - ( pNetworkBuffer == NULL ) ) - { - LogError( ( "Argument cannot be NULL: pContext=%p, " - "pTransportInterface=%p, " - "pNetworkBuffer=%p", - ( void * ) pContext, - ( void * ) pTransportInterface, - ( void * ) pNetworkBuffer ) ); - status = MQTTBadParameter; - } - else if( getTimeFunction == NULL ) - { - LogError( ( "Invalid parameter: getTimeFunction is NULL" ) ); - status = MQTTBadParameter; - } - else if( userCallback == NULL ) - { - LogError( ( "Invalid parameter: userCallback is NULL" ) ); - status = MQTTBadParameter; - } - else if( pTransportInterface->recv == NULL ) - { - LogError( ( "Invalid parameter: pTransportInterface->recv is NULL" ) ); - status = MQTTBadParameter; - } - else if( pTransportInterface->send == NULL ) - { - LogError( ( "Invalid parameter: pTransportInterface->send is NULL" ) ); - status = MQTTBadParameter; - } - else - { - ( void ) memset( pContext, 0x00, sizeof( MQTTContext_t ) ); - - pContext->connectStatus = MQTTNotConnected; - pContext->transportInterface = *pTransportInterface; - pContext->getTime = getTimeFunction; - pContext->appCallback = userCallback; - pContext->networkBuffer = *pNetworkBuffer; - - /* Zero is not a valid packet ID per MQTT spec. Start from 1. */ - pContext->nextPacketId = 1; - } - - return status; -} - -/*-----------------------------------------------------------*/ - -MQTTStatus_t MQTT_InitStatefulQoS( MQTTContext_t * pContext, - MQTTPubAckInfo_t * pOutgoingPublishRecords, - size_t outgoingPublishCount, - MQTTPubAckInfo_t * pIncomingPublishRecords, - size_t incomingPublishCount ) -{ - MQTTStatus_t status = MQTTSuccess; - - if( pContext == NULL ) - { - LogError( - ( "Argument cannot be NULL: pContext=%p\n", ( void * ) pContext ) ); - status = MQTTBadParameter; - } - - /* Check whether the arguments make sense. Not equal here behaves - * like an exclusive-or operator for boolean values. */ - else if( ( outgoingPublishCount == 0U ) != - ( pOutgoingPublishRecords == NULL ) ) - { - LogError( ( "Arguments do not match: pOutgoingPublishRecords=%p, " - "outgoingPublishCount=%lu", - ( void * ) pOutgoingPublishRecords, - outgoingPublishCount ) ); - status = MQTTBadParameter; - } - - /* Check whether the arguments make sense. Not equal here behaves - * like an exclusive-or operator for boolean values. */ - else if( ( incomingPublishCount == 0U ) != - ( pIncomingPublishRecords == NULL ) ) - { - LogError( ( "Arguments do not match: pIncomingPublishRecords=%p, " - "incomingPublishCount=%lu", - ( void * ) pIncomingPublishRecords, - incomingPublishCount ) ); - status = MQTTBadParameter; - } - else if( pContext->appCallback == NULL ) - { - LogError( - ( "MQTT_InitStatefulQoS must be called only after MQTT_Init has" - " been called succesfully.\n" ) ); - status = MQTTBadParameter; - } - else - { - pContext->incomingPublishRecordMaxCount = incomingPublishCount; - pContext->incomingPublishRecords = pIncomingPublishRecords; - pContext->outgoingPublishRecordMaxCount = outgoingPublishCount; - pContext->outgoingPublishRecords = pOutgoingPublishRecords; - } - - return status; -} - -/*-----------------------------------------------------------*/ - -MQTTStatus_t MQTT_CancelCallback( const MQTTContext_t * pContext, - uint16_t packetId ) -{ - MQTTStatus_t status = MQTTSuccess; - - if( pContext == NULL ) - { - LogWarn( ( "pContext is NULL\n" ) ); - status = MQTTBadParameter; - } - else if( pContext->outgoingPublishRecords == NULL ) - { - LogError( ( "QoS1/QoS2 is not initialized for use. Please, " - "call MQTT_InitStatefulQoS to enable QoS1 and QoS2 " - "publishes.\n" ) ); - status = MQTTBadParameter; - } - else - { - MQTT_PRE_STATE_UPDATE_HOOK( pContext ); - - status = MQTT_RemoveStateRecord( pContext, packetId ); - - MQTT_POST_STATE_UPDATE_HOOK( pContext ); - } - - return status; -} - -/*-----------------------------------------------------------*/ - -MQTTStatus_t MQTT_Connect( MQTTContext_t * pContext, - const MQTTConnectInfo_t * pConnectInfo, - const MQTTPublishInfo_t * pWillInfo, - uint32_t timeoutMs, - bool * pSessionPresent ) -{ - size_t remainingLength = 0UL, packetSize = 0UL; - MQTTStatus_t status = MQTTSuccess; - MQTTPacketInfo_t incomingPacket = { 0 }; - - incomingPacket.type = ( uint8_t ) 0; - - if( ( pContext == NULL ) || ( pConnectInfo == NULL ) || - ( pSessionPresent == NULL ) ) - { - LogError( ( "Argument cannot be NULL: pContext=%p, " - "pConnectInfo=%p, pSessionPresent=%p.", - ( void * ) pContext, - ( void * ) pConnectInfo, - ( void * ) pSessionPresent ) ); - status = MQTTBadParameter; - } - - if( status == MQTTSuccess ) - { - /* Get MQTT connect packet size and remaining length. */ - status = MQTT_GetConnectPacketSize( pConnectInfo, - pWillInfo, - &remainingLength, - &packetSize ); - LogDebug( ( "CONNECT packet size is %lu and remaining length is %lu.", - ( unsigned long ) packetSize, - ( unsigned long ) remainingLength ) ); - } - - if( status == MQTTSuccess ) - { - MQTT_PRE_SEND_HOOK( pContext ); - - status = sendConnectWithoutCopy( pContext, - pConnectInfo, - pWillInfo, - remainingLength ); - - MQTT_POST_SEND_HOOK( pContext ); - } - - /* Read CONNACK from transport layer. */ - if( status == MQTTSuccess ) - { - status = receiveConnack( pContext, - timeoutMs, - pConnectInfo->cleanSession, - &incomingPacket, - pSessionPresent ); - } - - if( status == MQTTSuccess ) - { - /* Resend PUBRELs when reestablishing a session, or clear records for - * new sessions. */ - status = handleSessionResumption( pContext, *pSessionPresent ); - } - - if( status == MQTTSuccess ) - { - LogInfo( ( "MQTT connection established with the broker." ) ); - pContext->connectStatus = MQTTConnected; - /* Initialize keep-alive fields after a successful connection. */ - pContext->keepAliveIntervalSec = pConnectInfo->keepAliveSeconds; - pContext->waitingForPingResp = false; - pContext->pingReqSendTimeMs = 0U; - } - else - { - LogError( ( "MQTT connection failed with status = %s.", - MQTT_Status_strerror( status ) ) ); - } - - return status; -} - -/*-----------------------------------------------------------*/ - -MQTTStatus_t MQTT_Subscribe( MQTTContext_t * pContext, - const MQTTSubscribeInfo_t * pSubscriptionList, - size_t subscriptionCount, - uint16_t packetId ) -{ - size_t remainingLength = 0UL, packetSize = 0UL; - - /* Validate arguments. */ - MQTTStatus_t status = validateSubscribeUnsubscribeParams( pContext, - pSubscriptionList, - subscriptionCount, - packetId ); - - if( status == MQTTSuccess ) - { - /* Get the remaining length and packet size.*/ - status = MQTT_GetSubscribePacketSize( pSubscriptionList, - subscriptionCount, - &remainingLength, - &packetSize ); - LogDebug( ( "SUBSCRIBE packet size is %lu and remaining length is %lu.", - ( unsigned long ) packetSize, - ( unsigned long ) remainingLength ) ); - } - - if( status == MQTTSuccess ) - { - MQTT_PRE_SEND_HOOK( pContext ); - - /* Send MQTT SUBSCRIBE packet. */ - status = sendSubscribeWithoutCopy( pContext, - pSubscriptionList, - subscriptionCount, - packetId, - remainingLength ); - - MQTT_POST_SEND_HOOK( pContext ); - } - - return status; -} - -/*-----------------------------------------------------------*/ - -MQTTStatus_t MQTT_Publish( MQTTContext_t * pContext, - const MQTTPublishInfo_t * pPublishInfo, - uint16_t packetId ) -{ - size_t headerSize = 0UL; - size_t remainingLength = 0UL; - size_t packetSize = 0UL; - MQTTPublishState_t publishStatus = MQTTStateNull; - bool stateUpdateHookExecuted = false; - - /* Maximum number of bytes required by the 'fixed' part of the PUBLISH - * packet header according to the MQTT specifications. - * Header byte 0 + 1 = 1 - * Length (max) + 4 = 5 - * Topic string length + 2 = 7 - * - * Note that since publish is one of the most common operations in MQTT - * connection, we have moved the topic string length to the 'fixed' part of - * the header so efficiency. Otherwise, we would need an extra vector and - * an extra call to 'send' (in case writev is not defined) to send the - * topic length. */ - uint8_t mqttHeader[ 7U ]; - - /* Validate arguments. */ - MQTTStatus_t status = validatePublishParams( pContext, - pPublishInfo, - packetId ); - - if( status == MQTTSuccess ) - { - /* Get the remaining length and packet size.*/ - status = MQTT_GetPublishPacketSize( pPublishInfo, - &remainingLength, - &packetSize ); - } - - if( status == MQTTSuccess ) - { - status = MQTT_SerializePublishHeaderWithoutTopic( pPublishInfo, - remainingLength, - mqttHeader, - &headerSize ); - } - - if( ( status == MQTTSuccess ) && ( pPublishInfo->qos > MQTTQoS0 ) ) - { - MQTT_PRE_STATE_UPDATE_HOOK( pContext ); - - /* Set the flag so that the corresponding hook can be called later. */ - stateUpdateHookExecuted = true; - - status = MQTT_ReserveState( pContext, packetId, pPublishInfo->qos ); - - /* State already exists for a duplicate packet. - * If a state doesn't exist, it will be handled as a new publish in - * state engine. */ - if( ( status == MQTTStateCollision ) && ( pPublishInfo->dup == true ) ) - { - status = MQTTSuccess; - } - } - - if( status == MQTTSuccess ) - { - /* Take the mutex as multiple send calls are required for sending this - * packet. */ - MQTT_PRE_SEND_HOOK( pContext ); - - status = sendPublishWithoutCopy( pContext, - pPublishInfo, - mqttHeader, - headerSize, - packetId ); - - /* Give the mutex away for the next taker. */ - MQTT_POST_SEND_HOOK( pContext ); - } - - if( ( status == MQTTSuccess ) && ( pPublishInfo->qos > MQTTQoS0 ) ) - { - /* Update state machine after PUBLISH is sent. - * Only to be done for QoS1 or QoS2. */ - status = MQTT_UpdateStatePublish( pContext, - packetId, - MQTT_SEND, - pPublishInfo->qos, - &publishStatus ); - - if( status != MQTTSuccess ) - { - LogError( ( "Update state for publish failed with status %s." - " However PUBLISH packet was sent to the broker." - " Any further handling of ACKs for the packet Id" - " will fail.", - MQTT_Status_strerror( status ) ) ); - } - } - - if( stateUpdateHookExecuted == true ) - { - /* Regardless of the status, if the mutex was taken due to the - * packet being of QoS > QoS0, then it should be relinquished. */ - MQTT_POST_STATE_UPDATE_HOOK( pContext ); - } - - if( status != MQTTSuccess ) - { - LogError( ( "MQTT PUBLISH failed with status %s.", - MQTT_Status_strerror( status ) ) ); - } - - return status; -} - -/*-----------------------------------------------------------*/ - -MQTTStatus_t MQTT_Ping( MQTTContext_t * pContext ) -{ - int32_t sendResult = 0; - MQTTStatus_t status = MQTTSuccess; - size_t packetSize = 0U; - /* MQTT ping packets are of fixed length. */ - uint8_t pingreqPacket[ 2U ]; - MQTTFixedBuffer_t localBuffer; - - localBuffer.pBuffer = pingreqPacket; - localBuffer.size = sizeof( pingreqPacket ); - - if( pContext == NULL ) - { - LogError( ( "pContext is NULL." ) ); - status = MQTTBadParameter; - } - - if( status == MQTTSuccess ) - { - /* Get MQTT PINGREQ packet size. */ - status = MQTT_GetPingreqPacketSize( &packetSize ); - - if( status == MQTTSuccess ) - { - assert( packetSize == localBuffer.size ); - LogDebug( ( "MQTT PINGREQ packet size is %lu.", - ( unsigned long ) packetSize ) ); - } - else - { - LogError( ( "Failed to get the PINGREQ packet size." ) ); - } - } - - if( status == MQTTSuccess ) - { - /* Serialize MQTT PINGREQ. */ - status = MQTT_SerializePingreq( &localBuffer ); - } - - if( status == MQTTSuccess ) - { - /* Take the mutex as the send call should not be interrupted in - * between. */ - MQTT_PRE_SEND_HOOK( pContext ); - - /* Send the serialized PINGREQ packet to transport layer. - * Here, we do not use the vectored IO approach for efficiency as the - * Ping packet does not have numerous fields which need to be copied - * from the user provided buffers. Thus it can be sent directly. */ - sendResult = sendBuffer( pContext, localBuffer.pBuffer, packetSize ); - - /* Give the mutex away. */ - MQTT_POST_SEND_HOOK( pContext ); - - /* It is an error to not send the entire PINGREQ packet. */ - if( sendResult < ( int32_t ) packetSize ) - { - LogError( ( "Transport send failed for PINGREQ packet." ) ); - status = MQTTSendFailed; - } - else - { - pContext->pingReqSendTimeMs = pContext->lastPacketTxTime; - pContext->waitingForPingResp = true; - LogDebug( ( "Sent %ld bytes of PINGREQ packet.", - ( long int ) sendResult ) ); - } - } - - return status; -} - -/*-----------------------------------------------------------*/ - -MQTTStatus_t MQTT_Unsubscribe( MQTTContext_t * pContext, - const MQTTSubscribeInfo_t * pSubscriptionList, - size_t subscriptionCount, - uint16_t packetId ) -{ - size_t remainingLength = 0UL, packetSize = 0UL; - - /* Validate arguments. */ - MQTTStatus_t status = validateSubscribeUnsubscribeParams( pContext, - pSubscriptionList, - subscriptionCount, - packetId ); - - if( status == MQTTSuccess ) - { - /* Get the remaining length and packet size.*/ - status = MQTT_GetUnsubscribePacketSize( pSubscriptionList, - subscriptionCount, - &remainingLength, - &packetSize ); - LogDebug( - ( "UNSUBSCRIBE packet size is %lu and remaining length is %lu.", - ( unsigned long ) packetSize, - ( unsigned long ) remainingLength ) ); - } - - if( status == MQTTSuccess ) - { - /* Take the mutex because the below call should not be interrupted. */ - MQTT_PRE_SEND_HOOK( pContext ); - - status = sendUnsubscribeWithoutCopy( pContext, - pSubscriptionList, - subscriptionCount, - packetId, - remainingLength ); - - /* Give the mutex away. */ - MQTT_POST_SEND_HOOK( pContext ); - } - - return status; -} - -/*-----------------------------------------------------------*/ - -MQTTStatus_t MQTT_Disconnect( MQTTContext_t * pContext ) -{ - size_t packetSize = 0U; - int32_t sendResult = 0; - MQTTStatus_t status = MQTTSuccess; - MQTTFixedBuffer_t localBuffer; - uint8_t disconnectPacket[ 2U ]; - - localBuffer.pBuffer = disconnectPacket; - localBuffer.size = 2U; - - /* Validate arguments. */ - if( pContext == NULL ) - { - LogError( ( "pContext cannot be NULL." ) ); - status = MQTTBadParameter; - } - - if( status == MQTTSuccess ) - { - /* Get MQTT DISCONNECT packet size. */ - status = MQTT_GetDisconnectPacketSize( &packetSize ); - LogDebug( ( "MQTT DISCONNECT packet size is %lu.", - ( unsigned long ) packetSize ) ); - } - - if( status == MQTTSuccess ) - { - /* Serialize MQTT DISCONNECT packet. */ - status = MQTT_SerializeDisconnect( &localBuffer ); - } - - if( status == MQTTSuccess ) - { - /* Take the mutex because the below call should not be interrupted. */ - MQTT_PRE_SEND_HOOK( pContext ); - - /* Here we do not use vectors as the disconnect packet has fixed fields - * which do not reside in user provided buffers. Thus, it can be sent - * using a simple send call. */ - sendResult = sendBuffer( pContext, localBuffer.pBuffer, packetSize ); - - /* Give the mutex away. */ - MQTT_POST_SEND_HOOK( pContext ); - - if( sendResult < ( int32_t ) packetSize ) - { - LogError( ( "Transport send failed for DISCONNECT packet." ) ); - status = MQTTSendFailed; - } - else - { - LogDebug( ( "Sent %ld bytes of DISCONNECT packet.", - ( long int ) sendResult ) ); - } - } - - if( status == MQTTSuccess ) - { - LogInfo( ( "Disconnected from the broker." ) ); - pContext->connectStatus = MQTTNotConnected; - - /* Reset the index and clean the buffer on a successful disconnect. */ - pContext->index = 0; - ( void ) memset( pContext->networkBuffer.pBuffer, - 0, - pContext->networkBuffer.size ); - } - - return status; -} - -/*-----------------------------------------------------------*/ - -MQTTStatus_t MQTT_ProcessLoop( MQTTContext_t * pContext ) -{ - MQTTStatus_t status = MQTTBadParameter; - - if( pContext == NULL ) - { - LogError( ( "Invalid input parameter: MQTT Context cannot be NULL." ) ); - } - else if( pContext->getTime == NULL ) - { - LogError( ( "Invalid input parameter: MQTT Context must have valid " - "getTime." ) ); - } - else if( pContext->networkBuffer.pBuffer == NULL ) - { - LogError( ( "Invalid input parameter: The MQTT context's networkBuffer " - "must not be NULL." ) ); - } - else - { - pContext->controlPacketSent = false; - status = receiveSingleIteration( pContext, true ); - } - - return status; -} - -/*-----------------------------------------------------------*/ - -MQTTStatus_t MQTT_ReceiveLoop( MQTTContext_t * pContext ) -{ - MQTTStatus_t status = MQTTBadParameter; - - if( pContext == NULL ) - { - LogError( ( "Invalid input parameter: MQTT Context cannot be NULL." ) ); - } - else if( pContext->getTime == NULL ) - { - LogError( ( "Invalid input parameter: MQTT Context must have a valid " - "getTime function." ) ); - } - else if( pContext->networkBuffer.pBuffer == NULL ) - { - LogError( ( "Invalid input parameter: MQTT context's networkBuffer " - "must not be NULL." ) ); - } - else - { - status = receiveSingleIteration( pContext, false ); - } - - return status; -} - -/*-----------------------------------------------------------*/ - -uint16_t MQTT_GetPacketId( MQTTContext_t * pContext ) -{ - uint16_t packetId = 0U; - - if( pContext != NULL ) - { - MQTT_PRE_STATE_UPDATE_HOOK( pContext ); - - packetId = pContext->nextPacketId; - - /* A packet ID of zero is not a valid packet ID. When the max ID - * is reached the next one should start at 1. */ - if( pContext->nextPacketId == ( uint16_t ) UINT16_MAX ) - { - pContext->nextPacketId = 1; - } - else - { - pContext->nextPacketId++; - } - - MQTT_POST_STATE_UPDATE_HOOK( pContext ); - } - - return packetId; -} - -/*-----------------------------------------------------------*/ - -MQTTStatus_t MQTT_MatchTopic( const char * pTopicName, - const uint16_t topicNameLength, - const char * pTopicFilter, - const uint16_t topicFilterLength, - bool * pIsMatch ) -{ - MQTTStatus_t status = MQTTSuccess; - bool topicFilterStartsWithWildcard = false; - bool matchStatus = false; - - if( ( pTopicName == NULL ) || ( topicNameLength == 0u ) ) - { - LogError( ( "Invalid paramater: Topic name should be non-NULL and its " - "length should be > 0: TopicName=%p, TopicNameLength=%hu", - ( void * ) pTopicName, - ( unsigned short ) topicNameLength ) ); - - status = MQTTBadParameter; - } - else if( ( pTopicFilter == NULL ) || ( topicFilterLength == 0u ) ) - { - LogError( - ( "Invalid paramater: Topic filter should be non-NULL and " - "its length should be > 0: TopicName=%p, TopicFilterLength=%hu", - ( void * ) pTopicFilter, - ( unsigned short ) topicFilterLength ) ); - status = MQTTBadParameter; - } - else if( pIsMatch == NULL ) - { - LogError( - ( "Invalid paramater: Output parameter, pIsMatch, is NULL" ) ); - status = MQTTBadParameter; - } - else - { - /* Check for an exact match if the incoming topic name and the - * registered topic filter length match. */ - if( topicNameLength == topicFilterLength ) - { - matchStatus = strncmp( pTopicName, - pTopicFilter, - topicNameLength ) == 0; - } - - if( matchStatus == false ) - { - /* If an exact match was not found, match against wildcard - * characters in topic filter.*/ - - /* Determine if topic filter starts with a wildcard. */ - topicFilterStartsWithWildcard = ( pTopicFilter[ 0 ] == '+' ) || - ( pTopicFilter[ 0 ] == '#' ); - - /* Note: According to the MQTT 3.1.1 specification, incoming PUBLISH - * topic names starting with "$" character cannot be matched against - * topic filter starting with a wildcard, i.e. for example, - * "$SYS/sport" cannot be matched with "#" or - * "+/sport" topic filters. */ - if( !( ( pTopicName[ 0 ] == '$' ) && - ( topicFilterStartsWithWildcard == true ) ) ) - { - matchStatus = matchTopicFilter( pTopicName, - topicNameLength, - pTopicFilter, - topicFilterLength ); - } - } - - /* Update the output parameter with the match result. */ - *pIsMatch = matchStatus; - } - - return status; -} - -/*-----------------------------------------------------------*/ - -MQTTStatus_t MQTT_GetSubAckStatusCodes( const MQTTPacketInfo_t * pSubackPacket, - uint8_t ** pPayloadStart, - size_t * pPayloadSize ) -{ - MQTTStatus_t status = MQTTSuccess; - - if( pSubackPacket == NULL ) - { - LogError( ( "Invalid parameter: pSubackPacket is NULL." ) ); - status = MQTTBadParameter; - } - else if( pPayloadStart == NULL ) - { - LogError( ( "Invalid parameter: pPayloadStart is NULL." ) ); - status = MQTTBadParameter; - } - else if( pPayloadSize == NULL ) - { - LogError( ( "Invalid parameter: pPayloadSize is NULL." ) ); - status = MQTTBadParameter; - } - else if( pSubackPacket->type != MQTT_PACKET_TYPE_SUBACK ) - { - LogError( ( "Invalid parameter: Input packet is not a SUBACK packet: " - "ExpectedType=%02x, InputType=%02x", - ( int ) MQTT_PACKET_TYPE_SUBACK, - ( int ) pSubackPacket->type ) ); - status = MQTTBadParameter; - } - else if( pSubackPacket->pRemainingData == NULL ) - { - LogError( - ( "Invalid parameter: pSubackPacket->pRemainingData is NULL" ) ); - status = MQTTBadParameter; - } - - /* A SUBACK must have a remaining length of at least 3 to accommodate the - * packet identifier and at least 1 return code. */ - else if( pSubackPacket->remainingLength < 3U ) - { - LogError( ( "Invalid parameter: Packet remaining length is invalid: " - "Should be greater than 2 for SUBACK packet: " - "InputRemainingLength=%lu", - ( unsigned long ) pSubackPacket->remainingLength ) ); - status = MQTTBadParameter; - } - else - { - /* According to the MQTT 3.1.1 protocol specification, the "Remaining - * Length" field is a length of the variable header (2 bytes) plus the - * length of the payload. Therefore, we add 2 positions for the starting - * address of the payload, and subtract 2 bytes from the remaining - * length for the length of the payload.*/ - *pPayloadStart = &pSubackPacket->pRemainingData[ sizeof( uint16_t ) ]; - *pPayloadSize = pSubackPacket->remainingLength - sizeof( uint16_t ); - } - - return status; -} - -/*-----------------------------------------------------------*/ - -const char * MQTT_Status_strerror( MQTTStatus_t status ) -{ - const char * str = NULL; - - switch( status ) - { - case MQTTSuccess: - str = "MQTTSuccess"; - break; - - case MQTTBadParameter: - str = "MQTTBadParameter"; - break; - - case MQTTNoMemory: - str = "MQTTNoMemory"; - break; - - case MQTTSendFailed: - str = "MQTTSendFailed"; - break; - - case MQTTRecvFailed: - str = "MQTTRecvFailed"; - break; - - case MQTTBadResponse: - str = "MQTTBadResponse"; - break; - - case MQTTServerRefused: - str = "MQTTServerRefused"; - break; - - case MQTTNoDataAvailable: - str = "MQTTNoDataAvailable"; - break; - - case MQTTIllegalState: - str = "MQTTIllegalState"; - break; - - case MQTTStateCollision: - str = "MQTTStateCollision"; - break; - - case MQTTKeepAliveTimeout: - str = "MQTTKeepAliveTimeout"; - break; - - case MQTTNeedMoreBytes: - str = "MQTTNeedMoreBytes"; - break; - - default: - str = "Invalid MQTT Status code"; - break; - } - - return str; -} - -/*-----------------------------------------------------------*/ diff --git a/formatting/goodFiles/source/tasks.c b/formatting/goodFiles/source/tasks.c deleted file mode 100644 index 3a642c3e..00000000 --- a/formatting/goodFiles/source/tasks.c +++ /dev/null @@ -1,6151 +0,0 @@ -/* - * FreeRTOS Kernel - * 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 -#include - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining - * all the API functions to use the MPU wrappers. That should only be done when - * task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -/* FreeRTOS includes. */ -#include "FreeRTOS.h" -#include "stack_macros.h" -#include "task.h" -#include "timers.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 -#endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 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 - -/* 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 */ - -/*-----------------------------------------------------------*/ - - #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 */ - -/*-----------------------------------------------------------*/ - -/* 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 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 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 - - 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. */ - 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( ( 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. */ -portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL; - -/* 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 xYieldPending = 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 - xIdleTaskHandle = NULL; /**< Holds the handle of the idle task. The idle - task is 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. */ -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 = 0UL; /**< Holds the value of a timer/counter the last - time a task was switched in. */ -PRIVILEGED_DATA static volatile configRUN_TIME_COUNTER_TYPE - ulTotalRunTime = 0UL; /**< Holds the total amount of execution time as - defined by the run time counter clock. */ - -#endif - -/*lint -restore */ - -/*-----------------------------------------------------------*/ - -/* File private functions. --------------------------------*/ - -/** - * 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. - * - * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific - * language extensions. The equivalent prototype for this function is: - * - * void prvIdleTask( void *pvParameters ); - * - */ -static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ) PRIVILEGED_FUNCTION; - -/* - * 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( 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 ) -{ - 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. */ - 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 ); - 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 ) -{ - 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; - 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 ); - - 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 ) -{ - TCB_t * pxNewTCB; - BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; - - configASSERT( pxTaskDefinition->puxStackBuffer ); - - if( pxTaskDefinition->puxStackBuffer != 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 * ) pvPortMalloc( sizeof( TCB_t ) ); - - if( pxNewTCB != NULL ) - { - 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 ); - - 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 ) -{ - 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 ) - { - 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 ) - { - 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 ); - 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 - -/* 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 */ - - 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(); - } -} -/*-----------------------------------------------------------*/ - -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(); - } -} -/*-----------------------------------------------------------*/ - -#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( pxTCB == pxCurrentTCB ) - { - /* A task is deleting itself. 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. */ - portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending ); - } - else - { - --uxCurrentNumberOfTasks; - traceTASK_DELETE( pxTCB ); - - /* Reset the next expected unblock time in case it referred to - * the task that has just been deleted. */ - prvResetNextTaskUnblockTime(); - } - } - 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 == ( UBaseType_t ) 0U ); - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } -} - -#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 ) ); - configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U ); - - vTaskSuspendAll(); - { - /* Minor optimisation. The tick count cannot change in this - * block. */ - const TickType_t xConstTickCount = xTickCount; - - /* 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 ) - { - portYIELD_WITHIN_API(); - } - 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 ) - { - configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U ); - vTaskSuspendAll(); - { - 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 ) - { - portYIELD_WITHIN_API(); - } - 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( pxTCB == pxCurrentTCB ) - { - /* The task calling this function is querying its own state. */ - eReturn = eRunning; - } - else - { - 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 = 0; x < 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 the task is not in any other state, it must be in the - * Ready (including pending ready) state. */ - eReturn = eReady; - } - } - - 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 uxSavedInterruptState; - - /* 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(); - - uxSavedInterruptState = portSET_INTERRUPT_MASK_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; - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState ); - - 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; - - 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 the calling task. */ - if( uxNewPriority > uxCurrentBasePriority ) - { - 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( pxTCB == pxCurrentTCB ) - { - /* Setting the priority of the running task down means - * there may now be another task of higher priority that - * is ready to execute. */ - 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 - { - mtCOVERAGE_TEST_MARKER(); - } - - if( xYieldRequired != pdFALSE ) - { - taskYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - /* Remove compiler warning about unused variables when the port - * optimised task selection is not being used. */ - ( void ) uxPriorityUsedOnEntry; - } - } - taskEXIT_CRITICAL(); -} - -#endif /* INCLUDE_vTaskPrioritySet */ -/*-----------------------------------------------------------*/ - -#if( INCLUDE_vTaskSuspend == 1 ) - -void vTaskSuspend( TaskHandle_t xTaskToSuspend ) -{ - TCB_t * pxTCB; - - taskENTER_CRITICAL(); - { - /* If null is passed in here then it is the running task that is - * being suspended. */ - pxTCB = prvGetTCBFromHandle( xTaskToSuspend ); - - traceTASK_SUSPEND( pxTCB ); - - /* 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 = 0; x < 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 ) */ - } - 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 == ( UBaseType_t ) 0U ); - 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(); - } -} - -#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 ); - - /* The parameter cannot be NULL as it is impossible to resume the - * currently executing task. */ - if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) ) - { - 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 ); - - /* 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 - { - 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 = portSET_INTERRUPT_MASK_FROM_ISR(); - { - if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) - { - traceTASK_RESUME_FROM_ISR( pxTCB ); - - /* Check the ready lists can be accessed. */ - if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) - { - /* 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. */ - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - ( 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 ) ); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - - return xYieldRequired; -} - -#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 \ - ) ) */ -/*-----------------------------------------------------------*/ - -void vTaskStartScheduler( void ) -{ - BaseType_t xReturn; - -/* 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 ); - xIdleTaskHandle = 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( xIdleTaskHandle != 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. - */ - &xIdleTaskHandle ); /*lint !e961 MISRA exception, - justified as it is not a - redundant explicit cast to - all supported compilers. - */ - } -#endif /* configSUPPORT_STATIC_ALLOCATION */ - -#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 xIdleTaskHandle is not used anywhere else. */ - ( void ) xIdleTaskHandle; - - /* 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 ) -{ - /* 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(); -} -/*----------------------------------------------------------*/ - -#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 uxSchedulerSuspended is zero then this function does not match a - * previous call to vTaskSuspendAll(). */ - configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U ); - - /* 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(); - { - --uxSchedulerSuspended; - - 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 and co-routines 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 the moved task has a priority higher than the current - * task then a yield must be performed. */ - if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) - { - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - - 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. */ - { - TickType_t xPendedCounts = xPendedTicks; /* Non-volatile - copy. */ - - if( xPendedCounts > ( TickType_t ) 0U ) - { - do - { - if( xTaskIncrementTick() != pdFALSE ) - { - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - --xPendedCounts; - } while( xPendedCounts > ( TickType_t ) 0U ); - - xPendedTicks = 0; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - - if( xYieldPending != pdFALSE ) - { -#if( configUSE_PREEMPTION != 0 ) - { - xAlreadyYielded = pdTRUE; - } -#endif - taskYIELD_IF_USING_PREEMPTION(); - } - 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 ) - -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 - and co-routines 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 and co-routines - 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; -} - -#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 ) - -TaskHandle_t xTaskGetIdleTaskHandle( void ) -{ - /* If xTaskGetIdleTaskHandle() is called before the scheduler has been - * started, then xIdleTaskHandle will be NULL. */ - configASSERT( ( xIdleTaskHandle != NULL ) ); - return xIdleTaskHandle; -} - -#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 ) - { - /* 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. */ - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_PREEMPTION */ - } - else - { - xReturn = pdFAIL; - } - } - ( void ) xTaskResumeAll(); - - return xReturn; -} - -#endif /* INCLUDE_xTaskAbortDelay */ -/*----------------------------------------------------------*/ - -BaseType_t xTaskIncrementTick( void ) -{ - TCB_t * pxTCB; - TickType_t xItemValue; - BaseType_t xSwitchRequired = pdFALSE; - - /* 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 ); - - 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 ) - { - /* 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(); - } - } -#endif /* configUSE_PREEMPTION */ - } - } - } - -/* 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( listCURRENT_LIST_LENGTH( - &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > - ( UBaseType_t ) 1 ) - { - xSwitchRequired = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } -#endif /* ( ( 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( xYieldPending != pdFALSE ) - { - xSwitchRequired = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } -#endif /* configUSE_PREEMPTION */ - } - 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 = portSET_INTERRUPT_MASK_FROM_ISR(); - { - xReturn = pxTCB->pxTaskTag; - } - portCLEAR_INTERRUPT_MASK_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 */ -/*-----------------------------------------------------------*/ - -void vTaskSwitchContext( void ) -{ - if( uxSchedulerSuspended != ( UBaseType_t ) 0U ) - { - /* The scheduler is currently suspended - do not allow a context - * switch. */ - xYieldPending = pdTRUE; - } - else - { - xYieldPending = pdFALSE; - traceTASK_SWITCHED_OUT(); - -#if( configGENERATE_RUN_TIME_STATS == 1 ) - { - #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE - portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); - #else - ulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) - 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 > ulTaskSwitchedInTime ) - { - pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - - ulTaskSwitchedInTime ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - ulTaskSwitchedInTime = ulTotalRunTime; - } -#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 and - co-routines 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 - } -} -/*-----------------------------------------------------------*/ - -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( 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. */ - xYieldPending = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - - 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( 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). */ - xYieldPending = pdTRUE; - } -} -/*-----------------------------------------------------------*/ - -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 ) -{ - xYieldPending = 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 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 ); - - for( ;; ) - { - /* 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 more than one - * task then a task other than the idle task is ready to execute. */ - if( listCURRENT_LIST_LENGTH( - &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > - ( UBaseType_t ) 1 ) - { - 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( 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( xYieldPending != 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 < 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 < 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 xRegions ) -{ - 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 ), xRegions, 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 ) - { - taskENTER_CRITICAL(); - { - pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( - &xTasksWaitingTermination ) ); /*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. */ - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); - --uxCurrentNumberOfTasks; - --uxDeletedTasksWaitingCleanUp; - } - taskEXIT_CRITICAL(); - - prvDeleteTCB( pxTCB ); - } - } -#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_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( pxTCB == pxCurrentTCB ) - { - 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( pxCurrentTCB->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 ) ) - -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; -} - -#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( uxSchedulerSuspended == ( UBaseType_t ) 0U ) - { - xReturn = taskSCHEDULER_RUNNING; - } - else - { - xReturn = taskSCHEDULER_SUSPENDED; - } - } - - 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 ); - } - 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 ); - - /* 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 ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } -} - -#endif /* configUSE_MUTEXES */ -/*-----------------------------------------------------------*/ - -#if( portCRITICAL_NESTING_IN_TCB == 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 /* portCRITICAL_NESTING_IN_TCB */ -/*-----------------------------------------------------------*/ - -#if( portCRITICAL_NESTING_IN_TCB == 1 ) - -void vTaskExitCritical( void ) -{ - if( xSchedulerRunning != pdFALSE ) - { - 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 /* portCRITICAL_NESTING_IN_TCB */ -/*-----------------------------------------------------------*/ - -#if( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) - -static char * prvWriteNameToBuffer( char * pcBuffer, const char * pcTaskName ) -{ - size_t x; - - /* Start by copying the entire string. */ - 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 ) ( configMAX_TASK_NAME_LEN - 1 ); - 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 ) -{ - /* If xSemaphoreCreateMutex() is called before any tasks have been created - * then pxCurrentTCB will be NULL. */ - if( pxCurrentTCB != NULL ) - { - ( pxCurrentTCB->uxMutexesHeld )++; - } - - return pxCurrentTCB; -} - -#endif /* configUSE_MUTEXES */ -/*-----------------------------------------------------------*/ - -#if( configUSE_TASK_NOTIFICATIONS == 1 ) - -uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait, - BaseType_t xClearCountOnExit, - TickType_t xTicksToWait ) -{ - uint32_t ulReturn; - - configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES ); - - taskENTER_CRITICAL(); - { - /* Only block if the notification count is not already non-zero. */ - if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL ) - { - /* Mark this task as waiting for a notification. */ - pxCurrentTCB - ->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; - - if( xTicksToWait > ( TickType_t ) 0 ) - { - prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); - traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait ); - - /* 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. */ - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL(); - - taskENTER_CRITICAL(); - { - traceTASK_NOTIFY_TAKE( uxIndexToWait ); - ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ]; - - if( ulReturn != 0UL ) - { - if( xClearCountOnExit != pdFALSE ) - { - pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = 0UL; - } - else - { - pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = ulReturn - - ( uint32_t ) 1; - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - pxCurrentTCB - ->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION; - } - taskEXIT_CRITICAL(); - - return ulReturn; -} - -#endif /* configUSE_TASK_NOTIFICATIONS */ -/*-----------------------------------------------------------*/ - -#if( configUSE_TASK_NOTIFICATIONS == 1 ) - -BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait, - uint32_t ulBitsToClearOnEntry, - uint32_t ulBitsToClearOnExit, - uint32_t * pulNotificationValue, - TickType_t xTicksToWait ) -{ - BaseType_t xReturn; - - configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES ); - - taskENTER_CRITICAL(); - { - /* Only block if a notification is not already pending. */ - if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != - 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[ uxIndexToWait ] &= ~ulBitsToClearOnEntry; - - /* Mark this task as waiting for a notification. */ - pxCurrentTCB - ->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; - - if( xTicksToWait > ( TickType_t ) 0 ) - { - prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); - traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait ); - - /* 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. */ - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL(); - - taskENTER_CRITICAL(); - { - traceTASK_NOTIFY_WAIT( uxIndexToWait ); - - if( pulNotificationValue != NULL ) - { - /* Output the current notification value, which may or may not - * have changed. */ - *pulNotificationValue = pxCurrentTCB - ->ulNotifiedValue[ uxIndexToWait ]; - } - - /* 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[ uxIndexToWait ] != - 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[ uxIndexToWait ] &= ~ulBitsToClearOnExit; - xReturn = pdTRUE; - } - - pxCurrentTCB - ->ucNotifyState[ uxIndexToWait ] = 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( 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 - { - 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 = portSET_INTERRUPT_MASK_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( 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. */ - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - portCLEAR_INTERRUPT_MASK_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 = portSET_INTERRUPT_MASK_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( 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. */ - xYieldPending = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - portCLEAR_INTERRUPT_MASK_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 ) - -configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ) -{ - return ulTaskGetRunTimeCounter( xIdleTaskHandle ); -} - -#endif -/*-----------------------------------------------------------*/ - -#if( configGENERATE_RUN_TIME_STATS == 1 ) - -configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ) -{ - return ulTaskGetRunTimePercent( xIdleTaskHandle ); -} - -#endif -/*-----------------------------------------------------------*/ - -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 ) */ diff --git a/formatting/uncrustify.cfg b/formatting/uncrustify.cfg new file mode 100644 index 00000000..0cb7d3fb --- /dev/null +++ b/formatting/uncrustify.cfg @@ -0,0 +1,160 @@ +# Uncrustify-0.67 +input_tab_size = 4 # unsigned number +output_tab_size = 4 # unsigned number +sp_arith = force # ignore/add/remove/force +sp_assign = force # ignore/add/remove/force +sp_assign_default = force # ignore/add/remove/force +sp_before_assign = force # ignore/add/remove/force +sp_after_assign = force # ignore/add/remove/force +sp_enum_assign = force # ignore/add/remove/force +sp_enum_before_assign = force # ignore/add/remove/force +sp_enum_after_assign = force # ignore/add/remove/force +sp_pp_stringify = add # ignore/add/remove/force +sp_bool = force # ignore/add/remove/force +sp_compare = force # ignore/add/remove/force +sp_inside_paren = force # ignore/add/remove/force +sp_paren_paren = force # ignore/add/remove/force +sp_paren_brace = force # ignore/add/remove/force +sp_before_ptr_star = force # ignore/add/remove/force +sp_before_unnamed_ptr_star = force # ignore/add/remove/force +sp_between_ptr_star = remove # ignore/add/remove/force +sp_after_ptr_star = force # ignore/add/remove/force +sp_before_byref = force # ignore/add/remove/force +sp_after_byref = remove # ignore/add/remove/force +sp_after_byref_func = remove # ignore/add/remove/force +sp_before_angle = remove # ignore/add/remove/force +sp_inside_angle = remove # ignore/add/remove/force +sp_after_angle = force # ignore/add/remove/force +sp_before_sparen = remove # ignore/add/remove/force +sp_inside_sparen = force # ignore/add/remove/force +sp_after_sparen = force # ignore/add/remove/force +sp_sparen_brace = force # ignore/add/remove/force +sp_before_semi_for = remove # ignore/add/remove/force +sp_before_semi_for_empty = add # ignore/add/remove/force +sp_after_semi_for_empty = force # ignore/add/remove/force +sp_before_square = remove # ignore/add/remove/force +sp_before_squares = remove # ignore/add/remove/force +sp_inside_square = force # ignore/add/remove/force +sp_after_comma = force # ignore/add/remove/force +sp_after_cast = force # ignore/add/remove/force +sp_inside_paren_cast = force # ignore/add/remove/force +sp_sizeof_paren = remove # ignore/add/remove/force +sp_inside_braces_enum = force # ignore/add/remove/force +sp_inside_braces_struct = force # ignore/add/remove/force +sp_inside_braces = force # ignore/add/remove/force +sp_inside_braces_empty = remove # ignore/add/remove/force +sp_type_func = force # ignore/add/remove/force +sp_func_proto_paren = remove # ignore/add/remove/force +sp_func_def_paren = remove # ignore/add/remove/force +sp_inside_fparens = remove # ignore/add/remove/force +sp_inside_fparen = force # ignore/add/remove/force +sp_fparen_brace = add # ignore/add/remove/force +sp_func_call_paren = remove # ignore/add/remove/force +sp_func_class_paren = remove # ignore/add/remove/force +sp_return_paren = remove # ignore/add/remove/force +sp_attribute_paren = remove # ignore/add/remove/force +sp_defined_paren = remove # ignore/add/remove/force +sp_macro = force # ignore/add/remove/force +sp_macro_func = force # ignore/add/remove/force +sp_brace_typedef = force # ignore/add/remove/force +sp_before_dc = remove # ignore/add/remove/force +sp_after_dc = remove # ignore/add/remove/force +sp_cond_colon = force # ignore/add/remove/force +sp_cond_question = force # ignore/add/remove/force +sp_case_label = force # ignore/add/remove/force +sp_endif_cmt = force # ignore/add/remove/force +sp_before_tr_emb_cmt = force # ignore/add/remove/force +sp_num_before_tr_emb_cmt = 1 # unsigned number +indent_columns = 4 # unsigned number +indent_with_tabs = 0 # unsigned number +indent_align_string = true # false/true +indent_class = true # false/true +indent_class_colon = true # false/true +indent_member = 3 # unsigned number +indent_switch_case = 4 # unsigned number +indent_case_brace = 3 # number +nl_assign_leave_one_liners = true # false/true +nl_class_leave_one_liners = true # false/true +nl_start_of_file = remove # ignore/add/remove/force +nl_end_of_file = force # ignore/add/remove/force +nl_end_of_file_min = 1 # unsigned number +nl_assign_brace = add # ignore/add/remove/force +nl_func_var_def_blk = 1 # unsigned number +nl_fcall_brace = add # ignore/add/remove/force +nl_enum_brace = force # ignore/add/remove/force +nl_struct_brace = force # ignore/add/remove/force +nl_union_brace = force # ignore/add/remove/force +nl_if_brace = add # ignore/add/remove/force +nl_brace_else = add # ignore/add/remove/force +nl_else_brace = add # ignore/add/remove/force +nl_getset_brace = force # ignore/add/remove/force +nl_for_brace = add # ignore/add/remove/force +nl_while_brace = add # ignore/add/remove/force +nl_do_brace = add # ignore/add/remove/force +nl_switch_brace = add # ignore/add/remove/force +nl_multi_line_define = true # false/true +nl_before_case = true # false/true +nl_after_case = true # false/true +nl_func_type_name = remove # ignore/add/remove/force +nl_func_proto_type_name = remove # ignore/add/remove/force +nl_func_paren = remove # ignore/add/remove/force +nl_func_def_paren = remove # ignore/add/remove/force +nl_func_decl_start = remove # ignore/add/remove/force +nl_func_def_start = remove # ignore/add/remove/force +nl_func_decl_args = add # ignore/add/remove/force +nl_func_def_args = add # ignore/add/remove/force +nl_func_decl_end = remove # ignore/add/remove/force +nl_func_def_end = remove # ignore/add/remove/force +nl_fdef_brace = add # ignore/add/remove/force +nl_after_semicolon = true # false/true +nl_after_brace_open = true # false/true +nl_after_brace_close = true # false/true +nl_squeeze_ifdef = true # false/true +nl_before_if = force # ignore/add/remove/force +nl_after_if = force # ignore/add/remove/force +nl_before_for = force # ignore/add/remove/force +nl_after_for = force # ignore/add/remove/force +nl_before_while = force # ignore/add/remove/force +nl_after_while = force # ignore/add/remove/force +nl_before_switch = force # ignore/add/remove/force +nl_after_switch = force # ignore/add/remove/force +nl_before_do = force # ignore/add/remove/force +nl_after_do = force # ignore/add/remove/force +nl_max = 4 # unsigned number +nl_after_func_proto_group = 1 # unsigned number +nl_after_func_body_class = 2 # unsigned number +nl_before_block_comment = 2 # unsigned number +eat_blanks_after_open_brace = true # false/true +eat_blanks_before_close_brace = true # false/true +nl_after_return = true # false/true +pos_bool = trail # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force +align_var_def_amp_style = 1 # unsigned number +align_var_def_thresh = 16 # unsigned number +align_assign_thresh = 12 # unsigned number +align_struct_init_span = 3 # unsigned number +align_typedef_gap = 3 # unsigned number +align_typedef_span = 5 # unsigned number +align_typedef_star_style = 1 # unsigned number +align_typedef_amp_style = 1 # unsigned number +align_right_cmt_span = 3 # unsigned number +align_nl_cont = true # false/true +align_pp_define_gap = 4 # unsigned number +align_pp_define_span = 3 # unsigned number +cmt_cpp_to_c = true # false/true +cmt_star_cont = true # false/true +mod_full_brace_do = add # ignore/add/remove/force +mod_full_brace_for = add # ignore/add/remove/force +mod_full_brace_if = add # ignore/add/remove/force +mod_full_brace_while = add # ignore/add/remove/force +mod_full_paren_if_bool = true # false/true +mod_remove_extra_semicolon = true # false/true +mod_add_long_ifdef_endif_comment = 10 # unsigned number +mod_add_long_ifdef_else_comment = 10 # unsigned number +mod_case_brace = remove # ignore/add/remove/force +mod_remove_empty_return = true # false/true +pp_indent = force # ignore/add/remove/force +pp_indent_at_level = true # false/true +pp_indent_count = 4 # unsigned number +pp_space = remove # ignore/add/remove/force +pp_if_indent_code = true # false/true +# option(s) with 'not default' value: 158