diff --git a/.codecheckignore b/.codecheckignore index 62e12b56f4e..c75a49e7bea 100644 --- a/.codecheckignore +++ b/.codecheckignore @@ -26,6 +26,7 @@ ^platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM ^platform/mbed-trace ^platform/randlib +^platform/source/newlib_nano_malloc_workaround.c ^platform/tests/UNITTESTS ^events/tests/UNITTESTS ^rtos/source/TARGET_CORTEX/rtx4 @@ -35,4 +36,3 @@ ^UNITTESTS ^storage/blockdevice/tests/UNITTESTS ^storage/kvstore/tests/UNITTESTS -^drivers/tests/UNITTESTS diff --git a/.github/workflows/basic_checks.yml b/.github/workflows/basic_checks.yml new file mode 100644 index 00000000000..0df1123509d --- /dev/null +++ b/.github/workflows/basic_checks.yml @@ -0,0 +1,269 @@ +# This workflow performs the checks like license check, +# doxygen, unit tests etc. +name: Basic Checks + +on: + pull_request: + workflow_dispatch: + push: + branches: + - master + +jobs: + license-check: + runs-on: ubuntu-latest + container: + image: ghcr.io/armmbed/mbed-os-env:master-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - + name: install dependencies + shell: bash + run: | + pip install -U scancode-toolkit click + + - + name: license check + run: | + set -x + mkdir -p SCANCODE + + git diff --name-only --diff-filter=d origin/${GITHUB_BASE_REF} \ + | ( grep '.\(c\|cpp\|h\|hpp\|py\)$' || true ) + echo $? + git diff --name-only --diff-filter=d origin/${GITHUB_BASE_REF} \ + | ( grep '.\(c\|cpp\|h\|hpp\|py\)$' || true ) \ + | ( grep -v '^tools/test/toolchains/api_test.py' || true ) \ + | while read file; do cp --parents "${file}" SCANCODE; done + ls SCANCODE + scancode -l --json-pp scancode.json SCANCODE + python ./tools/test/ci/scancode-evaluate.py scancode.json || true + cat scancode-evaluate.log + COUNT=$(cat scancode-evaluate.log | grep 'File:' | grep -v 'SPDX' | wc -l) || true + if [ $COUNT = 0 ]; then + echo "License check OK"; + true; + else + echo "License check failed, please review license issues found in files"; + false; + fi + + include-check: + runs-on: ubuntu-latest + container: + image: ghcr.io/armmbed/mbed-os-env:master-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - + name: include check + run: | + # checks mbed.h is not included in MbedOS files except in tests + ! git grep '^#include\s["'"']mbed.h['"'"]$' -- '*.c' '*.h' '*.cpp' '*.hpp' \ + ':!*platform_mbed.h' ':!*TESTS/*' ':!TEST_APPS/' ':!UNITTESTS/' \ + ':!*tests/*' ':!*targets/*' ':!*TARGET_*' ':!*unsupported/*' \ + ':!*events/tests/*' ':!*drivers/tests/*' + + style-check: + runs-on: ubuntu-latest + container: + image: ghcr.io/armmbed/mbed-os-env:master-latest + + steps: + + - name: Checkout repo + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - + name: UTF-8 Check + run: | + # Make sure we're not introducing any text which is not UTF-8 encoded + git diff origin/${GITHUB_BASE_REF} -U0 | ( grep -a '^+' || true ) | ( ! grep -axv '.*' ) + + + - + name: astyle checks + run: | + set -x + git diff --name-only --diff-filter=d origin/${GITHUB_BASE_REF} \ + | ( grep '.*\.\(c\|cpp\|h\|hpp\)$' || true ) \ + | ( grep -v -f .codecheckignore || true ) \ + | while read file; do astyle -n --options=.astylerc "${file}"; done + git diff --exit-code --diff-filter=d --color + + + docs-check: + runs-on: ubuntu-latest + container: + image: ghcr.io/armmbed/mbed-os-env:master-latest + + steps: + + - name: Checkout repo + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - + name: spell checks + run: | + set -x + ./tools/test/ci/doxy-spellchecker/spell.sh drivers .codecheckignore + ./tools/test/ci/doxy-spellchecker/spell.sh platform .codecheckignore + ./tools/test/ci/doxy-spellchecker/spell.sh events .codecheckignore + ./tools/test/ci/doxy-spellchecker/spell.sh rtos .codecheckignore + ./tools/test/ci/doxy-spellchecker/spell.sh connectivity/netsocket .codecheckignore + + - + name: doxygen + run: | + set -x + ccache -s + mkdir BUILD + # Assert that the Doxygen build produced no warnings. + # The strange command below asserts that the Doxygen command had an + # output of zero length + doxygen doxyfile_options 2>&1 + # Once Mbed OS has been fixed, enable the full test by replacing the top line with this: + # - ( ! doxygen doxyfile_options 2>&1 | grep . ) + # Assert that all binary libraries are named correctly + # The strange command below asserts that there are exactly 0 libraries + # that do not start with lib + find "(" -name "*.a" -or -name "*.ar" ")" -and -not -name "lib*" | + tee BUILD/badlibs | + sed -e "s/^/Bad library name found: /" && [ ! -s BUILD/badlibs ] + # Assert that all assembler files are named correctly + # The strange command below asserts that there are exactly 0 libraries + # that do end with .s + find -name "*.s" | tee BUILD/badasm | + sed -e "s/^/Bad Assembler file name found: /" && [ ! -s BUILD/badasm ] + + python-tests: + # these tests run in 3.7, hence running in vm not in pre-built docker + runs-on: ubuntu-latest + steps: + - + name: Checkout repo + uses: actions/checkout@v2 + + + - uses: actions/setup-python@v2 + with: + python-version: '3.7' + + - + name: install dependencies + run: | + pip install -r requirements.txt + pip install mock==2.0.0 attrs==19.1.0 pytest==3.3.0 'pylint>=1.9,<2' 'hypothesis>=3,<4' 'coverage>=4.5,<5' + + - + name: pytest + run: | + set -x + coverage run -a -m pytest tools/test + python tools/test/pylint.py + coverage run -a tools/project.py -S | sed -n '/^Total/p' + coverage html + + pin-validation: + runs-on: ubuntu-latest + container: + image: ghcr.io/armmbed/mbed-os-env:master-latest + steps: + - + name: Checkout repo + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - + name: validate pins + run: | + set -x + git diff --name-only --diff-filter=d origin/${GITHUB_BASE_REF} \ + | ( grep '.*[\\|\/]PinNames.h$' || true ) \ + | while read file; do python ./hal/tests/pinvalidate/pinvalidate.py -vvvfp "${file}"; done + git diff --exit-code --diff-filter=d --color + + cmake-checks: + env: + NAME: mbed-test-mode-check + ROOT: tools/cmake/tests/mbed_test_mode/ + TOOLCHAIN: GCC_ARM + TARGET_NAME: K64F + PROFILE: develop + runs-on: ubuntu-latest + container: + image: ghcr.io/armmbed/mbed-os-env:master-latest + steps: + - + name: Checkout repo + uses: actions/checkout@v2 + + - + name: cmake build + run: | + set -x + mbedtools configure -p ${{ env.ROOT}} -t ${{ env.TOOLCHAIN }} -m ${{ env.TARGET_NAME }} --mbed-os-path . + cmake -S ${{env.ROOT}} -B ${{ env.ROOT }}/cmake_build/${{env.TARGET_NAME}}/${{ env.PROFILE }}/${{ env.TOOLCHAIN }}/ -GNinja -DCMAKE_BUILD_TYPE=${{ env.PROFILE }} + cmake --build ${{ env.ROOT }}/cmake_build/${{ env.TARGET_NAME }}/${{ env.PROFILE }}/${{ env.TOOLCHAIN }}/ + + - + name: cmake unittest + run: | + set -x + ctest --build-and-test . build --build-generator Ninja --build-options -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DCOVERAGE=ON --test-command ctest + gcovr --gcov-executable gcov -r . ./build -s -e ".*\.h" --exclude-directories=${GITHUB_WORKSPACE}/build/UNITTESTS --exclude-directories=${GITHUB_WORKSPACE}/build/_deps + ccache -s + + # Reject any changes to tools that would require a re-release of the + # tools for the online compiler. + frozen-tools-check: + runs-on: ubuntu-latest + container: + image: ghcr.io/armmbed/mbed-os-env:master-latest + steps: + - + name: Checkout repo + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - + name: frozen tool check + run: | + set -x + git diff --name-only origin/${GITHUB_BASE_REF} \ + | egrep \ + -e "^tools/build_api*" \ + -e "^tools/config*" \ + -e "^tools/export*" \ + -e "^tools/notifier*" \ + -e "^tools/paths*" \ + -e "^tools/resources*" \ + -e "^tools/targets*" \ + -e "^tools/toolchains*" \ + -e "^tools/utils*" \ + -e "^$" > output.log | true + frozen_files=`cat output.log` + + if [ -z "$frozen_files" ]; then + echo "Success!"; + else + echo -e "Failure: Frozen files were modified\n$frozen_files"; + echo -e "Please see https://os.mbed.com/blog/entry/Introducing-the-new-Mbed-Tools/" \ + "\nfor why we've frozen the legacy tools."; + false; + fi diff --git a/.github/workflows/ci_scripts/ghcr_utils.py b/.github/workflows/ci_scripts/ghcr_utils.py new file mode 100644 index 00000000000..b80eb6fc4d8 --- /dev/null +++ b/.github/workflows/ci_scripts/ghcr_utils.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2017-2021 ARM Limited. All rights reserved. +SPDX-License-Identifier: Apache-2.0 +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations +""" +import click +import requests +import logging +import sys +import time +import json +import subprocess + +""" +This file contains ghcr utlity wrapper used for: +- retrieving digest of docker image +- deleting images in ghcr +""" + + +@click.command() +@click.pass_context +@click.option("-r", "--repository", required=True) +@click.option("-t", "--tag", required=True) +@click.option("-p", "--platform", required=False) +def get_digest(ctx, repository, tag, platform=None): + """ + Prints docker digest of specific platform of multi architecture image + :param ctx: click context + :param repository: docker repository + :param tag: docker tag + :param platform: platform for e.g, linux/arm64 + """ + command = f"docker run quay.io/skopeo/stable:v1.4.1 inspect --creds={ctx.obj['username']}:{ctx.obj['passwd']} docker://ghcr.io/{ctx.obj['username']}/{repository}:{tag} --raw" + output = subprocess.run( + command.split(), stdout=subprocess.PIPE, check=True + ).stdout.decode("utf-8") + output = json.loads(output) + + images = output["manifests"] + digest = "" + if len(images) and platform is None: + logging.error( + "This tag has more than one platform associated to it, please input a platform" + ) + sys.exit(1) + + for image in images: + if platform != None: + if (platform.split("/")[0] == image["platform"]["os"]) and ( + platform.split("/")[1] == image["platform"]["architecture"] + ): + digest = image["digest"] + else: + digest = image["digest"] + + if digest == "": + logging.error("Digest not found. image not in repo for the given platform") + sys.exit(1) + + print(digest) + + +@click.command() +@click.pass_context +@click.option("-r", "--repository", required=True) +@click.option( + "-n", + "--number_of_days", + default="10", + help="number of days since image was created", + required=False, +) +def delete_old_images(ctx, repository, number_of_days): + """ + delete old images from docker repository + + :param ctx: click context + :param repository: docker repository + :param number_of_days: delete older than these number of days + """ + with requests.Session() as s: + github_api_accept = "application/vnd.github.v3+json" + s.headers.update( + {"Authorization": f'token {ctx.obj["passwd"]}', "Accept": github_api_accept} + ) + r = s.get( + f"https://api.github.com/user/packages/container/{repository}/versions" + ) + versions = r.json() + version_id = None + pattern = "%d.%m.%Y %H:%M:%S" + pattern = "%Y-%m-%dT%H:%M:%SZ" + current_time = time.time() + for version in versions: + logging.info(version) + epoch = int(time.mktime(time.strptime(version["updated_at"], pattern))) + + if (current_time - epoch) / (24 * 60 * 60) > int(number_of_days): + version_id = version["id"] + logging.debug(f"deleteing image with version id {version_id}") + + url = f"https://api.github.com/user/packages/container/{repository}/versions/{version_id}" + resp = s.delete(url) + resp.raise_for_status() + + +@click.group() +@click.pass_context +@click.option("-u", "--username", required=False) +@click.option("-p", "--passwd", required=False) +@click.option("-v", "--verbose", is_flag=True, default=False) +def main(ctx, username, passwd, verbose): + ctx.obj = {"username": username, "passwd": passwd} + + if verbose: + logging.basicConfig( + stream=sys.stdout, + format="%(levelname)s %(asctime)s %(message)s", + datefmt="%m/%d/%Y %I:%M:%S %p", + ) + logging.getLogger().setLevel(logging.DEBUG) + else: + logging.basicConfig( + format="%(levelname)s %(asctime)s %(message)s", + datefmt="%m/%d/%Y %I:%M:%S %p", + ) + logging.getLogger().setLevel(logging.INFO) + + +if __name__ == "__main__": + main.add_command(get_digest) + main.add_command(delete_old_images) + main() diff --git a/.github/workflows/docker_management.branch.yml b/.github/workflows/docker_management.branch.yml new file mode 100644 index 00000000000..45881b27a3d --- /dev/null +++ b/.github/workflows/docker_management.branch.yml @@ -0,0 +1,245 @@ +name: Publish or Update docker image for head of branch +# Design details in https://github.com/ARMmbed/mbed-os/blob/master/docs/design-documents/docker_management + +on: + + # passive update once a week + schedule: + - cron: '15 4 * * 6' + + # build on master branch when there is changes for active update + push: + branches: + - master + + paths: + - requirements.txt + - docker_images/mbed-os-env/** + - .github/workflows/docker_management.branch.yml + + + # manual trigger when needed + workflow_dispatch: + + +jobs: + prepare-tags: + runs-on: ubuntu-latest + + steps: + - + name: Extract branch name + shell: bash + run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})" + id: extract_branch + + - + name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - + name: Set UUID + id: generate-uuid + uses: filipstefansson/uuid-action@v1 + +# set docker tags we are building, and intending to publish +# dev-tag is temporary for testing purpose. This should be considered as unstable. +# dated-tag is created for versioning purpose +# prod-tag-latest could be used by customers, CI etc for keeping up to date + - + name: Get build information + shell: bash + run: | + mkdir -p build_info + date=$(date +"%Y.%m.%dT%H.%M.%S") + echo dev-${{ steps.extract_branch.outputs.branch }}-${date}-${{ steps.generate-uuid.outputs.uuid }} > build_info/dev_tag + echo ${{ steps.extract_branch.outputs.branch }}-${date} > build_info/prod_tag_dated + echo ${{ steps.extract_branch.outputs.branch }}-latest > build_info/prod_tag_latest + echo ${{ steps.extract_branch.outputs.branch }} > build_info/mbed_os_version + echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]' > build_info/repository_owner + + - + name: Archive information + uses: actions/upload-artifact@v2 + with: + name: build-info + path: build_info + + + build-container: + runs-on: ubuntu-latest + needs: prepare-tags + outputs: + DEV_DIGEST: ${{ steps.docker_info_dev.outputs.DIGEST }} + PROD_DIGEST: ${{ steps.docker_info_prod.outputs.DIGEST }} + + steps: + - + name: unarchive artefacts + uses: actions/download-artifact@v2 + with: + name: build-info + + - + name: Get build info from archive + shell: bash + id: build_info + run: | + value=`cat dev_tag` + echo "DEV TAG is $value" + echo "::set-output name=DOCKER_DEV_TAG::$value" + value=`cat prod_tag_dated` + echo "PROD TAG DATED is $value" + echo "::set-output name=DOCKER_PROD_TAG_DATED::$value" + value=`cat prod_tag_latest` + echo "::set-output name=DOCKER_PROD_TAG_LATEST::$value" + echo "PROD TAG is $value" + value=`cat repository_owner` + echo "::set-output name=REPO_OWNER::$value" + + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - + name: Login to ghcr.io + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - + name: Checkout + uses: actions/checkout@v2 + + - + name: Build docker containers + uses: docker/build-push-action@v2 + id: docker_build_dev + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + file: ./docker_images/mbed-os-env/Dockerfile + tags: ghcr.io/${{ steps.build_info.outputs.REPO_OWNER }}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} + + test-container: + runs-on: ubuntu-latest + needs: build-container + strategy: + matrix: + platform: [linux/amd64, linux/arm64] + + steps: + - + name: unarchive artefacts + uses: actions/download-artifact@v2 + with: + name: build-info + + - + name: Get build info from archive + shell: bash + id: build_info + run: | + value=`cat dev_tag` + echo "TAG is $value" + echo "::set-output name=DOCKER_DEV_TAG::$value" + value=`cat prod_tag_dated` + echo "TAG is $value" + echo "::set-output name=DOCKER_PROD_TAG_DATED::$value" + value=`cat prod_tag_latest` + echo "::set-output name=DOCKER_PROD_TAG_LATEST::$value" + value=`cat mbed_os_version` + echo "::set-output name=MBED_OS_VERSION::$value" + value=`cat repository_owner` + echo "::set-output name=REPO_OWNER::$value" + + - + name: Checkout + uses: actions/checkout@v2 + + - + name: Find DEV DOCKER DIGEST + id: docker_info_dev + run: | + DIGEST=$(python ./.github/workflows/ci_scripts/ghcr_utils.py -u ${{ steps.build_info.outputs.REPO_OWNER }} -p ${{ secrets.GITHUB_TOKEN }} get-digest -r mbed-os-env-tmp -t ${{ steps.build_info.outputs.DOCKER_DEV_TAG }} -p ${{ matrix.platform }} ) + echo "::set-output name=DIGEST::$DIGEST" + echo "Docker DIGEST: $DIGEST" + + # as the dev images are created only for master branch, run test against + # development branch of blinky + - + name: Checkout + uses: actions/checkout@v2 + with: + repository: ARMmbed/mbed-os-example-blinky + path: mbed-os-example-blinky + ref: development + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - + name: test the container + id: test + uses: addnab/docker-run-action@v3 + with: + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + registry: ghcr.io + options: -v ${{ github.workspace }}:/work -w=/work + image: ghcr.io/${{ steps.build_info.outputs.REPO_OWNER }}/mbed-os-env-tmp@${{ steps.docker_info_dev.outputs.DIGEST }} + shell: bash + + run: | + uname -m + cd mbed-os-example-blinky + mbed deploy + # build using CLI1 + mbed compile -m K64F -t GCC_ARM + + # build using CLI2 + mbed-tools compile -m K64F -t GCC_ARM + + + deploy-container: + runs-on: ubuntu-latest + needs: test-container + + steps: + - + name: unarchive artefacts + uses: actions/download-artifact@v2 + with: + name: build-info + + - + name: Get build info from archive + shell: bash + id: build_info + run: | + value=`cat dev_tag` + echo "TAG is $value" + echo "::set-output name=DOCKER_DEV_TAG::$value" + value=`cat prod_tag_dated` + echo "TAG is $value" + echo "::set-output name=DOCKER_PROD_TAG_DATED::$value" + value=`cat prod_tag_latest` + echo "::set-output name=DOCKER_PROD_TAG_LATEST::$value" + value=`cat repository_owner` + echo "::set-output name=REPO_OWNER::$value" + + - + name: copy dev tag to prod + run: | + docker run quay.io/skopeo/stable:v1.4.1 copy --src-creds=${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }} --dest-creds=${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }} --all docker://ghcr.io/${{ steps.build_info.outputs.REPO_OWNER }}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} docker://ghcr.io/${{ steps.build_info.outputs.REPO_OWNER }}/mbed-os-env:latest + docker run quay.io/skopeo/stable:v1.4.1 copy --src-creds=${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }} --dest-creds=${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }} --all docker://ghcr.io/${{ steps.build_info.outputs.REPO_OWNER }}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} docker://ghcr.io/${{ steps.build_info.outputs.REPO_OWNER }}/mbed-os-env:${{ steps.build_info.outputs.DOCKER_PROD_TAG_LATEST }} + docker run quay.io/skopeo/stable:v1.4.1 copy --src-creds=${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }} --dest-creds=${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }} --all docker://ghcr.io/${{ steps.build_info.outputs.REPO_OWNER }}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} docker://ghcr.io/${{ steps.build_info.outputs.REPO_OWNER }}/mbed-os-env:${{ steps.build_info.outputs.DOCKER_PROD_TAG_DATED }} diff --git a/.github/workflows/docker_management.prune.yml b/.github/workflows/docker_management.prune.yml new file mode 100644 index 00000000000..56814e0752f --- /dev/null +++ b/.github/workflows/docker_management.prune.yml @@ -0,0 +1,25 @@ +name: Prune temporary docker images + +on: + schedule: + - cron: '15 4 * * 6' + + workflow_dispatch: + +jobs: + prune-images: + runs-on: ubuntu-latest + + steps: + - + name: Checkout + uses: actions/checkout@v2 + + - + name: Delete old temporary images + run: | + # the following command may fail because github package doesn't allow + # deletion if only one image exists or if DOCKER_MANAGEMENT_TOKEN is not + # setup. This shouldn't create any alarm as temporary image deletion is + # not a critical activity. + python ./.github/workflows/ci_scripts/ghcr_utils.py -u ${{ github.repository_owner }} -p ${{ secrets.DOCKER_MANAGEMENT_TOKEN }} delete-old-images -r mbed-os-env-tmp || true \ No newline at end of file diff --git a/.github/workflows/docker_management.release.yml b/.github/workflows/docker_management.release.yml new file mode 100644 index 00000000000..809ac868b89 --- /dev/null +++ b/.github/workflows/docker_management.release.yml @@ -0,0 +1,307 @@ +name: Release or update docker image for a released mbed-os version + +# Design doc: https://github.com/ARMmbed/mbed-os/blob/master/docs/design-documents/docker_management + +on: + push: + tags: + - mbed-os-6.[0-9]+.[0-9]+ + + schedule: + - cron: '15 4 * * 6' + + workflow_dispatch: + inputs: + mbed_os_release_version: + description: 'mbed-os release version for which you want to update docker image.' + required: true + +jobs: + # this job finds the necessary tags to be applied to docker image + prepare-tags: + runs-on: ubuntu-latest + + steps: + - + name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - + # if manually triggered makes sure that input tag exists on the branch selected + # this is to avoid silly mistakes, for example: mbed-os-7.0.16-latest docker image + # getting released on mbed-os-6 branch + if: ${{ github.event_name == 'workflow_dispatch' }} + name: Sanity check tag of manual trigger + shell: bash + run: | + if [ -z $(git tag --merged ${GITHUB_REF} ${{ github.event.inputs.mbed_os_release_version }}) ]; then + echo "Check the tag name ${{ github.event.inputs.mbed_os_release_version }} is not found on branch ${GITHUB_REF}" + exit 1 + fi + + - + name: Set UUID + id: generate-uuid + uses: filipstefansson/uuid-action@v1 + + - + # set docker tags we are building, and intending to release + # this workflow can be executed when a tag is pushed, scheduled, or manual trigger + # depending on the trigger cache source and version of mbed-os will change + # + # when trigger is due to tag pushed (ie, a new mbed-os release is made), + # we are targeting to build docker image for the tag + # when trigger is manual + # we are targeting to build docker image for the input tag in workflow + # when trigger is scheduled + # we are targeting to build docker image for the last tag on the branch + name: Get build information + shell: bash + run: | + mkdir -p build_info + date=$(date +"%Y.%m.%dT%H.%M.%S") + if [ "push" == "${{github.event_name}}" ];then + version=${GITHUB_REF#refs/tags/} + elif [ "workflow_dispatch" == "${{github.event_name}}" ];then + version=${{ github.event.inputs.mbed_os_release_version }} + else + version=`git describe --tags --abbrev=0 --match mbed-os-[0-9]*.[0-9]*.[0-9]*` + fi + echo dev-${version}-${date}-${version} > build_info/dev_tag + echo ${version}-${date} > build_info/prod_tag_dated + echo ${version} > build_info/mbed_os_version + echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]' > build_info/repository_owner + + - + name: Archive information + uses: actions/upload-artifact@v2 + with: + name: build-info + path: build_info + + + build-container: + runs-on: ubuntu-latest + needs: prepare-tags + outputs: + DEV_DIGEST: ${{ steps.docker_info_dev.outputs.DIGEST }} + PROD_DIGEST: ${{ steps.docker_info_prod.outputs.DIGEST }} + REPO_FILE_CHECK: ${{steps.repo_status.outcome}} + + steps: + - + name: unarchive artefacts + uses: actions/download-artifact@v2 + with: + name: build-info + + # DOCKER_DEV_TAG is temporary image name. + # DOCKER_PROD_TAG_DATED is fixed tag + # prod-tag-latest could be used by customers, CI etc for keeping up to date + - + name: Get build info from archive + shell: bash + id: build_info + run: | + value=`cat dev_tag` + echo "TAG is $value" + echo "::set-output name=DOCKER_DEV_TAG::$value" + value=`cat prod_tag_dated` + echo "TAG is $value" + echo "::set-output name=DOCKER_PROD_TAG_DATED::$value" + value=`cat mbed_os_version` + echo "::set-output name=MBED_OS_VERSION::$value" + value=`cat repository_owner` + echo "::set-output name=REPO_OWNER::$value" + + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - + name: Login to ghcr.io + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - + name: Checkout + uses: actions/checkout@v2 + with: + ref: refs/tags/${{ steps.build_info.outputs.MBED_OS_VERSION }} + + # if we are trying to build docker image for an earlier version of mbed-os, either scheduled + # or manually, dockerfile will not exist. Then, skip the workflow + - + name: Skip the workflow if Dockerfile doesn't exist + id: repo_status + run: | + if [ ! -f "./docker_images/mbed-os-env/Dockerfile" ]; then + echo "Dockerfile doesn't in this repo." + exit 1 + fi + continue-on-error: true + + - + name: Build docker containers + if: steps.repo_status.outcome == 'success' + uses: docker/build-push-action@v2 + id: docker_build_dev + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + file: ./docker_images/mbed-os-env/Dockerfile + tags: ghcr.io/${{ steps.build_info.outputs.REPO_OWNER }}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} + + + test-container: + runs-on: ubuntu-latest + needs: build-container + if: needs.build-container.outputs.REPO_FILE_CHECK=='success' + strategy: + matrix: + platform: [linux/amd64, linux/arm64] + + steps: + - + name: unarchive artefacts + uses: actions/download-artifact@v2 + with: + name: build-info + + - + name: Get build info from archive + shell: bash + id: build_info + run: | + value=`cat dev_tag` + echo "TAG is $value" + echo "::set-output name=DOCKER_DEV_TAG::$value" + value=`cat prod_tag_dated` + echo "TAG is $value" + echo "::set-output name=DOCKER_PROD_TAG_DATED::$value" + value=`cat mbed_os_version` + echo "::set-output name=MBED_OS_VERSION::$value" + value=`cat repository_owner` + echo "::set-output name=REPO_OWNER::$value" + + # as the dev images are created only for master branch, run test against + # development branch of blinky + - + name: Checkout example blinky + uses: actions/checkout@v2 + with: + repository: ARMmbed/mbed-os-example-blinky + path: mbed-os-example-blinky + fetch-depth: 0 + + + - + name: update the example application version to test against correct version + # When mbed-os tag is applied, and workflow is triggered to build RELEASE image, example application with same tag will be available yet. + # use release candidate branch to test the image in that case. + # When RELEASE image is passively checked, tag should be available in example application repo, then use it. + shell: bash + id: example_app_info + run: | + cd mbed-os-example-blinky + EXAMPLE_VERSION="release_candidate" + MBED_OS_VERSION=${{ steps.build_info.outputs.MBED_OS_VERSION }} + # if tag is present in example repo, use the tag + if git rev-parse "$MBED_OS_VERSION" >/dev/null 2>&1; then + EXAMPLE_VERSION=$MBED_OS_VERSION + fi + git checkout ${EXAMPLE_VERSION} + + - + name: Checkout + uses: actions/checkout@v2 + with: + ref: refs/tags/${{ steps.build_info.outputs.MBED_OS_VERSION }} + path: mbed-os-example-blinky/mbed-os + + - + name: Find DEV DOCKER DIGEST + id: docker_info + run: | + cd mbed-os-example-blinky/mbed-os + DIGEST=$(python ./.github/workflows/ci_scripts/ghcr_utils.py -u ${{ steps.build_info.outputs.REPO_OWNER }} -p ${{ secrets.GITHUB_TOKEN }} get-digest -r mbed-os-env-tmp -t ${{ steps.build_info.outputs.DOCKER_DEV_TAG }} -p ${{ matrix.platform }} ) + echo "::set-output name=DIGEST::$DIGEST" + echo "Docker DIGEST: $DIGEST" + + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - + name: test the container + id: test + uses: addnab/docker-run-action@v3 + with: + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + registry: ghcr.io + options: -v ${{ github.workspace }}:/work -w=/work + image: ghcr.io/${{ steps.build_info.outputs.REPO_OWNER }}/mbed-os-env-tmp@${{ steps.docker_info.outputs.DIGEST }} + shell: bash + run: | + uname -m + cd mbed-os-example-blinky + # build using CLI1 + mbed compile -m K64F -t GCC_ARM + + # build using CLI2 + mbed-tools compile -m K64F -t GCC_ARM + + + deploy-container: + runs-on: ubuntu-latest + needs: test-container + steps: + - + name: unarchive artefacts + uses: actions/download-artifact@v2 + with: + name: build-info + + - + name: Get build info from archive + shell: bash + id: build_info + run: | + value=`cat dev_tag` + echo "DEV TAG is $value" + echo "::set-output name=DOCKER_DEV_TAG::$value" + value=`cat prod_tag_dated` + echo "DATED PROD TAG is $value" + echo "::set-output name=DOCKER_PROD_TAG_DATED::$value" + value=`cat mbed_os_version` + echo "MBED OS VERSION is $value" + echo "::set-output name=MBED_OS_VERSION::$value" + value=`cat repository_owner` + echo "::set-output name=REPO_OWNER::$value" + + - + name: copy dev tag to prod tags + run: | + set -x + echo ${{ needs.test-container.result }} + REPO_OWNER=${{ steps.build_info.outputs.REPO_OWNER }} + upto_patch_version=${{ steps.build_info.outputs.MBED_OS_VERSION }}-latest + upto_min_version=${upto_patch_version%.[0-9]*}-latest + upto_major_version=${upto_patch_version%.[0-9]*.[0-9]*}-latest + docker run quay.io/skopeo/stable:v1.4.1 copy --src-creds=${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }} --dest-creds=${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }} --all docker://ghcr.io/${REPO_OWNER}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} docker://ghcr.io/${REPO_OWNER}/mbed-os-env:${upto_patch_version} + docker run quay.io/skopeo/stable:v1.4.1 copy --src-creds=${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }} --dest-creds=${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }} --all docker://ghcr.io/${REPO_OWNER}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} docker://ghcr.io/${REPO_OWNER}/mbed-os-env:${upto_min_version} + docker run quay.io/skopeo/stable:v1.4.1 copy --src-creds=${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }} --dest-creds=${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }} --all docker://ghcr.io/${REPO_OWNER}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} docker://ghcr.io/${REPO_OWNER}/mbed-os-env:${upto_major_version} + + # copy to fixed tag + docker run quay.io/skopeo/stable:v1.4.1 copy --src-creds=${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }} --dest-creds=${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }} --all docker://ghcr.io/${REPO_OWNER}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} docker://ghcr.io/${REPO_OWNER}/mbed-os-env:${{ steps.build_info.outputs.DOCKER_PROD_TAG_DATED }} diff --git a/.github/workflows/docker_management.test-PR.yml b/.github/workflows/docker_management.test-PR.yml new file mode 100644 index 00000000000..d41391a6db6 --- /dev/null +++ b/.github/workflows/docker_management.test-PR.yml @@ -0,0 +1,82 @@ +name: Build docker image + +# This workflow is triggered when Dockerfile related or github action itself changes are made in a PR +# The workflow is quite simple - builds and test the image. Release of newer version is done only when PR is merged. +# Design doc: https://github.com/ARMmbed/mbed-os/blob/master/docs/design-documents/docker_management + +on: + pull_request: + branches: [ master ] + paths: + - docker_images/mbed-os-env/** + - .github/workflows/docker_management.* + - requirements.txt + +jobs: + + build-container: + runs-on: ubuntu-latest + + strategy: + matrix: + platform: [linux/amd64, linux/arm64] + + steps: + + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + # for PR tests, development branch of blinky is used + - + name: Checkout + uses: actions/checkout@v2 + with: + repository: ARMmbed/mbed-os-example-blinky + path: mbed-os-example-blinky + ref: development + + - + name: Remove mbed-os from example-application + shell: bash + run: | + cd mbed-os-example-blinky + rm -rf mbed-os + + - + name: Checkout + uses: actions/checkout@v2 + with: + path: mbed-os-example-blinky/mbed-os + + - + name: Build container + uses: docker/build-push-action@v2 + id: docker_build_dev + with: + context: ./mbed-os-example-blinky/mbed-os + platforms: ${{ matrix.platform }} + file: ./mbed-os-example-blinky/mbed-os/docker_images/mbed-os-env/Dockerfile + load: true + tags: mbed-os-env:a_pr_test + + - + name: test the container + id: test + uses: addnab/docker-run-action@v2 + with: + options: -v ${{ github.workspace }}:/work -w=/work + image: mbed-os-env:a_pr_test + shell: bash + run: | + uname -m + cd mbed-os-example-blinky + # build using CLI1 + mbed compile -m K64F -t GCC_ARM + + # build using CLI2 + mbed-tools compile -m K64F -t GCC_ARM diff --git a/.github/workflows/greentea_cmake.yml b/.github/workflows/greentea_cmake.yml new file mode 100644 index 00000000000..f98921a196c --- /dev/null +++ b/.github/workflows/greentea_cmake.yml @@ -0,0 +1,30 @@ +name: test building greentea tests with cmake + +on: [pull_request] + +jobs: + build-greentea-cmake: + runs-on: ubuntu-latest + container: ghcr.io/armmbed/mbed-os-env:master-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install the latest mbed-tools + run: | + pip3 install --upgrade mbed-tools + mbedtools --version + + - name: Build NUCLEO_G031K8 with baremetal profile + run: | + rm -rf __build + mbedtools configure -t GCC_ARM -m NUCLEO_G031K8 --mbed-os-path . --output-dir __build --app-config TESTS/configs/baremetal.json + cmake -S . -B __build -GNinja -DCMAKE_CTEST_ARGUMENTS="--output-on-failure;-V" -DBUILD_GREENTEA_TESTS=ON -DMBED_GREENTEA_TEST_BAREMETAL=ON + cmake --build __build + + - name: Build ARM_MUSCA_S1 with full profile + run: | + rm -rf __build + mbedtools configure -t GCC_ARM -m ARM_MUSCA_S1 --mbed-os-path . --output-dir __build + cmake -S . -B __build -GNinja -DCMAKE_CTEST_ARGUMENTS="--output-on-failure;-V" -DBUILD_GREENTEA_TESTS=ON + cmake --build __build diff --git a/.github/workflows/run_conditional_ble_feature_compilation.yml b/.github/workflows/run_conditional_ble_feature_compilation.yml new file mode 100644 index 00000000000..e93a01fb838 --- /dev/null +++ b/.github/workflows/run_conditional_ble_feature_compilation.yml @@ -0,0 +1,29 @@ +name: run conditional BLE feature compilation +on: + workflow_dispatch: + pull_request: + paths: + - 'connectivity/FEATURE_BLE/**' +jobs: + run-conditional-feature-compilation-test: + name: Conditional BLE features compilation tested + runs-on: ubuntu-latest + container: mbedos/mbed-os-env:latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + path: mbed-os + + - name: Build + run: | + git clone https://github.com/ARMmbed/mbed-os-example-ble.git + cd mbed-os-example-ble/BLE_SupportedFeatures + ln -s ../../mbed-os mbed-os + for f in ../resources/test_configs/*; do + echo "Configuration file ${f}: " + echo "-------------------------------------------------------------------------" + cat "${f}" + echo "-------------------------------------------------------------------------" + mbed compile -t GCC_ARM -m NRF52840_DK --app-config "${f}" + done diff --git a/.github/workflows/test_building_multiple_executables.yml b/.github/workflows/test_building_multiple_executables.yml new file mode 100644 index 00000000000..09d3a5abd81 --- /dev/null +++ b/.github/workflows/test_building_multiple_executables.yml @@ -0,0 +1,28 @@ +name: test building multiple executables with CMake + +on: [pull_request] + +jobs: + multiple-executables-example: + runs-on: ubuntu-latest + container: ghcr.io/armmbed/mbed-os-env:master-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Build the multiple_executables example + run: | + mbedtools compile \ + -t GCC_ARM \ + -m ARM_MUSCA_S1 \ + --program-path tools/cmake/tests/multiple_executables/ \ + --mbed-os-path . + + - name: Verify the post-build command has run successfully on each image + run: | + APP1=tools/cmake/tests/multiple_executables/cmake_build/ARM_MUSCA_S1/develop/GCC_ARM/app1/app1.bin + APP2=tools/cmake/tests/multiple_executables/cmake_build/ARM_MUSCA_S1/develop/GCC_ARM/app2/app2.bin + BOOTLOADER=targets/TARGET_ARM_SSG/TARGET_MUSCA_S1/bl2.bin + BOOTLOADER_SIZE=`du -b targets/TARGET_ARM_SSG/TARGET_MUSCA_S1/bl2.bin | cut -f1` + cmp -n $BOOTLOADER_SIZE $APP1 $BOOTLOADER + cmp -n $BOOTLOADER_SIZE $APP2 $BOOTLOADER diff --git a/.mergify.yml b/.mergify.yml index 41edcccd68b..0062487842b 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -35,10 +35,17 @@ pull_request_rules: remove: ['needs: review', 'needs: CI'] # From needs: review to needs: work - CI failure - - name: "label needs: work when travis-ci failed" + - name: "label needs: work when GitHub Actions jobs have failed" conditions: - # Travis failing - - status-failure~=Travis CI - Pull Request + # GitHub Actions are failing + - check-failure=license-check + - check-failure=include-check + - check-failure=style-check + - check-failure=docs-check + - check-failure=python-tests + - check-failure=pin-validation + - check-failure=cmake-checks + - check-failure=frozen-tools-check - "label!=mergify skip" actions: label: @@ -49,7 +56,7 @@ pull_request_rules: - name: "label needs: work when Jenkins CI failed - pr head" conditions: # Jenkins CI failing - - status-failure~=continuous-integration/jenkins/pr-head + - check-failure~=continuous-integration/jenkins/pr-head - "label!=mergify skip" actions: label: @@ -60,7 +67,7 @@ pull_request_rules: - name: "label needs: work when Jenkins CI failed - any of the pipeline" conditions: # Jenkins CI failing - any of the pipeline - - status-failure~=^jenkins-ci + - check-failure~=^jenkins-ci - "label!=mergify skip" actions: label: @@ -80,11 +87,18 @@ pull_request_rules: # No conflict with the base branch - -conflict - # CI green policy, at least Travis should be green - - status-success~=Travis CI - Pull Request + # CI green policy, at least GitHub Actions jobs should be green + - check-success=license-check + - check-success=include-check + - check-success=style-check + - check-success=docs-check + - check-success=python-tests + - check-success=pin-validation + - check-success=cmake-checks + - check-success=frozen-tools-check # new CI needs to be done (neutral does not work, lets check if it failed or passed, if none, we need to run again) - - -status-success~=continuous-integration/jenkins/pr-head - - -status-failure~=continuous-integration/jenkins/pr-head + - -check-success~=continuous-integration/jenkins/pr-head + - -check-failure~=continuous-integration/jenkins/pr-head actions: label: add: ['needs: CI'] @@ -132,11 +146,19 @@ pull_request_rules: - "#changes-requested-reviews-by=0" # CI green policy - - status-success~=Travis CI - Pull Request + - check-success=license-check + - check-success=include-check + - check-success=style-check + - check-success=docs-check + - check-success=python-tests + - check-success=pin-validation + - check-success=cmake-checks + - check-success=frozen-tools-check + # Internal Jenkins - we rely on PR head to provide status - - status-success~=continuous-integration/jenkins/pr-head + - check-success~=continuous-integration/jenkins/pr-head # any of the jenkins pipeline needs to be green. We rely on not failure means all good (if skipped or executed) - - -status-failure~=^jenkins-ci + - -check-failure~=^jenkins-ci actions: label: add: ['ready for merge'] diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 30f38ab7e3b..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,341 +0,0 @@ -# Copyright (c) 2013-2019 Arm Limited. All rights reserved. -# -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -language: sh -os: linux -dist: focal - - -env: - global: - - deps_url="https://mbed-os-ci-public.s3-eu-west-1.amazonaws.com/jenkins-ci/deps" - - deps_dir="${HOME}/.cache/deps" - -cache: - pip: true - ccache: true - directories: - - ${HOME}/.cache/deps - -before_install: - - source tools/test/travis-ci/functions.sh - -addons: - apt: - sources: - - sourceline: 'deb https://apt.kitware.com/ubuntu/ focal main' - key_url: 'https://apt.kitware.com/keys/kitware-archive-latest.asc' - packages: - - cmake - - ninja-build - - gcovr - - libncursesw5 - - g++-7 - -matrix: - include: - - ### Basic Tests ### - - &basic-vm - stage: "Basic" - name: "file attributes" - env: NAME=gitattributestest - script: - - git diff --exit-code - - - <<: *basic-vm - name: "license check" - env: NAME=licence_check - language: python - python: 3.6.8 # scancode-toolkit v3.1.1 requires v3.6.8 - install: - # workaround for https://github.com/ARMmbed/mbed-os/issues/13322 - - pip install pdfminer.six==20200517 - - pip install scancode-toolkit==3.1.1 - before_script: - - mkdir -p SCANCODE - - mkdir -p SCANCODE_NEW_FILES - # Fetch the base branch to compare against - - git fetch origin "${TRAVIS_BRANCH}" --depth=1 - script: - # scancode does not support list of files, only one file or directory - # we use SCANCODE directory for all changed files (their copies with full tree) - - >- - git diff --name-only --diff-filter=ad FETCH_HEAD..HEAD \ - | ( grep '.\(c\|cpp\|h\|hpp\|py\)$' || true ) \ - | ( grep -v '^tools/test/toolchains/api_test.py' || true ) \ - | while read file; do cp --parents "${file}" SCANCODE; done - - scancode -l --json-pp scancode.json SCANCODE - - python ./tools/test/travis-ci/scancode-evaluate.py scancode.json || true - # run the same but for new files. All new files must have SPDX - - >- - git diff --name-only --diff-filter=A FETCH_HEAD..HEAD \ - | ( grep '.\(c\|cpp\|h\|hpp\|py\)$' || true ) \ - | ( grep -v '^tools/test/toolchains/api_test.py' || true ) \ - | while read file; do cp --parents "${file}" SCANCODE_NEW_FILES; done - - scancode -l --json-pp scancode_new_files.json SCANCODE_NEW_FILES - - python ./tools/test/travis-ci/scancode-evaluate.py scancode_new_files.json || true - - cat scancode-evaluate.log - - COUNT=$(cat scancode-evaluate.log | grep 'File:' | grep -v 'SPDX' | wc -l) || true - - python ./tools/test/travis-ci/scancode-evaluate.py scancode_new_files.json - - cat scancode-evaluate.log - - COUNT_NEW_FILES=$(cat scancode-evaluate.log | grep 'File:' | grep -v 'SPDX' | wc -l) || true - - | - if [ $COUNT == 0 ] && [ $COUNT_NEW_FILES == 0 ]; then - echo "License check OK"; - true; - elif [ $COUNT_NEW_FILES != 0 ]; then - echo "License check failed, new files with the license issues found"; - false; - else - echo "License check failed, please review license issues found in modified files"; - false; - fi - - - <<: *basic-vm - name: "UTF-8 Check" - script: - # Make sure we're not introducing any text which is not UTF-8 encoded - - git diff $TRAVIS_BRANCH...HEAD -U0 | ( grep -a '^+' || true ) | ( ! grep -axv '.*' ) - - - <<: *basic-vm - name: "include check" - env: NAME=include_check - script: - - | - ! git grep '^#include\s["'"']mbed.h['"'"]$' -- '*.c' '*.h' '*.cpp' '*.hpp' \ - ':!*platform_mbed.h' ':!*TESTS/*' ':!TEST_APPS/' ':!UNITTESTS/' \ - ':!*tests/*' ':!*targets/*' ':!*TARGET_*' ':!*unsupported/*' \ - ':!*events/tests/*' ':!*drivers/tests/*' - - ### Docs Tests ### - - &docs-vm - stage: "Docs" - name: "astyle" - env: NAME=astyle - install: - - >- - curl -L0 https://mbed-os-ci-public.s3-eu-west-1.amazonaws.com/jenkins-ci/deps/astyle_3.1_linux.tar.gz --output astyle.tar.gz; - mkdir -p BUILD && tar xf astyle.tar.gz -C BUILD; - cd BUILD/astyle/build/gcc; - make; - export PATH="${PWD}/bin:${PATH}"; - cd - - - astyle --version - # Fetch the base branch to compare against - - git fetch origin "${TRAVIS_BRANCH}" --depth=1 - script: - - >- - git diff --name-only --diff-filter=d FETCH_HEAD..HEAD \ - | ( grep '.*\.\(c\|cpp\|h\|hpp\)$' || true ) \ - | ( grep -v -f .codecheckignore || true ) \ - | while read file; do astyle -n --options=.astylerc "${file}"; done - - git diff --exit-code --diff-filter=d --color - - - <<: *docs-vm - name: "spellcheck" - env: NAME=doxy-spellcheck - install: - - source_pkg aspell - script: - # TODO: run checks on all directories once all mispellings are fixed - - ./tools/test/travis-ci/doxy-spellchecker/spell.sh drivers .codecheckignore - - ./tools/test/travis-ci/doxy-spellchecker/spell.sh platform .codecheckignore - - ./tools/test/travis-ci/doxy-spellchecker/spell.sh events .codecheckignore - - ./tools/test/travis-ci/doxy-spellchecker/spell.sh rtos .codecheckignore - - ./tools/test/travis-ci/doxy-spellchecker/spell.sh connectivity/netsocket .codecheckignore - - - <<: *docs-vm - name: "doxygen" - env: NAME=docs - install: - # Build doxygen - - > - (git clone --depth=1 --single-branch --branch Release_1_8_14 https://github.com/doxygen/doxygen; - cd doxygen; - mkdir build; - cd build; - cmake -G "Unix Makefiles" ..; - make; - sudo make install) - # Create BUILD directory for tests - - ccache -s - - mkdir BUILD - script: - # Assert that the Doxygen build produced no warnings. - # The strange command below asserts that the Doxygen command had an - # output of zero length - - doxygen doxyfile_options 2>&1 - # Once Mbed OS has been fixed, enable the full test by replacing the top line with this: - # - ( ! doxygen doxyfile_options 2>&1 | grep . ) - # Assert that all binary libraries are named correctly - # The strange command below asserts that there are exactly 0 libraries - # that do not start with lib - - > - find "(" -name "*.a" -or -name "*.ar" ")" -and -not -name "lib*" | - tee BUILD/badlibs | - sed -e "s/^/Bad library name found: /" && [ ! -s BUILD/badlibs ] - # Assert that all assembler files are named correctly - # The strange command below asserts that there are exactly 0 libraries - # that do end with .s - - > - find -name "*.s" | tee BUILD/badasm | - sed -e "s/^/Bad Assembler file name found: /" && [ ! -s BUILD/badasm ] - - ### Python Tests ### - - &pytools-vm - stage: "Pytest" - name: "tools-py35" - env: NAME=tools-py3.5 - language: python - python: 3.7 - install: - # Install gcc - - source_pkg gcc - - arm-none-eabi-gcc --version - # Install additional python modules - - python --version - - |- - tr -d ' ' >> requirements.txt <<< " - mock==2.0.0 - attrs==19.1.0 - pytest==3.3.0 - pylint>=1.9,<2 - hypothesis>=3,<4 - coverage>=4.5,<5 - " - - pip install --upgrade pip - - pip install -r requirements.txt - - pip list --verbose - script: - # Run local testing on tools - - PYTHONPATH=. coverage run -a -m pytest tools/test - - python tools/test/pylint.py - - coverage run -a tools/project.py -S | sed -n '/^Total/p' - - coverage html - - - &extended-vm - stage: "Pin validation" - name: "pinvalidate" - env: NAME=pinvalidate - language: python - python: 3.7 - install: - # Install python modules - - pip install --upgrade pip - - pip install tabulate argparse - - pip list --verbose - # Fetch the base branch to compare against - - git fetch origin "${TRAVIS_BRANCH}" --depth=1 - script: - - >- - git diff --name-only --diff-filter=d FETCH_HEAD..HEAD \ - | ( grep '.*[\\|\/]PinNames.h$' || true ) \ - | while read file; do python ./hal/tests/pinvalidate/pinvalidate.py -vfp "${file}"; done - - git diff --exit-code --diff-filter=d --color - - ### CMake Check ### - - &cmake-vm - stage: "CMake Check" - name: "Backward compatiblity check - MBED_TEST_MODE" - env: NAME=mbed-test-mode-check ROOT=tools/cmake/tests/mbed_test_mode/ TOOLCHAIN=GCC_ARM TARGET_NAME=K64F PROFILE=develop - language: python - python: 3.8 - install: - # Hide Travis-preinstalled CMake - # The Travis-preinstalled CMake is unfortunately not installed via apt, so we - # can't replace it with an apt-supplied version very easily. Additionally, we - # can't permit the Travis-preinstalled copy to survive, as the Travis default - # path lists the Travis CMake install location ahead of any place where apt - # would install CMake to. Instead of apt removing or upgrading to a new CMake - # version, we must instead delete the Travis copy of CMake. - - sudo rm -rf /usr/local/cmake* - # Setup ccache - - ccache -o compiler_check=content - - ccache -M 1G - - pushd /usr/lib/ccache - - sudo ln -s ../../bin/ccache arm-none-eabi-gcc - - sudo ln -s ../../bin/ccache arm-none-eabi-g++ - - export PATH="/usr/lib/ccache:$PATH" - - popd - # Install arm-none-eabi-gcc - - pushd /home/travis/build && mkdir arm-gcc && cd arm-gcc - - curl -L0 "https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2?revision=05382cca-1721-44e1-ae19-1e7c3dc96118&la=en&hash=D7C9D18FCA2DD9F894FD9F3C3DC9228498FA281A" --output gcc-arm-none-eabi-9-2020-q2-update.tar.bz2 - - tar xf gcc-arm-none-eabi-9-2020-q2-update.tar.bz2 - - export PATH="$PATH:${PWD}/gcc-arm-none-eabi-9-2020-q2-update/bin" - - popd - - arm-none-eabi-gcc --version - # Install python modules - - pip install --upgrade mbed-tools - - pip install -r tools/cmake/requirements.txt - script: - - mbedtools configure -p ${ROOT} -t ${TOOLCHAIN} -m ${TARGET_NAME} --mbed-os-path . - - cmake -S ${ROOT} -B ${ROOT}/cmake_build/${TARGET_NAME}/${PROFILE}/${TOOLCHAIN}/ -GNinja -DCMAKE_BUILD_TYPE=${PROFILE} - - cmake --build ${ROOT}/cmake_build/${TARGET_NAME}/${PROFILE}/${TOOLCHAIN}/ - - ### Mbed OS unittest ### - - &cmake-build-run-unittest - stage: "CMake" - name: "CMake unittest build" - env: NAME=cmake_unittest - install: - # Hide Travis-preinstalled CMake - # The Travis-preinstalled CMake is unfortunately not installed via apt, so we - # can't replace it with an apt-supplied version very easily. Additionally, we - # can't permit the Travis-preinstalled copy to survive, as the Travis default - # path lists the Travis CMake install location ahead of any place where apt - # would install CMake to. Instead of apt removing or upgrading to a new CMake - # version, we must instead delete the Travis copy of CMake. - - sudo rm -rf /usr/local/cmake* - script: - - echo ctest --build-and-test . build --build-generator Ninja --build-options -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DCOVERAGE=ON -DCMAKE_CXX_COMPILER=g++-7 -DCMAKE_C_COMPILER=gcc-7 --test-command ctest - - ctest --build-and-test . build --build-generator Ninja --build-options -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DCOVERAGE=ON -DCMAKE_CXX_COMPILER=g++-7 -DCMAKE_C_COMPILER=gcc-7 --test-command ctest - - gcovr --gcov-executable gcov-7 -r . ./build -s -e ".*\.h" --exclude-directories=$TRAVIS_BUILD_DIR/build/UNITTESTS --exclude-directories=$TRAVIS_BUILD_DIR/build/_deps - - ccache -s - - ### Frozen tools check ### - - &frozen-tools-vm - stage: "Frozen tools check" - name: "Frozen tools check" - env: NAME=frozen_tools_check - before_script: - # Fetch the base branch to compare against - - git fetch origin "${TRAVIS_BRANCH}" --depth=1 - script: - # Reject any changes to tools that would require a re-release of the - # tools for the online compiler. - - >- - frozen_files=`\ - git diff --name-only FETCH_HEAD..HEAD \ - | egrep \ - -e "^tools/build_api*" \ - -e "^tools/config*" \ - -e "^tools/export*" \ - -e "^tools/notifier*" \ - -e "^tools/paths*" \ - -e "^tools/resources*" \ - -e "^tools/targets*" \ - -e "^tools/toolchains*" \ - -e "^tools/utils*" \ - -e "^$"` - if [ -z "$frozen_files" ]; then - echo "Success!"; - else - echo -e "Failure: Frozen files were modified\n$frozen_files"; - echo -e "Please see https://os.mbed.com/blog/entry/Introducing-the-new-Mbed-Tools/" \ - "\nfor why we've frozen the legacy tools."; - false; - fi diff --git a/CMakeLists.txt b/CMakeLists.txt index 186825ad08f..9536ccf0f32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,17 @@ cmake_minimum_required(VERSION 3.19.0 FATAL_ERROR) +option(BUILD_GREENTEA_TESTS "Build greentea tests only." OFF) + +if(BUILD_GREENTEA_TESTS) + # Usually we rely on the application to set MBED_CONFIG_PATH and include + # app.cmake. They are both required if we're building an application to run + # on an mbed-target. + set(MBED_CONFIG_PATH ${CMAKE_CURRENT_BINARY_DIR} CACHE STRING "") + # TODO: Remove when https://github.com/ARMmbed/mbed-os/issues/14518 is fixed + include(${CMAKE_CURRENT_LIST_DIR}/tools/cmake/app.cmake) +endif() + if(${CMAKE_CROSSCOMPILING}) include(${MBED_CONFIG_PATH}/mbed_config.cmake) include(mbed_set_linker_script) @@ -14,17 +25,19 @@ project(mbed-os) # Add all paths to the list files within Mbed OS list(APPEND CMAKE_MODULE_PATH - "${mbed-os_SOURCE_DIR}/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_LATEST/scripts;${mbed-os_SOURCE_DIR}/targets/TARGET_Cypress/scripts;${mbed-os_SOURCE_DIR}/targets/TARGET_NXP/scripts" + "${mbed-os_SOURCE_DIR}/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_LATEST/scripts;${mbed-os_SOURCE_DIR}/targets/TARGET_Cypress/scripts;${mbed-os_SOURCE_DIR}/targets/TARGET_NXP/scripts;${mbed-os_SOURCE_DIR}/targets/TARGET_NUVOTON/scripts/" ) add_subdirectory(extern) -option(BUILD_TESTING "Run unit tests only." OFF) - -if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING) +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) include(CTest) - add_definitions(-DUNITTEST) - add_subdirectory(UNITTESTS) + + if((NOT BUILD_GREENTEA_TESTS) AND BUILD_TESTING) + # Building unit tests only. + add_definitions(-DUNITTEST) + add_subdirectory(UNITTESTS) + endif() endif() add_library(mbed-core INTERFACE) @@ -88,16 +101,19 @@ if(${CMAKE_CROSSCOMPILING}) target_compile_definitions(mbed-core INTERFACE + TARGET_NAME=${MBED_TARGET} ${MBED_TARGET_DEFINITIONS} ${MBED_CONFIG_DEFINITIONS} ) # Add MBED_TEST_MODE for backward compatibility with Greentea tests written for use with Mbed CLI 1 if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING) - target_compile_definitions(${PROJECT_NAME} - INTERFACE - MBED_TEST_MODE - ) + if(NOT BUILD_GREENTEA_TESTS) + target_compile_definitions(${PROJECT_NAME} + INTERFACE + MBED_TEST_MODE + ) + endif() endif() # We need to generate a "response file" to pass to the C preprocessor when we preprocess the linker @@ -144,12 +160,16 @@ target_include_directories(mbed-core add_library(mbed-device_key INTERFACE) add_library(mbed-rtos INTERFACE) +# Include targets/ first, because any post-build hook needs to be defined +# before other parts of Mbed OS can add greentea tests which require +# mbed_set_post_build(). +add_subdirectory(targets) + add_subdirectory(cmsis) add_subdirectory(drivers) add_subdirectory(hal) add_subdirectory(platform) add_subdirectory(rtos) -add_subdirectory(targets) add_subdirectory(storage) add_subdirectory(events) add_subdirectory(connectivity) @@ -171,122 +191,6 @@ if(${CMAKE_CROSSCOMPILING}) target_link_libraries(mbed-core INTERFACE ${MBED_TARGET_CONVERTED}) endif() -# -# Converts output file of `target` to binary file and to Intel HEX file. -# -function(mbed_generate_bin_hex target) - get_property(elf_to_bin GLOBAL PROPERTY ELF2BIN) - if (MBED_TOOLCHAIN STREQUAL "GCC_ARM") - # The first condition is quoted in case MBED_OUTPUT_EXT is unset - if ("${MBED_OUTPUT_EXT}" STREQUAL "" OR MBED_OUTPUT_EXT STREQUAL "bin") - list(APPEND CMAKE_POST_BUILD_COMMAND - COMMAND ${elf_to_bin} -O binary $ ${CMAKE_CURRENT_BINARY_DIR}/${target}.bin - COMMAND ${CMAKE_COMMAND} -E echo "-- built: ${CMAKE_CURRENT_BINARY_DIR}/${target}.bin" - ) - endif() - if ("${MBED_OUTPUT_EXT}" STREQUAL "" OR MBED_OUTPUT_EXT STREQUAL "hex") - list(APPEND CMAKE_POST_BUILD_COMMAND - COMMAND ${elf_to_bin} -O ihex $ ${CMAKE_CURRENT_BINARY_DIR}/${target}.hex - COMMAND ${CMAKE_COMMAND} -E echo "-- built: ${CMAKE_CURRENT_BINARY_DIR}/${target}.hex" - ) - endif() - elseif(MBED_TOOLCHAIN STREQUAL "ARM") - get_property(mbed_studio_arm_compiler GLOBAL PROPERTY MBED_STUDIO_ARM_COMPILER) - if ("${MBED_OUTPUT_EXT}" STREQUAL "" OR MBED_OUTPUT_EXT STREQUAL "bin") - list(APPEND CMAKE_POST_BUILD_COMMAND - COMMAND ${elf_to_bin} ${mbed_studio_arm_compiler} --bin -o ${CMAKE_CURRENT_BINARY_DIR}/${target}.bin $ - COMMAND ${CMAKE_COMMAND} -E echo "-- built: ${CMAKE_CURRENT_BINARY_DIR}/${target}.bin" - ) - endif() - if ("${MBED_OUTPUT_EXT}" STREQUAL "" OR MBED_OUTPUT_EXT STREQUAL "hex") - list(APPEND CMAKE_POST_BUILD_COMMAND - COMMAND ${elf_to_bin} ${mbed_studio_arm_compiler} --i32combined -o ${CMAKE_CURRENT_BINARY_DIR}/${target}.hex $ - COMMAND ${CMAKE_COMMAND} -E echo "-- built: ${CMAKE_CURRENT_BINARY_DIR}/${target}.hex" - ) - endif() - endif() - add_custom_command( - TARGET - ${target} - POST_BUILD - ${CMAKE_POST_BUILD_COMMAND} - COMMENT - "executable:" - VERBATIM - ) - - if(TARGET mbed-post-build-bin-${MBED_TARGET}) - # Remove the .elf file to force regenerate the application binaries - # (including .bin and .hex). This ensures that the post-build script runs - # on a raw application instead of a previous build that already went - # through the post-build process once. - file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/${target}.elf) - - # Pass the application's name to the Mbed target's post build operation - set_target_properties(mbed-post-build-bin-${MBED_TARGET} - PROPERTIES - application ${target} - ) - - # The artefacts must be created before they can be further manipulated - add_dependencies(mbed-post-build-bin-${MBED_TARGET} ${target}) - - # Add a post-build hook to the top-level CMake target in the form of a - # CMake custom target. The hook depends on Mbed target specific - # post-build CMake target which has a custom command attached to it. - add_custom_target(mbed-post-build ALL DEPENDS mbed-post-build-bin-${MBED_TARGET}) - endif() -endfunction() - -# -# Parse toolchain generated map file of `target` and display a readable table format. -# -function(mbed_generate_map_file target) - add_custom_command( - TARGET - ${target} - POST_BUILD - COMMAND ${Python3_EXECUTABLE} ${mbed-os_SOURCE_DIR}/tools/memap.py -t ${MBED_TOOLCHAIN} ${CMAKE_CURRENT_BINARY_DIR}/${target}${CMAKE_EXECUTABLE_SUFFIX}.map - WORKING_DIRECTORY - ${CMAKE_CURRENT_BINARY_DIR} - COMMENT - "Displaying memory map for ${target}" -) -endfunction() - -# -# Validate selected application profile. -# -function(mbed_validate_application_profile target) - get_target_property(app_link_libraries ${target} LINK_LIBRARIES) - string(FIND "${app_link_libraries}" "mbed-baremetal" string_found_position) - if(${string_found_position} GREATER_EQUAL 0) - if(NOT "bare-metal" IN_LIST MBED_TARGET_SUPPORTED_APPLICATION_PROFILES) - message(FATAL_ERROR - "Use full profile as baremetal profile is not supported for this Mbed target") - endif() - elseif(NOT "full" IN_LIST MBED_TARGET_SUPPORTED_APPLICATION_PROFILES) - message(FATAL_ERROR - "The full profile is not supported for this Mbed target") - endif() -endfunction() - -# -# Set post build operations -# -function(mbed_set_post_build target) - # The mapfile name includes the top-level target name and the - # executable suffix for all toolchains as CMake hardcodes the name of the - # diagnostic output file for some toolchains. - mbed_configure_memory_map(${target} "${CMAKE_CURRENT_BINARY_DIR}/${target}${CMAKE_EXECUTABLE_SUFFIX}.map") - mbed_validate_application_profile(${target}) - mbed_generate_bin_hex(${target}) - - if(HAVE_MEMAP_DEPS) - mbed_generate_map_file(${target}) - endif() -endfunction() - # Ninja requires to be forced for response files if ("${CMAKE_GENERATOR}" MATCHES "Ninja") # known issue ARMClang and Ninja with response files for windows diff --git a/LICENSE.md b/LICENSE.md index a689f199e94..888613a6afd 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -44,8 +44,6 @@ The Python modules used by Mbed tools are used under the following licenses: - [Jinja2](https://pypi.org/project/Jinja2) - BSD-3-Clause - [jsonschema](https://pypi.org/project/jsonschema) - MIT - [junit-xml](https://pypi.org/project/junit-xml) - MIT -- [manifest-tool](https://pypi.org/project/manifest-tool) - Apache-2.0 -- [mbed-cloud-sdk](https://pypi.org/project/mbed-cloud-sdk) - Apache 2.0 - [mbed-greentea](https://pypi.org/project/mbed-greentea) - Apache-2.0 - [mbed-host-tests](https://pypi.org/project/mbed-host-tests) - Apache-2.0 - [mbed-ls](https://pypi.org/project/mbed-ls) - Apache-2.0 diff --git a/README.md b/README.md index e4cfea0aaef..503d271672c 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,12 @@ [![Mbed OS][mbed-os-logo]][mbed-os-link] -[![Build status release][mbed-travis-release-svg]][mbed-travis-release] -[![Build status master][mbed-travis-master-svg]][mbed-travis-master] +[![Build status master][mbed-master-svg]][mbed-master] [![Tools coverage status][mbed-coveralls-tools-svg]][mbed-coveralls-tools] [mbed-os-logo]: logo.png [mbed-os-link]: https://www.mbed.com/en/platform/mbed-os/ -[mbed-travis-master]: https://travis-ci.org/ARMmbed/mbed-os -[mbed-travis-master-svg]: https://travis-ci.org/ARMmbed/mbed-os.svg?branch=master -[mbed-travis-release]: https://travis-ci.org/ARMmbed/mbed-os/branches -[mbed-travis-release-svg]: https://travis-ci.org/ARMmbed/mbed-os.svg?branch=latest +[mbed-master]: https://github.com/ARMmbed/mbed-os/actions/workflows/basic_checks.yml +[mbed-master-svg]: https://github.com/ARMmbed/mbed-os/actions/workflows/basic_checks.yml/badge.svg [mbed-coveralls-tools]: https://coveralls.io/github/ARMmbed/mbed-os?branch=master [mbed-coveralls-tools-svg]: https://coveralls.io/repos/github/ARMmbed/mbed-os/badge.svg?branch=master diff --git a/TEST_APPS/__init__.py b/TEST_APPS/__init__.py deleted file mode 100644 index 11867b5685a..00000000000 --- a/TEST_APPS/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -Copyright (c) 2020 ARM Limited -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" diff --git a/TEST_APPS/device/exampleapp/main.cpp b/TEST_APPS/device/exampleapp/main.cpp deleted file mode 100644 index 99987036cd5..00000000000 --- a/TEST_APPS/device/exampleapp/main.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2018 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include -#include "mbed.h" -#include "mbed-client-cli/ns_cmdline.h" - -#ifndef ICETEA_EXAMPLE_ENABLED -#error [NOT_SUPPORTED] Skipping example application. -#endif -/** - * Macros for setting console flow control. - */ -#define CONSOLE_FLOWCONTROL_RTS 1 -#define CONSOLE_FLOWCONTROL_CTS 2 -#define CONSOLE_FLOWCONTROL_RTSCTS 3 -#define mbed_console_concat_(x) CONSOLE_FLOWCONTROL_##x -#define mbed_console_concat(x) mbed_console_concat_(x) -#define CONSOLE_FLOWCONTROL mbed_console_concat(MBED_CONF_TARGET_CONSOLE_UART_FLOW_CONTROL) - -#define SERIAL_CONSOLE_BAUD_RATE 115200 - -void cmd_ready_cb(int retcode) -{ - cmd_next(retcode); -} - -void wrap_printf(const char *f, va_list a) -{ - vprintf(f, a); -} - -int main() -{ - cmd_init(&wrap_printf); - - int c; - while ((c = getchar()) != EOF) { - cmd_char_input(c); - } - return 0; -} - -FileHandle *mbed::mbed_override_console(int) -{ - static BufferedSerial console(STDIO_UART_TX, STDIO_UART_RX, SERIAL_CONSOLE_BAUD_RATE); -#if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS - console.set_flow_control(SerialBase::RTS, STDIO_UART_RTS, NC); -#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS - console.set_flow_control(SerialBase::CTS, NC, STDIO_UART_CTS); -#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS - console.set_flow_control(SerialBase::RTSCTS, STDIO_UART_RTS, STDIO_UART_CTS); -#endif - return &console; -} diff --git a/TEST_APPS/device/nanostack_mac_tester/README.md b/TEST_APPS/device/nanostack_mac_tester/README.md deleted file mode 100644 index 0a42a2d2f89..00000000000 --- a/TEST_APPS/device/nanostack_mac_tester/README.md +++ /dev/null @@ -1,88 +0,0 @@ -# Nanostack MAC test application - -You can use this application to test the Nanostack RF driver implementations that follow the [Nanostack RF driver porting instructions](https://os.mbed.com/docs/v5.6/reference/contributing-connectivity.html#porting-new-rf-driver-for-6lowpan-stack). The application has a command-line interface that is used to send commands to Nanostack's MAC layer, for example starting PANs, scanning or sending data. The provided tests do not test performance or stability and only indirectly test RF functionalities. - -## Table of contents - -* [Prerequisites](#prerequisites) -* [Setting up the application](#setting-up-the-application) -* [Application usage](#application-usage) - * [Interactive mode](#interactive-mode) - * [Automated mode](#automated-mode) - * [Testcases](#testcases) - * [Considerations](#considerations) - -## Prerequisites - -* [Mbed CLI](https://github.com/ARMmbed/mbed-cli). -* Mbed OS target board with build in radio, OR RF shield with Mbed OS driver - -## Setting up the application - -### Add your RF driver - -When using RF shield, you need to configure it to be a default RF driver and instruct Mbed OS that RF driver is present. For example, configuring Atmel RF driver to provide default driver: - -``` - "target_overrides": { - "*": { - "target.device_has_add": ["802_15_4_RF_PHY"], - "atmel-rf.provide-default": true -``` - -### Checking platform support - -Check that your choice of platform is supported by your choice of toolchain: - -``` -mbed compile --supported -``` - -**Note:** Targets are often abbreviated from the full model names. In the case of `FRDM-K64F` the target is `K64F`. - -## Run tests - -You can use this application in interactive or automated mode. - -### Interactive mode - -To set the application to interactive mode: - -1. Build the application. -``` -mbed test --compile --icetea -t TOOLCHAIN -m TARGET_PLATFORM -DICETEA_MAC_TESTER_ENABLED --test-config NANOSTACK_MAC_TESTER -n address_read_and_write,send_data,send_data_indirect,send_large_payloads,create_and_join_PAN,ED_scan -``` -2. Connect your board and copy the compiled application binary from the `BUILD/tests/TARGET_PLATFORM/TOOLCHAIN/TEST_APPS/device/nanostack_mac_tester/` folder to the board. -3. Wait for the device to flash the binary. -4. Open a serial connection with a program such as PuTTY, screen or minicom. The default baudrate is 115200. -5. Press the reset button on the board. The Arm Mbed logo and trace appears in the terminal window. - -If the driver registration and SW MAC creation was successful, the application is ready to receive commands. - -To start off, type `help` to list all commands available and furthermore `help ` to print detailed information about a specific command. - -### Automated mode - -``` -mbed test --clean --compile --run --icetea -t TOOLCHAIN -m TARGET_PLATFORM -DICETEA_MAC_TESTER_ENABLED --test-config NANOSTACK_MAC_TESTER -n address_read_and_write,send_data,send_data_indirect,send_large_payloads,create_and_join_PAN,ED_scan -``` - -Many of the provided testcases have a `self.channel` variable in the `setUp()` function for setting the RF channel. The default channel is 11. If you wish to run a test on another channel, you will need to change it manually in TEST_APPS/testcases/nanostack_mac_tester/. - -Some testcases also use a secondary channel for transmitting and will use the next higher channel for that purpose. If the given channel is 26, the secondary channel will default to 25. - -### Test cases - -The automated test set runs the following testcases included in the repository under `TEST_APPS/testcases/nanostack_mac_tester/`. -* Create and join PAN -* Direct data transmission(Transmission between two devices) -* Indirect data transmission(Transmission between two devices with one device acting as intermediary) -* ED scan(Energy Density scanning) -* Address read and write -* Large data transmission - -### Considerations - -* Devices need to be power cycled if they are unresponsive to test framework commands even after resetting. -* Devices can be enclosed in an RF isolation box to improve the consistency of test results. -* Some boards and radio modules come with a PCB trace antenna, instead of an SMD antenna, and need to be spaced further apart to decrease interference. \ No newline at end of file diff --git a/TEST_APPS/device/nanostack_mac_tester/main.cpp b/TEST_APPS/device/nanostack_mac_tester/main.cpp deleted file mode 100644 index ee97dd49559..00000000000 --- a/TEST_APPS/device/nanostack_mac_tester/main.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2017, Arm Limited and affiliates. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "mbed.h" -#include "rtos.h" -#include "sw_mac.h" -#include "ns_hal_init.h" -#define MBED_CMDLINE_MAX_LINE_LENGTH 250 -#include "ns_cmdline.h" - -#include "mac_commands.h" - -#define HEAP_FOR_MAC_TESTER_SIZE 10000 -#define RX_BUFFER_SIZE 512 - -#define ATMEL 1 -#define MCR20 2 -#define OTHER 3 - -#define TRACE_GROUP "Main" -#include "mbed-trace/mbed_trace.h" - -#include "NanostackRfPhy.h" - -#if !DEVICE_802_15_4_PHY -#error [NOT_SUPPORTED] No 802.15.4 RF driver found for this target -#endif - -#ifndef ICETEA_MAC_TESTER_ENABLED -#error [NOT_SUPPORTED] Skipping Nanostack MAC tester application. -#endif - -extern mac_api_s *mac_interface; -UnbufferedSerial pc(CONSOLE_TX, CONSOLE_RX); -osThreadId_t main_thread; -static CircularBuffer rx_buffer; -static uint8_t ns_heap[HEAP_FOR_MAC_TESTER_SIZE]; - -static void app_heap_error_handler(heap_fail_t event) -{ - tr_error("Heap error (%d), app_heap_error_handler()", event); - switch (event) { - case NS_DYN_MEM_NULL_FREE: - case NS_DYN_MEM_DOUBLE_FREE: - case NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID: - case NS_DYN_MEM_POINTER_NOT_VALID: - case NS_DYN_MEM_HEAP_SECTOR_CORRUPTED: - case NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED: - break; - default: - break; - } - while (1); -} - -static void rx_interrupt(void) -{ - uint8_t c; - pc.read(&c, 1); - rx_buffer.push(c); - if (main_thread != NULL) { - osThreadFlagsSet(main_thread, 1); - } -} - -static void handle_rx_data(void) -{ - bool exit = false; - uint8_t data; - - while (1) { - exit = !rx_buffer.pop(data); - if (exit) { - break; - } - cmd_char_input(data); - } -} - - -static int mac_prepare(void) -{ - NanostackRfPhy &rf_phy = NanostackRfPhy::get_default_instance(); - int8_t rf_driver_id = rf_phy.rf_register(); - uint8_t rf_eui64[8]; - - if (rf_driver_id < 0) { - tr_error("Failed to register RF driver."); - return -1; - } - rf_phy.get_mac_address(rf_eui64); - mac_description_storage_size_t mac_description; - mac_description.device_decription_table_size = DEVICE_DESCRIPTOR_TABLE_SIZE; /** MAC Device description list size */ - mac_description.key_description_table_size = KEY_DESCRIPTOR_TABLE_SIZE; /** MAC Key description list size */ - mac_description.key_lookup_size = LOOKUP_DESCRIPTOR_TABLE_SIZE; /** Key description key lookup list size */ - mac_description.key_usage_size = USAGE_DESCRIPTOR_TABLE_SIZE; /** Key description key usage list size */ - tr_info("Registered RF driver with id: %hhu, EUI64: %s", rf_driver_id, mbed_trace_array(rf_eui64, 8)); - mac_interface = ns_sw_mac_create(rf_driver_id, &mac_description); - if (!mac_interface) { - tr_error("Failed to create SW MAC."); - return -2; - } - - return mac_interface->mac_initialize(mac_interface, mac_data_confirm_handler, - mac_data_indication_handler, mac_purge_confirm_handler, mac_mlme_confirm_handler, - mac_mlme_indication_handler, rf_driver_id); -} - -static void cmd_ready_cb(int retcode) -{ - cmd_next(retcode); -} - -static void trace_printer(const char *str) -{ - printf("%s\n", str); - cmd_output(); - fflush(stdout); -} - -int main(void) -{ - main_thread = ThisThread::get_id(); - pc.baud(MBED_CONF_PLATFORM_STDIO_BAUD_RATE); - pc.attach(rx_interrupt); - ns_hal_init(ns_heap, HEAP_FOR_MAC_TESTER_SIZE, app_heap_error_handler, NULL); - mbed_trace_init(); - mbed_trace_print_function_set(trace_printer); - cmd_init(&default_cmd_response_out); - cmd_set_ready_cb(cmd_ready_cb); - mac_commands_init(); - - if (mac_prepare() != 0) { - return -1; - } - tr_info("Created driver & SW MAC"); - - while (true) { - ThisThread::flags_wait_any(1); - handle_rx_data(); - } - return 0; -} diff --git a/TEST_APPS/device/nanostack_mac_tester/mbed_app.json b/TEST_APPS/device/nanostack_mac_tester/mbed_app.json deleted file mode 100644 index d86bfd2dc72..00000000000 --- a/TEST_APPS/device/nanostack_mac_tester/mbed_app.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "macros": ["MBED_TRACE_LINE_LENGTH=200", "OS_TASKCNT=4", "OS_IDLESTKSIZE=32"], - "target_overrides": { - "*": { - "nanostack.configuration": "lowpan_host", - "platform.stdio-convert-newlines": true, - "platform.stdio-baud-rate": 115200, - "mbed-mesh-api.heap-size": 6000, - "nanostack-hal.event_loop_thread_stack_size": 2000, - "mbed-trace.enable": true, - "nsapi.default-stack": "LWIP", - "target.device_has_add": ["802_15_4_PHY"], - "atmel-rf.provide-default": true - } - } -} diff --git a/TEST_APPS/device/nanostack_mac_tester/source/mac_commands.cpp b/TEST_APPS/device/nanostack_mac_tester/source/mac_commands.cpp deleted file mode 100644 index 08117b7482a..00000000000 --- a/TEST_APPS/device/nanostack_mac_tester/source/mac_commands.cpp +++ /dev/null @@ -1,1654 +0,0 @@ -/* - * Copyright (c) 2017, Arm Limited and affiliates. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "mac_commands.h" - -//Need to disable filtering until mac_filter_api.h in mbed-os is updated -#define DISABLE_FILTERING - -#define TRACE_GROUP "MAC" - -#define MAN_MAC_START "start --- Starts a PAN\n"\ - " --pan_id PAN id in hex, default: 0x1234\n"\ - " --logical_channel Operated logical channel, default: 11 (0-26)\n"\ - " --channel_page Operated channel page, default: 0 (0-2)\n"\ - " --start_time Time at which to start sending beacons\n"\ - " default: 0\n"\ - " --beacon_order How often are beacons transmitted\n"\ - " default: 15 (0-15, 15 = never)\n"\ - " --super_frame_order Length of the superframe's active portion\n"\ - " if beacon_order is 15, this option is ignored\n"\ - " default: 15 (0-15)\n"\ - " --pan_coordinator Is this device the PAN coordinator?\n"\ - " default: true\n"\ - " --battery_life_extension Disable beaconing device periodically\n"\ - " to save power? default: false\n"\ - " --coord_realignment If true, coordinator realignment command\n"\ - " is sent prior to changing\n"\ - " the superframe configuration default: false\n" - -#define MAN_MAC_SCAN "scan --- Perform a scan\n"\ - " --scan_type What type of scan to perform, 0=ED, 1=active\n"\ - " 2=passive, 3=orphan, default: 1\n"\ - " --channel_page_enum default: 0 (0-10)\n"\ - " --channel_mask Bitmap of the channels on which to perform\n"\ - " the scan, lower 27-bits are used\n"\ - " bit 0 corresponds to channel 0 and so forth\n"\ - " default: 0x07FFF800 (channels 11-26)\n"\ - " --scan_duration How long to spend in each channel,\n"\ - " aBaseSuperFrameDuration * (2^n + 1) symbols\n"\ - " default: 5 (0-14)\n"\ - " --channel_page The channel page on which to perform the scan\n"\ - " default: 0 (0-31)\n"\ - MAN_MAC_SECURITY - -#define MAN_MAC_DATA "data --- Send arbitrary data\n"\ - " --src_addr_mode Source addressing mode, 0=no address, 1=reserved\n"\ - " 2=16-bit address, 3=64-bit address\n"\ - " default: 3 (0-3)\n"\ - " --dst_addr_mode Destination addressing mode, same as above\n"\ - " default: 3 (0-3)\n"\ - " --dst_pan_id Destination PAN id in hex\n"\ - " default: 0x1234 (0x0-0xFFFF)\n"\ - " --dst_addr Destination address, default: 00:00:00:...\n"\ - " --msdu_length Length of the data to send, default: 0 (0-255)\n"\ - " --msdu Data to transmit, default: \n"\ - " --msdu_handle Handle of this MSDU, default: 0 (0-255)\n"\ - " --tx_ack_req Is ack required for this transmission?\n"\ - " default: true\n"\ - " --indirect_tx Transmit indirectly? default: false\n"\ - " --pending_bit Specifies whether more fragments (higher layer)\n"\ - " are to be sent, default: false\n"\ - " --wait_for_confirm Should we block further commands until we have\n"\ - " received a data confirmation, default: true\n"\ - MAN_MAC_SECURITY - -#define MAN_MAC_POLL "poll --- Poll the coordinator for data\n"\ - " --coord_addr_mode Coordinator addressing mode, 2=16-bit address\n"\ - " 3=64-bit address, default: 3 (2-3)\n"\ - " --coord_pan_id Coordinator PAN id in hex\n"\ - " default: 0x1234 (0x0-0xFFFF)\n"\ - " --coord_address Coordinator address, default 00:00:00:...\n"\ - MAN_MAC_SECURITY - -#define MAN_MAC_PURGE "purge --- Remove a transmission from the queue\n"\ - " --msdu_handle Handle of the MSDU to be removed\n"\ - " default: 0 (0-255)\n"\ - -#define MAN_MAC_SET "mlme-set --- Set a specified PIB attribute\n"\ - " --attr ID of the attribute to set in hex (0x0-0xFF)\n"\ - " --attr_index <0-255> Index of the attribute, default: 0 (0-255)\n"\ - " --value_ascii Specify the set value as an ASCII string\n"\ - " --value_bytes Value as a string of bytes\n"\ - " --value_uint8/16/32 Value as a uint8, uint16, or uint32\n"\ - " Max value for uint32 is the max value for int32\n"\ - " --value_size Size of the value in bytes (0-255)\n" - -#define MAN_MAC_GET "mlme-get --- Get a specified PIB attribute\n"\ - " --attr ID of the attribute we want to get in hex (0x0-0xFF)\n"\ - " --attr_index Index of the attribute, default: 0 (0-255)\n" - -#define MAN_MAC_RESET "mlme-reset --- Reset the MAC sublayer\n"\ - " --set_default_pib When set to true, PIB attributes are set to\n"\ - " their default values\n"\ - " If set to false, PIB attributes retain\n"\ - " their values, default: true\n" - -#define MAN_MAC_ADDR "addr --- Configure 16/64-bit MAC addresses\n"\ - " having no options will display the addresses\n"\ - " --16-bit 16-bit MAC address in hex (0x0-0xFFFF)\n"\ - " --64-bit 64-bit MAC address\n" - -#define MAN_MAC_SECURITY " --security_level 0=no security, 1=MIC32, 2=MIC64, 3=MIC128,\n"\ - " 4=ENC, 5=ENC+MIC32, 6=ENC+MIC64, 7=ENC+MIC128\n"\ - " default: 0\n"\ - " --key_id_mode 0=implicit, 1=default key source\n"\ - " 2=2-byte key source\n"\ - " 3=8-byte key source, default: 0 (0-3)\n"\ - " --key_index Which key to use, default: 0 (0-255)\n"\ - " --key_source The originator of the key to be used\n" - -#define MAN_MAC_KEY "key --- Configure or add key descriptors\n"\ - "config --- Configure parameters for key descriptor\n"\ - " --key Actual security key, 16 bytes\n"\ - " default: C0:C1:C2:...:CF\n"\ - " --key_id_lookup_list_entries Amount of entries in the key's lookup\n"\ - " --key_device_list_entries ...device...\n"\ - " --key_usage_list_entries and usage list, default: 2 (0-255)\n"\ - " --lookup_index Which entry of the lookup list\n"\ - " are we accessing? default: 0 (0-255)\n"\ - " --lookup_data The lookup data for this key\n"\ - " length is 9 bytes regardless of\n"\ - " the next option\n"\ - " --lookup_data_size How large is the lookup data? (0-1)\n"\ - " 0=5 bytes, 1=9 bytes\n"\ - " --device_list_index Which entry of the device list\n"\ - " are we accessing, default: 0 (0-255)\n"\ - " --device_descriptor_handle Which entry in our neighbour table\n"\ - " do we want to use this key with\n"\ - " default: 0 (0-255)\n"\ - " --unique_device Is the device unique to the key?\n"\ - " --blacklisted Is the device blacklisted?\n"\ - " --usage_list_index Which entry of the usage list\n"\ - " are we accessing, default: 0 (0-255)\n"\ - " --frame_type What type of frame do we want to\n"\ - " use this key with? (0-3)\n"\ - " 0=beacon, 1=data, 2=ACK, 3=command\n"\ - " --command_frame_identifier Type of the command frame (1-9)\n"\ - " 1=association request\n"\ - " 2=association response\n"\ - " 3=disassociation notification\n"\ - " 4=data request\n"\ - " 5=PAN id conflict notification\n"\ - " 6=orphan notification\n"\ - " 7=beacon request\n"\ - " 8=coordinator realigment\n"\ - " 9=GTS request\n"\ - "add --- Add the key into the key descriptor table\n"\ - " --index Index in the key table (0-255)\n" - -#define MAN_MAC_ADD_NEIGHBOUR "add-neigh --- Add an entry to the neighbour table\n"\ - " --frame_ctr Frame counter for this neighbour\n"\ - " --mac16 16-bit MAC address in hex (0x0-0xFFFF)\n"\ - " --mac64 64-bit MAC address\n"\ - " --pan_id PAN id (0x0-0xFFFF)\n"\ - " --index Index in the neighbour table (0-255)\n" - -#define MAN_MAC_FILTER "filter --- Configure MAC layer filtering\n"\ - "start --- Start a generic filter in blacklist, whitelist or fixed mode\n"\ - " --mode Set the filtering mode, values: allow|block|fixed\n"\ - " --lqi_m LQI multiplier (fixed mode only)\n"\ - " --dbm_m dBm multiplier (fixed mode only)\n"\ - "add --- Add a filter by manually supplying values, or using a preset mode\n"\ - " --lqi_m LQI multiplier\n"\ - " --lqi_add Value added to the LQI\n"\ - " --dbm_m dBm multiplier\n"\ - " --dbm_add Value added to the dBm\n"\ - " --mode Filtering mode, values: allow|block|fixed\n"\ - " --short 16-bit address in hex to filter (0x0-0xFFFF)\n"\ - " --long 64-bit address as bytes to filter\n"\ - "remove --- Remove a filter\n"\ - " --short 16-bit address to remove from filter (0x0-0xFFFF)\n"\ - " --long 64-bit address to remove from filter\n"\ - "clear --- Clear all filters excluding the default one\n"\ - "stop --- Stop filtering completely\n"\ - -#define MAN_MAC_CONFIG_STATUS "config-status --- Configure expected status codes\n"\ - " having no options will display configured statuses\n"\ - " default: 0 (MLME_SUCCESS) for all\n"\ - " --data_conf MCPS-DATA.confirm (0-255)\n"\ - " --data_ind MCPS-DATA.indication (0-255)\n"\ - " --get MLME-GET.confirm (0-255)\n"\ - " --scan MLME-SCAN.confirm (0-255)\n"\ - " --poll MLME-POLL.confirm (0-255)\n"\ - " --purge MCPS-PURGE.confirm (0-255)\n"\ - " --comm_status MLME-COMM-STATUS.indication (0-255)\n"\ - " --list List all statuses\n"\ - " --reset Reset all statuses to default values\n" - -#define MAN_MAC_FIND_BEACON "find-beacon --- Search for a PAN in the\n"\ - " results of the last scan\n"\ - " --data Beacon data transmitted in the beacon\n" - -#define MAN_MAC_WAIT "wait --- Wait for data sent directly for a\n"\ - " specified amount of milliseconds\n"\ - " --timeout Milliseconds to wait, default: 1000\n" - -#define MAN_MAC_ED_ANALYZE "analyze-ed Channel to analyze (11-26)\n"\ - " --above Check if the ED value is above a given value\n"\ - " --below Check if the ED value is below a given value\n" - -#define MAN_RESET "reset --- Reset MCPS and MLME structures to default values\n" - -#define MAN_SILENT "silent-mode --- When enabled, doesn't print extended information\n"\ - " of MCPS/MLME primitives\n" - -mac_api_s *mac_interface = NULL; -static bool wait_for_confirm = true; -static bool silent_mode = false; -static volatile unsigned int data_count = 0; - -static mlme_start_t start_req = { - 0x1234, /*PANId*/ - 11, /*LogicalChannel*/ - 0, /*ChannelPage*/ - 0, /*StartTime*/ - 15, /*BeaconOrder*/ - 15, /*SuperframeOrder*/ - true, /*PANCoordinator*/ - false, /*BatteryLifeExtension*/ - false, /*CoordRealignment*/ -}; - -static mlme_scan_t scan_req = { - MAC_ACTIVE_SCAN, /*ScanType*/ - { - CHANNEL_PAGE_0, /*channel_page (enum)*/ - 0x07FFF800 /*channel_mask*/ - }, - 5, /*ScanDuration*/ - 0, /*ChannelPage*/ - { - 0, /*SecurityLevel*/ - 0, /*KeyIdMode*/ - 0, /*KeyIndex*/ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /*Keysource*/ - } -}; - -static mcps_data_req_t data_req = { - 3, /*SrcAddrMode*/ - 3, /*DstAddrMode*/ - 0x1234, /*DstPANId*/ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*DstAddr*/ - 0, /*msduLength*/ - NULL, /*msdu*/ - 0, /*msduHandle*/ - true, /*TxAckReq*/ - false, /*IndirectTx*/ - false, /*PendingBit*/ - false, /*SeqNumSuppressed*/ - false, /*PanIdSuppressed*/ - { - 0, /*SecurityLevel*/ - 0, /*KeyIdMode*/ - 0, /*KeyIndex*/ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /*Keysource*/ - } -}; - -static mlme_poll_t poll_req = { - 3, /*CoordAddrMode*/ - 0x1234, /*CoordPANId*/ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*CoordAddress*/ - { - 0, /*SecurityLevel*/ - 0, /*KeyIdMode*/ - 0, /*KeyIndex*/ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /*Keysource*/ - } -}; - -static mcps_purge_t purge_req = { - 0 /*msduHandle*/ -}; - -static mlme_set_t set_req = { - (mlme_attr_t)0x39, /*attr*/ - 0, /*attr_index*/ - NULL, /*value_pointer*/ - 0 /*value_size*/ -}; - -static mlme_get_t get_req = { - (mlme_attr_t)0x39, /*attr*/ - 0 /*attr_index*/ -}; - -static mlme_reset_t reset_req = { - true /*SetDefaultPIB*/ -}; - -static mlme_key_id_lookup_descriptor_t lookup_descriptors[LOOKUP_DESCRIPTOR_TABLE_SIZE]; -static mlme_key_device_descriptor_t device_descriptors[DEVICE_DESCRIPTOR_TABLE_SIZE]; -static mlme_key_usage_descriptor_t usage_descriptors[USAGE_DESCRIPTOR_TABLE_SIZE]; -static mlme_key_descriptor_entry_t key_descriptor = { - lookup_descriptors, /*KeyIdLookupList*/ - LOOKUP_DESCRIPTOR_TABLE_SIZE, /*KeyIdLookupListEntries*/ - device_descriptors, /*KeyDeviceList*/ - DEVICE_DESCRIPTOR_TABLE_SIZE, /*KeyDeviceListEntries*/ - usage_descriptors, /*KeyUsageList*/ - USAGE_DESCRIPTOR_TABLE_SIZE, /*KeyUsageListEntries*/ - {0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF} /*Key*/ -}; - -struct status_list_t { - uint8_t data_conf; - uint8_t get_conf; - uint8_t scan_conf; - uint8_t poll_conf; - uint8_t purge_conf; - uint8_t comm_status_ind; - uint8_t data_ind_len; - uint8_t *data_ind; -}; - -static struct status_list_t expected_statuses = { - MLME_SUCCESS, - MLME_SUCCESS, - MLME_SUCCESS, - MLME_SUCCESS, - MLME_SUCCESS, - MLME_SUCCESS, - 0, - NULL -}; - -struct beacon_list_t { - size_t count; - char *beacons[MLME_MAC_RES_SIZE_MAX]; - uint8_t beacon_lengths[MLME_MAC_RES_SIZE_MAX]; -}; - -static struct beacon_list_t received_beacons = {}; - -struct ed_scan_result_list_t { - uint8_t count; - uint8_t channel[MLME_MAC_RES_SIZE_MAX]; - uint8_t ED_values[MLME_MAC_RES_SIZE_MAX]; -}; - -static struct ed_scan_result_list_t last_ed_results; - -static void print_security(const mlme_security_t *key) -{ - if (key->SecurityLevel > 0) { - cmd_printf("Key.SecurityLevel: %u\n", key->SecurityLevel); - cmd_printf("Key.KeyIdMode: %u\n", key->KeyIdMode); - cmd_printf("Key.KeyIndex: %hhu\n", key->KeyIndex); - cmd_printf("Key.Keysource %s\n", trace_array(key->Keysource, 8)); - } -} - -static void print_PAN_descriptor(const mlme_pan_descriptor_t *desc) -{ - cmd_printf("PANDescriptor.CoordAddrMode: %u\n", desc->CoordAddrMode); - cmd_printf("PANDescriptor.CoordPANId: 0x%04X\n", desc->CoordPANId); - cmd_printf("PANDescriptor.CoordAddress: %s\n", trace_array(desc->CoordAddress, 8)); - cmd_printf("PANDescriptor.LogicalChannel: %hhu\n", desc->LogicalChannel); - cmd_printf("PANDescriptor.ChannelPage: %hhu\n", desc->ChannelPage); - cmd_printf("PANDescriptor.SuperframeSpec: %02x:%02x\n", desc->SuperframeSpec[0], desc->SuperframeSpec[1]); - cmd_printf("PANDescriptor.GTSPermit: %s\n", desc->GTSPermit ? "true" : "false"); - cmd_printf("PANDescriptor.LinkQuality: %hhu\n", desc->LinkQuality); - cmd_printf("PANDescriptor.Timestamp: %lu\n", desc->Timestamp); - cmd_printf("PANDescriptor.SecurityFailure: %hhu\n", desc->SecurityFailure); - print_security(&desc->Key); -} - -static int handle_security_args(int argc, char *argv[], mlme_security_t *key) -{ - char *str; - int32_t val; - - if (cmd_parameter_int(argc, argv, "--security_level", &val)) { - if (val >= 0 && val <= 7) { - key->SecurityLevel = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--key_id_mode", &val)) { - if (val >= 0 && val <= 3) { - key->KeyIdMode = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--key_index", &val)) { - if (val >= 0 && val <= 255) { - key->KeyIndex = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_val(argc, argv, "--key_source", &str)) { - if (strlen(str) == 2 * 8 + 7) { - if (string_to_bytes(str, key->Keysource, 8) != 0) { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - return CMDLINE_RETCODE_SUCCESS; -} - -static void add_beacon(const uint8_t *beacon, uint8_t len) -{ - if (received_beacons.count >= MLME_MAC_RES_SIZE_MAX) { - tr_warn("List of received beacons is full. Discarding %s <%.*s>", trace_array(beacon, len), len, beacon); - return; - } - unsigned int cur_beacon = received_beacons.count; - received_beacons.beacon_lengths[cur_beacon] = len; - received_beacons.beacons[cur_beacon] = (char *)ns_dyn_mem_temporary_alloc(len <= 75 ? 75 : len); - if (len != 0) { - std::memcpy(received_beacons.beacons[cur_beacon], beacon, len); - } - ++received_beacons.count; -} - -static void clear_beacons(void) -{ - for (unsigned int i = 0; i < received_beacons.count; ++i) { - ns_dyn_mem_free(received_beacons.beacons[i]); - received_beacons.beacons[i] = NULL; - received_beacons.beacon_lengths[i] = 0; - } - received_beacons.count = 0; -} - -void mac_commands_init(void) -{ - cmd_add("start", mac_start_command, "Start a PAN", MAN_MAC_START); - cmd_add("scan", mac_scan_command, "Perform a scan", MAN_MAC_SCAN); - cmd_add("data", mac_data_command, "Send data", MAN_MAC_DATA); - cmd_add("poll", mac_poll_command, "Poll for data", MAN_MAC_POLL); - cmd_add("purge", mac_purge_command, "Purge data from the transmission queue", MAN_MAC_PURGE); - cmd_add("mlme-set", mac_set_command, "Writes a given value to the PIB attribute", MAN_MAC_SET); - cmd_add("mlme-get", mac_get_command, "Gets the value of a given PIB attribute", MAN_MAC_GET); - cmd_add("mlme-reset", mac_reset_command, "Resets the MAC sublayer to default values", MAN_MAC_RESET); - cmd_add("addr", mac_address_command, "Configure MAC addresses", MAN_MAC_ADDR); - cmd_add("key", mac_key_command, "Configure or add security keys", MAN_MAC_KEY); - cmd_add("add-neigh", mac_add_neighbour_command, "Add a device to the neighbour table", MAN_MAC_ADD_NEIGHBOUR); - cmd_add("filter", mac_filter_command, "Add or remove filters based on MAC addresses", MAN_MAC_FILTER); - cmd_add("config-status", mac_config_status_command, "Set expected return statuses for confirmations and indications", MAN_MAC_CONFIG_STATUS); - cmd_add("find-beacon", mac_find_beacon_command, "Find a PAN by beacon data", MAN_MAC_FIND_BEACON); - cmd_add("wait", mac_wait_command, "Wait for data", MAN_MAC_WAIT); - cmd_add("analyze-ed", mac_analyze_ed_command, "Analyze the results of the last ED scan", MAN_MAC_ED_ANALYZE); - cmd_add("reset", reset_command, "Reset MCPS/MLME structures to default values", MAN_RESET); - cmd_add("silent-mode", silent_mode_command, "Stop printing fields of MCPS/MLME structures", MAN_SILENT); -} - -void mac_data_confirm_handler(const mac_api_t *api, const mcps_data_conf_t *data) -{ - cmd_printf("MCPS-DATA.confirm\n"); - if (!silent_mode) { - cmd_printf("msduHandle: %hhu\n", data->msduHandle); - cmd_printf("status: %hhu (%s)\n", data->status, mlme_status_string(data->status)); - cmd_printf("timestamp: %lu\n", data->timestamp); - cmd_printf("cca_retries:%hhu\n", data->cca_retries); - cmd_printf("tx_retries: %hhu\n", data->tx_retries); - } - if (data->status == expected_statuses.data_conf) { - cmd_ready(CMDLINE_RETCODE_SUCCESS); - } else { - cmd_printf("CMD failed, status: %hhu (%s)\n", data->status, mlme_status_string(data->status)); - cmd_ready(CMDLINE_RETCODE_FAIL); - } -} - -void mac_data_indication_handler(const mac_api_t *api, const mcps_data_ind_t *data) -{ - cmd_printf("MCPS-DATA.indication\n"); - if (!silent_mode) { - cmd_printf("SrcAddrMode: %u\n", data->SrcAddrMode); - cmd_printf("SrcPANId: 0x%04X\n", data->SrcPANId); - cmd_printf("SrcAddr: %s\n", trace_array(data->SrcAddr, 8)); - cmd_printf("DstAddrMode: %u\n", data->DstAddrMode); - cmd_printf("DstPANId: 0x%04X\n", data->DstPANId); - cmd_printf("DstAddr: %s\n", trace_array(data->DstAddr, 8)); - cmd_printf("mpduLinkQuality:%hhu\n", data->mpduLinkQuality); - cmd_printf("signal_dbm: %hhi\n", data->signal_dbm); - cmd_printf("timestamp: %lu\n", data->timestamp); - cmd_printf("DSN: %hhi\n", data->DSN); - print_security(&data->Key); - cmd_printf("msduLength %hu\n", data->msduLength); - cmd_printf("msdu_ptr: %s <%.*s>\n", trace_array(data->msdu_ptr, data->msduLength), data->msduLength, data->msdu_ptr); - } - if (data->msdu_ptr && expected_statuses.data_ind) { - if (data->msduLength != expected_statuses.data_ind_len) { - cmd_printf("Bad recv length %d != %d!\n", data->msduLength, expected_statuses.data_ind_len); - return; - } - if (strncmp((const char *)data->msdu_ptr, (const char *)expected_statuses.data_ind, expected_statuses.data_ind_len) == 0) { - ++data_count; - cmd_printf("Data count %d\n", data_count); - } else { - cmd_printf("Received unexpected data!\n"); - } - } -} - -void mac_purge_confirm_handler(const mac_api_t *api, mcps_purge_conf_t *data) -{ - cmd_printf("MCPS-PURGE.confirm\n"); - if (!silent_mode) { - cmd_printf("msduHandle: %hhu\n", data->msduHandle); - cmd_printf("status: %hhu (%s)\n", data->status, mlme_status_string(data->status)); - } - if (data->status == expected_statuses.purge_conf) { - cmd_ready(CMDLINE_RETCODE_SUCCESS); - } else { - cmd_printf("CMD failed, status: %hhu (%s)\n", data->status, mlme_status_string(data->status)); - cmd_ready(CMDLINE_RETCODE_FAIL); - } -} - -void mac_mlme_confirm_handler(const mac_api_t *api, mlme_primitive id, const void *data) -{ - switch (id) { - case MLME_ASSOCIATE: { - break; - } - case MLME_DISASSOCIATE: { - break; - } - case MLME_GET: { - mlme_get_conf_t *get_data = (mlme_get_conf_t *)data; - cmd_printf("MLME-GET.confirm\n"); - if (!silent_mode) { - cmd_printf("status: %hhu (%s)\n", get_data->status, mlme_status_string(get_data->status)); - cmd_printf("attr: %hhu\n", get_data->attr); - cmd_printf("attr_index: %hhu\n", get_data->attr_index); - cmd_printf("value_pointer: %s\n", trace_array((uint8_t *)get_data->value_pointer, get_data->value_size)); - cmd_printf("value_size: %hhu\n", get_data->value_size); - } - if (get_data->status == expected_statuses.get_conf) { - cmd_ready(CMDLINE_RETCODE_SUCCESS); - } else { - cmd_printf("CMD failed, status: %hhu (%s)\n", get_data->status, mlme_status_string(get_data->status)); - cmd_ready(CMDLINE_RETCODE_FAIL); - } - break; - } - case MLME_GTS: { - break; - } - case MLME_RESET: { - break; - } - case MLME_RX_ENABLE: { - break; - } - case MLME_SCAN: { - mlme_scan_conf_t *scan_data = (mlme_scan_conf_t *)data; - cmd_printf("MLME-SCAN.confirm\n"); - if (!silent_mode) { - cmd_printf("status: %hhu (%s)\n", scan_data->status, mlme_status_string(scan_data->status)); - cmd_printf("ScanType: %u\n", scan_data->ScanType); - cmd_printf("ChannelPage: %hhu\n", scan_data->ChannelPage); - cmd_printf("UnscannedChannels: 0x%08lX\n", scan_data->UnscannedChannels.channel_mask[0]); - cmd_printf("ResultListSize: %hhu\n", scan_data->ResultListSize); - } - for (unsigned int i = 0; i < scan_data->ResultListSize; ++i) { - if (scan_data->ScanType == MAC_ED_SCAN_TYPE) { - cmd_printf("Channel %d ED value: %hhu\n", channel_from_mask(scan_req.ScanChannels.channel_mask[0], i), scan_data->ED_values[i]); - memcpy(last_ed_results.ED_values, scan_data->ED_values, scan_data->ResultListSize); - last_ed_results.count = scan_data->ResultListSize; - for (int i = 0; i < scan_data->ResultListSize; ++i) { - last_ed_results.channel[i] = channel_from_mask(scan_req.ScanChannels.channel_mask[0], i); - } - } else if (scan_data->ScanType == MAC_PASSIVE_SCAN) { - print_PAN_descriptor(scan_data->PAN_values[i]); - } - } - if (scan_data->status == expected_statuses.scan_conf || scan_data->status == MLME_LIMIT_REACHED) { - cmd_ready(CMDLINE_RETCODE_SUCCESS); - } else { - cmd_printf("CMD failed, status: %hhu (%s)\n", scan_data->status, mlme_status_string(scan_data->status)); - cmd_ready(CMDLINE_RETCODE_FAIL); - } - break; - } - case MLME_SET: { - break; - } - case MLME_START: { - break; - } - case MLME_POLL: { - mlme_poll_conf_t *poll_data = (mlme_poll_conf_t *)data; - cmd_printf("MLME-POLL.confirm\n"); - if (!silent_mode) { - cmd_printf("status: %hhu (%s)\n", poll_data->status, mlme_status_string(poll_data->status)); - cmd_printf("expected status: %hhu (%s)\n", expected_statuses.poll_conf, mlme_status_string(expected_statuses.poll_conf)); - cmd_printf("data_count %u\n", data_count); - } - if (expected_statuses.poll_conf == MLME_SUCCESS) { - if (data_count == 1 && poll_data->status == MLME_SUCCESS) { - cmd_ready(CMDLINE_RETCODE_SUCCESS); - } else { - cmd_printf("CMD failed, data_count = %u, status:%hhu\n", data_count, poll_data->status); - cmd_ready(CMDLINE_RETCODE_FAIL); - } - } else if (expected_statuses.poll_conf == poll_data->status) { - cmd_ready(CMDLINE_RETCODE_SUCCESS); - } else { - cmd_printf("CMD failed, data_count = %u, status:%hhu, expected ret:%hhu\n", data_count, poll_data->status, expected_statuses.poll_conf); - cmd_ready(CMDLINE_RETCODE_FAIL); - } - break; - } - default: { - cmd_ready(CMDLINE_RETCODE_COMMAND_NOT_IMPLEMENTED); - cmd_printf("CMD failed, not implemented\n"); - break; - } - } -} - -void mac_mlme_indication_handler(const mac_api_t *api, mlme_primitive id, const void *data) -{ - switch (id) { - case MLME_ASSOCIATE: { - break; - } - case MLME_DISASSOCIATE: { - break; - } - case MLME_BEACON_NOTIFY: { - const mlme_beacon_ind_t *beacon_ind = (mlme_beacon_ind_t *)data; - cmd_printf("MLME-BEACON-NOTIFY.indication\n"); - if (!silent_mode) { - cmd_printf("BSN: %hhu\n", beacon_ind->BSN); - print_PAN_descriptor(&beacon_ind->PANDescriptor); - cmd_printf("PendAddrSpec.short_address_count %u\n", beacon_ind->PendAddrSpec.short_address_count); - cmd_printf("PendAddrSpec.extended_address_count %u\n", beacon_ind->PendAddrSpec.extended_address_count); - cmd_printf("AddrList %s\n", trace_array(beacon_ind->AddrList, beacon_ind->PendAddrSpec.short_address_count * 2 + - beacon_ind->PendAddrSpec.extended_address_count * 8)); - cmd_printf("beacon_data_length %hu\n", beacon_ind->beacon_data_length); - cmd_printf("beacon_data %s\n", trace_array(beacon_ind->beacon_data, beacon_ind->beacon_data_length)); - } - add_beacon(beacon_ind->beacon_data, beacon_ind->beacon_data_length); - break; - } - case MLME_GTS: { - break; - } - case MLME_ORPHAN: { - break; - } - case MLME_COMM_STATUS: { - cmd_printf("MLME-COMM-STATUS.indication\n"); - const mlme_comm_status_t *comm_status_ind_data = (mlme_comm_status_t *)data; - if (!silent_mode) { - cmd_printf("PANId: 0x%04X\n", comm_status_ind_data->PANId); - cmd_printf("SrcAddrMode: %u\n", comm_status_ind_data->SrcAddrMode); - cmd_printf("SrcAddr: %s\n", trace_array(comm_status_ind_data->SrcAddr, 8)); - cmd_printf("DstAddrMode: %u\n", comm_status_ind_data->DstAddrMode); - cmd_printf("DstAddr: %s\n", trace_array(comm_status_ind_data->DstAddr, 8)); - cmd_printf("status: %hhu (%s)\n", comm_status_ind_data->status, mlme_status_string(comm_status_ind_data->status)); - print_security(&comm_status_ind_data->Key); - } - break; - } - case MLME_SYNC_LOSS: { - break; - } - default: - break; - } -} - -int mac_start_command(int argc, char *argv[]) -{ - char *str; - int32_t val; - bool boolean; - - cmd_printf("MLME-START.request\n"); - if (cmd_parameter_val(argc, argv, "--pan_id", &str)) { - uint32_t pan_id = strtoul(str, NULL, 16); - if (pan_id <= 0xFFFF) { - start_req.PANId = pan_id; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--logical_channel", &val)) { - if (val >= 0 && val <= 26) { - start_req.LogicalChannel = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--channel_page", &val)) { - if (val >= 0 && val <= 2) { - start_req.ChannelPage = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--start_time", &val)) { - start_req.StartTime = val; - } - if (cmd_parameter_int(argc, argv, "--beacon_order", &val)) { - if (val >= 0 && val <= 15) { - start_req.BeaconOrder = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--super_frame_order", &val)) { - if (val >= 0 && val <= 15) { - start_req.SuperframeOrder = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_bool(argc, argv, "--pan_coordinator", &boolean)) { - start_req.PANCoordinator = boolean; - } - if (cmd_parameter_bool(argc, argv, "--battery_life_extension", &boolean)) { - start_req.BatteryLifeExtension = boolean; - } - if (cmd_parameter_bool(argc, argv, "--coord_realignment", &boolean)) { - start_req.CoordRealignment = boolean; - } - mac_interface->mlme_req(mac_interface, MLME_START, &start_req); - return CMDLINE_RETCODE_SUCCESS; -} - -int mac_scan_command(int argc, char *argv[]) -{ - char *str; - int32_t val; - - cmd_printf("MLME-SCAN.request\n"); - if (cmd_parameter_int(argc, argv, "--scan_type", &val)) { - if (val >= 0 && val <= 3) { - scan_req.ScanType = (mac_scan_type_t)val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--channel_page_enum", &val)) { - if (val >= 0 && val <= 10) { - scan_req.ScanChannels.channel_page = (channel_page_e)val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_val(argc, argv, "--channel_mask", &str)) { - scan_req.ScanChannels.channel_mask[0] = strtoul(str, NULL, 16); - } - if (cmd_parameter_int(argc, argv, "--scan_duration", &val)) { - if (val >= 0 && val <= 14) { - scan_req.ScanDuration = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--channel_page", &val)) { - if (val >= 0 && val <= 2) { - scan_req.ChannelPage = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (handle_security_args(argc, argv, &scan_req.Key) != CMDLINE_RETCODE_SUCCESS) { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - clear_beacons(); - mac_interface->mlme_req(mac_interface, MLME_SCAN, &scan_req); - return CMDLINE_RETCODE_EXCUTING_CONTINUE; -} - -int mac_data_command(int argc, char *argv[]) -{ - char *str; - int32_t val; - bool boolean; - - cmd_printf("MCPS-DATA.request\n"); - if (cmd_parameter_int(argc, argv, "--src_addr_mode", &val)) { - if (val == 0 || val == 2 || val == 3) { - data_req.SrcAddrMode = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--dst_addr_mode", &val)) { - if (val == 0 || val == 2 || val == 3) { - data_req.DstAddrMode = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_val(argc, argv, "--dst_pan_id", &str)) { - uint32_t pan_id = strtoul(str, NULL, 16); - if (pan_id <= 0xFFFF) { - data_req.DstPANId = pan_id; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_val(argc, argv, "--dst_addr", &str)) { - int len = (data_req.DstAddrMode == 2 ? 2 : 8); - if (string_to_bytes(str, data_req.DstAddr, len) != 0) { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--msdu_length", &val)) { - data_req.msduLength = val; - } - if (cmd_parameter_val(argc, argv, "--msdu", &str)) { - ns_dyn_mem_free(data_req.msdu); - if (strlen(str) != data_req.msduLength) { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - data_req.msdu = (uint8_t *)ns_dyn_mem_temporary_alloc(data_req.msduLength); - if (data_req.msdu == NULL) { - tr_error("Failed to allocate memory for the msdu"); - return CMDLINE_RETCODE_FAIL; - } - std::memcpy(data_req.msdu, str, data_req.msduLength); - } - if (cmd_parameter_int(argc, argv, "--msdu_handle", &val)) { - if (val >= 0 && val <= 255) { - data_req.msduHandle = val; - } - } - if (cmd_parameter_bool(argc, argv, "--tx_ack_req", &boolean)) { - data_req.TxAckReq = boolean; - } - if (cmd_parameter_bool(argc, argv, "--indirect_tx", &boolean)) { - data_req.InDirectTx = boolean; - } - if (cmd_parameter_bool(argc, argv, "--pending_bit", &boolean)) { - data_req.PendingBit = boolean; - } - if (cmd_parameter_bool(argc, argv, "--wait_for_confirm", &boolean)) { - wait_for_confirm = boolean; - } - if (handle_security_args(argc, argv, &data_req.Key) != CMDLINE_RETCODE_SUCCESS) { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - mac_interface->mcps_data_req(mac_interface, &data_req); - if (wait_for_confirm) { - return CMDLINE_RETCODE_EXCUTING_CONTINUE; - } - return CMDLINE_RETCODE_SUCCESS; -} - -int mac_poll_command(int argc, char *argv[]) -{ - char *str; - int32_t val; - - cmd_printf("MLME-POLL.request\n"); - data_count = 0; - if (cmd_parameter_int(argc, argv, "--coord_addr_mode", &val)) { - if (val == 2 || val == 3) { - poll_req.CoordAddrMode = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_val(argc, argv, "--coord_pan_id", &str)) { - unsigned long pan_id = strtoul(str, NULL, 16); - if (pan_id <= 0xFFFF) { - poll_req.CoordPANId = pan_id; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_val(argc, argv, "--coord_address", &str)) { - int len = (poll_req.CoordAddrMode == 2 ? 2 : 8); - if (string_to_bytes(str, poll_req.CoordAddress, len) != 0) { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (handle_security_args(argc, argv, &poll_req.Key) != CMDLINE_RETCODE_SUCCESS) { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - mac_interface->mlme_req(mac_interface, MLME_POLL, &poll_req); - return CMDLINE_RETCODE_EXCUTING_CONTINUE; -} - -int mac_purge_command(int argc, char *argv[]) -{ - int32_t val; - - cmd_printf("MCPS-PURGE.request\n"); - if (cmd_parameter_int(argc, argv, "--msdu_handle", &val)) { - if (val >= 0 && val <= 255) { - purge_req.msduHandle = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - mac_interface->mcps_purge_req(mac_interface, &purge_req); - return CMDLINE_RETCODE_EXCUTING_CONTINUE; -} - -int mac_set_command(int argc, char *argv[]) -{ - char *str; - int32_t val; - uint8_t val_uint8 = 0; - uint16_t val_uint16 = 0; - uint32_t val_uint32 = 0; - uint8_t *val_ptr_array = NULL; - - cmd_printf("MLME-SET.request\n"); - if (cmd_parameter_val(argc, argv, "--attr", &str)) { - uint32_t attribute = strtoul(str, NULL, 16); - if (attribute <= 255) { - set_req.attr = (mlme_attr_t)attribute; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--attr_index", &val)) { - if (val >= 0 && val <= 255) { - set_req.attr_index = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_val(argc, argv, "--value_ascii", &str)) { - val_ptr_array = (uint8_t *)ns_dyn_mem_temporary_alloc(strlen(str)); - if (val_ptr_array == NULL) { - tr_error("Failed to allocate memory for MLME-SET.request"); - return CMDLINE_RETCODE_FAIL; - } - std::memcpy(val_ptr_array, str, strlen(str)); - set_req.value_pointer = val_ptr_array; - } else if (cmd_parameter_val(argc, argv, "--value_bytes", &str)) { - size_t bytes = (strlen(str) + 1) / 3; - val_ptr_array = (uint8_t *)ns_dyn_mem_temporary_alloc(bytes); - if (val_ptr_array == NULL) { - tr_error("Failed to allocate memory for MLME-SET.request"); - return CMDLINE_RETCODE_FAIL; - } - if (string_to_bytes(str, val_ptr_array, bytes) != 0) { - ns_dyn_mem_free(val_ptr_array); - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - set_req.value_pointer = val_ptr_array; - } else if (cmd_parameter_int(argc, argv, "--value_uint8", &val)) { - if (val >= 0 && val <= 0xFF) { - val_uint8 = val; - set_req.value_pointer = &val_uint8; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else if (cmd_parameter_int(argc, argv, "--value_uint16", &val)) { - if (val >= 0 && val <= 0xFFFF) { - val_uint16 = val; - set_req.value_pointer = &val_uint16; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else if (cmd_parameter_int(argc, argv, "--value_uint32", &val)) { - if (val >= 0 && val <= 0x7FFFFFFF) { - val_uint32 = val; - set_req.value_pointer = &val_uint32; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--value_size", &val)) { - if (val >= 0 && val <= 255) { - set_req.value_size = val; - } - } - - mac_interface->mlme_req(mac_interface, MLME_SET, &set_req); - ns_dyn_mem_free(val_ptr_array); - set_req.value_pointer = NULL; - return CMDLINE_RETCODE_SUCCESS; -} - -int mac_get_command(int argc, char *argv[]) -{ - char *str; - int32_t val; - - cmd_printf("MLME-GET.request\n"); - if (cmd_parameter_val(argc, argv, "--attr", &str)) { - uint32_t attribute = strtoul(str, NULL, 16); - if (attribute <= 255) { - get_req.attr = (mlme_attr_t)attribute; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--attr_index", &val)) { - if (val >= 0 && val <= 255) { - get_req.attr_index = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - mac_interface->mlme_req(mac_interface, MLME_GET, &get_req); - return CMDLINE_RETCODE_SUCCESS; -} - -int mac_reset_command(int argc, char *argv[]) -{ - bool boolean; - - cmd_printf("MLME-RESET.request\n"); - if (cmd_parameter_bool(argc, argv, "--set_default_pib", &boolean)) { - reset_req.SetDefaultPIB = boolean; - } - mac_interface->mlme_req(mac_interface, MLME_RESET, &reset_req); - return CMDLINE_RETCODE_SUCCESS; -} - -int mac_address_command(int argc, char *argv[]) -{ - char *str; - uint8_t ext_addr[8]; - - if (cmd_parameter_val(argc, argv, "--64-bit", &str)) { - if (string_to_bytes(str, ext_addr, 8) != 0) { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - mac_interface->mac64_set(mac_interface, ext_addr); - cmd_printf("64-bit MAC address set to: %s\n", trace_array(ext_addr, 8)); - } else if (cmd_parameter_val(argc, argv, "--16-bit", &str)) { - uint32_t short_addr_32 = strtoul(str, NULL, 16); - if (short_addr_32 <= 0xFFFF) { - uint16_t short_addr = short_addr_32; - mlme_set_t set_req; - set_req.attr = macShortAddress; - set_req.value_pointer = &short_addr; - set_req.value_size = 2; - mac_interface->mlme_req(mac_interface, MLME_SET, &set_req); - cmd_printf("16-bit MAC address set to: 0x%04X\n", short_addr); - } else { - tr_warn("Invalid 16-bit MAC address given: %lu", short_addr_32); - } - } else if (argc == 1) { - if (mac_interface->mac64_get(mac_interface, MAC_EXTENDED_READ_ONLY, ext_addr) == 0) { - cmd_printf("EUI64: %s\n", trace_array(ext_addr, 8)); - } else { - tr_warn("Failed to read EUI64"); - return CMDLINE_RETCODE_FAIL; - } - if (mac_interface->mac64_get(mac_interface, MAC_EXTENDED_DYNAMIC, ext_addr) == 0) { - cmd_printf("MAC64: %s\n", trace_array(ext_addr, 8)); - } else { - tr_warn("Failed to read MAC64"); - return CMDLINE_RETCODE_FAIL; - } - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - return CMDLINE_RETCODE_SUCCESS; -} - -static int key_config_command(int argc, char *argv[]) -{ - char *str; - int32_t val; - bool boolean; - int lookup_index = 0, device_index = 0, usage_index = 0; - - if (cmd_parameter_val(argc, argv, "--key", &str)) { - if (strlen(str) == 2 * 16 + 15) { - if (string_to_bytes(str, key_descriptor.Key, 16) != 0) { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--key_id_lookup_list_entries", &val)) { - if (val >= 0 && val < LOOKUP_DESCRIPTOR_TABLE_SIZE) { - key_descriptor.KeyIdLookupListEntries = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--key_device_list_entries", &val)) { - if (val >= 0 && val < DEVICE_DESCRIPTOR_TABLE_SIZE) { - key_descriptor.KeyDeviceListEntries = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--key_usage_list_entries", &val)) { - if (val >= 0 && val < USAGE_DESCRIPTOR_TABLE_SIZE) { - key_descriptor.KeyUsageListEntries = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--lookup_index", &val)) { - if (val >= 0 && val < LOOKUP_DESCRIPTOR_TABLE_SIZE) { - lookup_index = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_val(argc, argv, "--lookup_data", &str)) { - if (strlen(str) == 2 * 9 + 8) { - if (string_to_bytes(str, key_descriptor.KeyIdLookupList[lookup_index].LookupData, 9) != 0) { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--lookup_data_size", &val)) { - if (val == 0 || val == 1) { - key_descriptor.KeyIdLookupList[lookup_index].LookupDataSize = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--device_list_index", &val)) { - if (val >= 0 && val < DEVICE_DESCRIPTOR_TABLE_SIZE) { - device_index = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--device_descriptor_handle", &val)) { - if (val >= 0 && val <= 255) { - key_descriptor.KeyDeviceList[device_index].DeviceDescriptorHandle = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_bool(argc, argv, "--unique_device", &boolean)) { - key_descriptor.KeyDeviceList[device_index].UniqueDevice = boolean; - } - if (cmd_parameter_bool(argc, argv, "--blacklisted", &boolean)) { - key_descriptor.KeyDeviceList[device_index].Blacklisted = boolean; - } - if (cmd_parameter_int(argc, argv, "--usage_index", &val)) { - if (val >= 0 && val <= USAGE_DESCRIPTOR_TABLE_SIZE) { - usage_index = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--frame_type", &val)) { - if (val >= 0 && val <= 3) { - key_descriptor.KeyUsageList[usage_index].FrameType = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (key_descriptor.KeyUsageList[usage_index].FrameType == 3) { - if (cmd_parameter_int(argc, argv, "--command_frame_identifier", &val)) { - if (val >= 1 && val <= 9) { - key_descriptor.KeyUsageList[usage_index].CommandFrameIdentifier = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - } - return CMDLINE_RETCODE_SUCCESS; -} - -static int key_add_command(int argc, char *argv[]) -{ - mlme_set_t set_req; - int32_t val; - int key_index = 0; - - if (cmd_parameter_int(argc, argv, "--index", &val)) { - if (val >= 0 && val <= 255) { - key_index = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - - set_req.attr = macKeyTable; - set_req.attr_index = key_index; - set_req.value_pointer = &key_descriptor; - set_req.value_size = sizeof(mlme_key_descriptor_entry_t); - mac_interface->mlme_req(mac_interface, MLME_SET, &set_req); - return CMDLINE_RETCODE_SUCCESS; -} - -int mac_key_command(int argc, char *argv[]) -{ - char *cmd = argv[1]; - - if (strcmp(cmd, "config") == 0) { - return key_config_command(argc, argv); - } else if (strcmp(cmd, "add") == 0) { - return key_add_command(argc, argv); - } - return CMDLINE_RETCODE_INVALID_PARAMETERS; -} - -int mac_add_neighbour_command(int argc, char *argv[]) -{ - char *str; - int32_t val; - mlme_device_descriptor_t neighbour; - mlme_set_t set_req; - - neighbour.Exempt = false; - if (cmd_parameter_int(argc, argv, "--frame_ctr", &val)) { - neighbour.FrameCounter = val; - } - if (cmd_parameter_val(argc, argv, "--mac16", &str)) { - uint32_t short_addr = strtoul(str, NULL, 16); - if (short_addr <= 0xFFFF) { - neighbour.ShortAddress = short_addr; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_val(argc, argv, "--mac64", &str)) { - if (strlen(str) == 2 * 8 + 7) { - if (string_to_bytes(str, neighbour.ExtAddress, 8) != 0) { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_val(argc, argv, "--pan_id", &str)) { - uint32_t pan_id = strtoul(str, NULL, 16); - if (pan_id <= 0xFFFF) { - neighbour.PANId = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - if (cmd_parameter_int(argc, argv, "--index", &val)) { - if (val >= 0 && val <= 255) { - set_req.attr_index = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - - set_req.attr = macDeviceTable; - set_req.value_pointer = &neighbour; - set_req.value_size = sizeof(mlme_device_descriptor_t); - mac_interface->mlme_req(mac_interface, MLME_SET, &set_req); - return CMDLINE_RETCODE_SUCCESS; -} - -#ifndef DISABLE_FILTERING -static int filter_start(int argc, char *argv[]) -{ - char *str; - - if (cmd_parameter_val(argc, argv, "--mode", &str)) { - if (strcmp(str, "allow") == 0) { - return mac_filter_start(mac_interface->parent_id, MAC_FILTER_ALLOWED) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS; - } else if (strcmp(str, "block") == 0) { - return mac_filter_start(mac_interface->parent_id, MAC_FILTER_BLOCKED) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS;; - } else if (strcmp(str, "fixed") == 0) { - int32_t lqi, dbm; - if (cmd_parameter_int(argc, argv, "--lqi_m", &lqi) && - cmd_parameter_int(argc, argv, "--dbm_m", &dbm)) { - return mac_filter_start(mac_interface->parent_id, MAC_FILTER_FIXED(lqi, dbm)) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS; - } - } - } - return CMDLINE_RETCODE_INVALID_PARAMETERS; -} - -static int filter_add(int argc, char *argv[]) -{ - char *str; - uint32_t short_addr; - uint8_t long_addr[8]; - int32_t lqi_m, lqi_add, dbm_m, dbm_add; - - if (cmd_parameter_int(argc, argv, "--lqi_m", &lqi_m) && - cmd_parameter_int(argc, argv, "--lqi_add", &lqi_add) && - cmd_parameter_int(argc, argv, "--dbm_m", &dbm_m) && - cmd_parameter_int(argc, argv, "--dbm_add", &dbm_add)) { - } else if (cmd_parameter_val(argc, argv, "--mode", &str)) { - if (strcmp(str, "allow")) { - lqi_m = dbm_m = 256; - lqi_add = dbm_add = 0; - } else if (strcmp(str, "block")) { - lqi_m = lqi_add = dbm_m = dbm_add = 0; - } else if (strcmp(str, "fixed")) { - lqi_add = dbm_add = 0; - if (cmd_parameter_int(argc, argv, "--lqi_m", &lqi_m) && - cmd_parameter_int(argc, argv, "--dbm_m", &dbm_m)) { - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - - if (cmd_parameter_val(argc, argv, "--short", &str)) { - short_addr = strtoul(str, NULL, 16); - if (short_addr <= 0xFFFF) { - return mac_filter_add_short(mac_interface->parent_id, short_addr, lqi_m, lqi_add, dbm_m, dbm_add) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else if (cmd_parameter_val(argc, argv, "--long", &str)) { - if (string_to_bytes(str, long_addr, 8) != 0) { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - return mac_filter_add_long(mac_interface->parent_id, long_addr, lqi_m, lqi_add, dbm_m, dbm_add) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } -} - -static int filter_remove(int argc, char *argv[]) -{ - char *str; - uint32_t short_addr; - uint8_t long_addr[8]; - - if (cmd_parameter_val(argc, argv, "--short", &str)) { - short_addr = strtoul(str, NULL, 16); - if (short_addr <= 0xFFFF) { - return mac_filter_delete_short(mac_interface->parent_id, short_addr) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else if (cmd_parameter_val(argc, argv, "--long", &str)) { - if (string_to_bytes(str, long_addr, 8) != 0) { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - return mac_filter_delete_long(mac_interface->parent_id, long_addr) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } -} - -static int filter_clear(int argc, char *argv[]) -{ - return mac_filter_clear(mac_interface->parent_id) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS; -} - -static int filter_stop(int argc, char *argv[]) -{ - mac_filter_stop(mac_interface->parent_id); - return CMDLINE_RETCODE_SUCCESS; -} -#else -static int filter_start(int argc, char *argv[]) -{ - (void)argc; - (void)argv; - return 0; -} - -static int filter_add(int argc, char *argv[]) -{ - (void)argc; - (void)argv; - return 0; -} -static int filter_remove(int argc, char *argv[]) -{ - (void)argc; - (void)argv; - return 0; -} -static int filter_clear(int argc, char *argv[]) -{ - (void)argc; - (void)argv; - return 0; -} -static int filter_stop(int argc, char *argv[]) -{ - (void)argc; - (void)argv; - return 0; -} -#endif -int mac_filter_command(int argc, char *argv[]) -{ - char *cmd = argv[1]; - - if (strcmp(cmd, "start") == 0) { - return filter_start(argc, argv); - } else if (strcmp(cmd, "add") == 0) { - return filter_add(argc, argv); - } else if (strcmp(cmd, "remove") == 0) { - return filter_remove(argc, argv); - } else if (strcmp(cmd, "clear") == 0) { - return filter_clear(argc, argv); - } else if (strcmp(cmd, "stop") == 0) { - return filter_stop(argc, argv); - } - return CMDLINE_RETCODE_INVALID_PARAMETERS; -} - -int mac_config_status_command(int argc, char *argv[]) -{ - int32_t val; - char *str; - - if (cmd_parameter_int(argc, argv, "--data_conf", &val)) { - if (val >= 0 && val <= 255) { - expected_statuses.data_conf = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else if (cmd_parameter_val(argc, argv, "--data_ind", &str)) { - size_t len = strlen(str); - ns_dyn_mem_free(expected_statuses.data_ind); - expected_statuses.data_ind = (uint8_t *)ns_dyn_mem_temporary_alloc(len); - expected_statuses.data_ind_len = len; - std::memcpy(expected_statuses.data_ind, str, len); - } else if (cmd_parameter_int(argc, argv, "--get", &val)) { - if (val >= 0 && val <= 255) { - expected_statuses.get_conf = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else if (cmd_parameter_int(argc, argv, "--scan", &val)) { - if (val >= 0 && val <= 255) { - expected_statuses.scan_conf = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else if (cmd_parameter_int(argc, argv, "--poll", &val)) { - if (val >= 0 && val <= 255) { - expected_statuses.poll_conf = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else if (cmd_parameter_int(argc, argv, "--purge", &val)) { - if (val >= 0 && val <= 255) { - expected_statuses.purge_conf = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else if (cmd_parameter_int(argc, argv, "--comm_status", &val)) { - if (val >= 0 && val <= 255) { - expected_statuses.comm_status_ind = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else if (cmd_parameter_index(argc, argv, "--list") != -1) { - for (unsigned int i = 0; i < 256; ++i) { - const char *status = mlme_status_string(i); - if (status) { - cmd_printf("%hhu\t%s\n", i, status); - } - } - } else if (cmd_parameter_index(argc, argv, "--reset") != -1) { - expected_statuses.data_conf = MLME_SUCCESS; - expected_statuses.get_conf = MLME_SUCCESS; - expected_statuses.scan_conf = MLME_SUCCESS; - expected_statuses.poll_conf = MLME_SUCCESS; - expected_statuses.purge_conf = MLME_SUCCESS; - expected_statuses.comm_status_ind = MLME_SUCCESS; - expected_statuses.data_ind_len = 0; - expected_statuses.data_ind = NULL; - } else if (argc == 1) { - cmd_printf("MCPS-DATA.confirm: %d (%s)\n", expected_statuses.data_conf, mlme_status_string(expected_statuses.data_conf)); - cmd_printf("MLME-GET.confirm: %d (%s)\n", expected_statuses.get_conf, mlme_status_string(expected_statuses.get_conf)); - cmd_printf("MLME-SCAN.confirm: %d (%s)\n", expected_statuses.scan_conf, mlme_status_string(expected_statuses.scan_conf)); - cmd_printf("MLME-POLL.confirm: %d (%s)\n", expected_statuses.poll_conf, mlme_status_string(expected_statuses.poll_conf)); - cmd_printf("MCPS.PURGE.confirm. %d (%s)\n", expected_statuses.purge_conf, mlme_status_string(expected_statuses.purge_conf)); - cmd_printf("MLME-COMM-STATUS.indication: %d (%s)\n", expected_statuses.comm_status_ind, mlme_status_string(expected_statuses.comm_status_ind)); - cmd_printf("MCPS-DATA.indication: %s <%.*s>\n", trace_array(expected_statuses.data_ind, expected_statuses.data_ind_len), expected_statuses.data_ind_len, expected_statuses.data_ind); - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - return CMDLINE_RETCODE_SUCCESS; -} - -int mac_find_beacon_command(int argc, char *argv[]) -{ - char *str; - - if (cmd_parameter_val(argc, argv, "--data", &str)) { - for (int i = 0; i < MLME_MAC_RES_SIZE_MAX; ++i) { - if (received_beacons.beacons[i] == NULL) { - continue; - } - if (strncmp(received_beacons.beacons[i], str, received_beacons.beacon_lengths[i]) == 0) { - return CMDLINE_RETCODE_SUCCESS; - } - } - return CMDLINE_RETCODE_FAIL; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } -} - -int mac_wait_command(int argc, char *argv[]) -{ - int32_t val; - static uint32_t timeout_ms = 1000; - int remaining_ms = timeout_ms; - if (cmd_parameter_int(argc, argv, "--timeout", &val)) { - if (val >= 0) { - timeout_ms = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } - while (data_count < 1) { - ThisThread::sleep_for(10); - remaining_ms -= 10; - if (remaining_ms <= 0) { - return CMDLINE_RETCODE_FAIL; - } - } - data_count = 0; - return CMDLINE_RETCODE_SUCCESS; -} - -int mac_analyze_ed_command(int argc, char *argv[]) -{ - int32_t val; - int channel; - - if (cmd_parameter_int(argc, argv, "--channel", &val)) { - if (val >= 0 && val <= 26) { - channel = val; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - - if (cmd_parameter_int(argc, argv, "--above", &val)) { - for (int i = 0; i < last_ed_results.count; ++i) { - if (last_ed_results.channel[i] == channel) { - return last_ed_results.ED_values[i] >= val ? CMDLINE_RETCODE_SUCCESS : CMDLINE_RETCODE_FAIL; - } - } - } else if (cmd_parameter_int(argc, argv, "--below", &val)) { - for (int i = 0; i < last_ed_results.count; ++i) { - if (last_ed_results.channel[i] == channel) { - return last_ed_results.ED_values[i] <= val ? CMDLINE_RETCODE_SUCCESS : CMDLINE_RETCODE_FAIL; - } - } - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } - return CMDLINE_RETCODE_FAIL; -} - -static void reset_security(mlme_security_t *sec) -{ - sec->SecurityLevel = 0; - sec->KeyIdMode = 0; - sec->KeyIndex = 0; - memset(sec->Keysource, 0, 8); -} - -int reset_command(int argc, char *argv[]) -{ - wait_for_confirm = true; - silent_mode = false; - data_count = 0; - - start_req.PANId = 0x1234; - start_req.LogicalChannel = 11; - start_req.ChannelPage = 0; - start_req.StartTime = 0; - start_req.BeaconOrder = 15; - start_req.SuperframeOrder = 15; - start_req.PANCoordinator = true; - start_req.BatteryLifeExtension = false; - start_req.CoordRealignment = false; - reset_security(&start_req.CoordRealignKey); - reset_security(&start_req.BeaconRealignKey); - - scan_req.ScanType = MAC_ACTIVE_SCAN; - scan_req.ScanChannels.channel_page = CHANNEL_PAGE_0; - scan_req.ScanChannels.channel_mask[0] = 0x07FFF800; - reset_security(&scan_req.Key); - - data_req.SrcAddrMode = 3; - data_req.DstAddrMode = 3; - data_req.DstPANId = 0x1234; - memset(data_req.DstAddr, 0, 8); - data_req.msduLength = 0; - data_req.msdu = NULL; - data_req.msduHandle = 0; - data_req.TxAckReq = true; - data_req.InDirectTx = false; - data_req.PendingBit = false; - reset_security(&data_req.Key); - - poll_req.CoordAddrMode = 3; - poll_req.CoordPANId = 0x1234; - memset(poll_req.CoordAddress, 0, 8); - reset_security(&poll_req.Key); - - purge_req.msduHandle = 0; - - set_req.attr = (mlme_attr_t)0x39; - set_req.attr_index = 0; - set_req.value_pointer = NULL; - set_req.value_size = 0; - - get_req.attr = (mlme_attr_t)0x39; - get_req.attr_index = 0; - - reset_req.SetDefaultPIB = true; - - return CMDLINE_RETCODE_SUCCESS; -} - -int silent_mode_command(int argc, char *argv[]) -{ - char *cmd; - if (argc < 2) { - return CMDLINE_RETCODE_FAIL; - } - cmd = argv[1]; - if (strcmp(cmd, "on") == 0) { - silent_mode = true; - return CMDLINE_RETCODE_SUCCESS; - } else if (strcmp(cmd, "off") == 0) { - silent_mode = false; - return CMDLINE_RETCODE_SUCCESS; - } else { - return CMDLINE_RETCODE_INVALID_PARAMETERS; - } -} diff --git a/TEST_APPS/device/nanostack_mac_tester/source/mac_commands.h b/TEST_APPS/device/nanostack_mac_tester/source/mac_commands.h deleted file mode 100644 index a15d97faf67..00000000000 --- a/TEST_APPS/device/nanostack_mac_tester/source/mac_commands.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2017, Arm Limited and affiliates. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef MAC_COMMANDS_H_ -#define MAC_COMMANDS_H_ - -#include -#include - -#include "ns_cmdline.h" -#include "nsdynmemLIB.h" -#include "mbed_trace.h" -#include "mac_api.h" -#include "mlme.h" -#include "mac_mcps.h" -#include "mac_common_defines.h" -#include "mac_filter_api.h" -#include "mac_tester_util.h" - -#define LOOKUP_DESCRIPTOR_TABLE_SIZE 2 -#define DEVICE_DESCRIPTOR_TABLE_SIZE 2 -#define USAGE_DESCRIPTOR_TABLE_SIZE 2 -#define KEY_DESCRIPTOR_TABLE_SIZE 2 - -void mac_commands_init(void); - -void mac_data_confirm_handler(const mac_api_t *api, const mcps_data_conf_t *data); -void mac_data_indication_handler(const mac_api_t *api, const mcps_data_ind_t *data); -void mac_purge_confirm_handler(const mac_api_t *api, mcps_purge_conf_t *data); -void mac_mlme_confirm_handler(const mac_api_t *api, mlme_primitive id, const void *data); -void mac_mlme_indication_handler(const mac_api_t *api, mlme_primitive id, const void *data); - -int mac_start_command(int argc, char *argv[]); -int mac_scan_command(int argc, char *argv[]); -int mac_data_command(int argc, char *argv[]); -int mac_poll_command(int argc, char *argv[]); -int mac_purge_command(int argc, char *argv[]); -int mac_set_command(int argc, char *argv[]); -int mac_get_command(int argc, char *argv[]); -int mac_reset_command(int argc, char *argv[]); -int mac_address_command(int argc, char *argv[]); -int mac_key_command(int argc, char *argv[]); -int mac_add_neighbour_command(int argc, char *argv[]); -int mac_filter_command(int argc, char *argv[]); -int mac_config_status_command(int argc, char *argv[]); -int mac_find_beacon_command(int argc, char *argv[]); -int mac_wait_command(int argc, char *argv[]); -int mac_analyze_ed_command(int argc, char *argv[]); -int reset_command(int argc, char *argv[]); -int silent_mode_command(int argc, char *argv[]); - -#endif diff --git a/TEST_APPS/device/nanostack_mac_tester/source/mac_tester_util.cpp b/TEST_APPS/device/nanostack_mac_tester/source/mac_tester_util.cpp deleted file mode 100644 index 15fec17bef9..00000000000 --- a/TEST_APPS/device/nanostack_mac_tester/source/mac_tester_util.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2017, Arm Limited and affiliates. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "mac_tester_util.h" - -int string_to_bytes(const char *str, uint8_t *buf, int bytes) -{ - int len = strlen(str); - - if (len <= (3 * bytes - 1)) { - int i; - - for (i = 0; i < bytes; ++i) { - if (i * 3 < len) { - buf[i] = (uint8_t)strtoul(str + i * 3, NULL, 16); - } else { - buf[i] = 0; - } - } - return 0; - } - return -1; -} - -const char *mlme_status_string(uint8_t status) -{ - switch (status) { - case MLME_SUCCESS: - return "MLME_SUCCESS"; - case MLME_BUSY_CHAN: - return "MLME_BUSY_CHAN"; - case MLME_BUSY_RX: - return "MLME_BUSY_RX"; - case MLME_BUSY_TX: - return "MLME_BUSY_TX"; - case MLME_FORCE_TRX_OFF: - return "MLME_FORCE_TRX_OFF"; - case MLME_IDLE: - return "MLME_IDLE"; - case MLME_RX_ON: - return "MLME_RX_ON"; - case MLME_TRX_OFF: - return "MLME_TRX_OFF"; - case MLME_TX_ON: - return "MLME_TX_ON"; - case MLME_COUNTER_ERROR: - return "MLME_COUNTER_ERROR"; - case MLME_IMPROPER_KEY_TYPE: - return "MLME_IMPROPER_KEY_TYPE"; - case MLME_IMPROPER_SECURITY_LEVEL: - return "MLME_IMPROPER_SECURITY_LEVEL"; - case MLME_UNSUPPORTED_LEGACY: - return "MLME_UNSUPPORTED_LEGACY"; - case MLME_UNSUPPORTED_SECURITY: - return "MLME_UNSUPPORTED_SECURITY"; - case MLME_SECURITY_FAIL: - return "MLME_SECURITY_FAIL"; - case MLME_FRAME_TOO_LONG: - return "MLME_FRAME_TOO_LONG"; - case MLME_INVALID_HANDLE: - return "MLME_INVALID_HANDLE"; - case MLME_INVALID_PARAMETER: - return "MLME_INVALID_PARAMETER"; - case MLME_TX_NO_ACK: - return "MLME_TX_NO_ACK"; - case MLME_NO_BEACON: - return "MLME_NO_BEACON"; - case MLME_NO_DATA: - return "MLME_NO_DATA"; - case MLME_NO_SHORT_ADDRESS: - return "MLME_NO_SHORT_ADDRESS"; - case MLME_PAN_ID_CONFLICT: - return "MLME_PAN_ID_CONFLICT"; - case MLME_TRANSACTION_EXPIRED: - return "MLME_TRANSACTION_EXPIRED"; - case MLME_TRANSACTION_OVERFLOW: - return "MLME_TRANSACTION_OVERFLOW"; - case MLME_UNAVAILABLE_KEY: - return "MLME_UNAVAILABLE_KEY"; - case MLME_UNSUPPORTED_ATTRIBUTE: - return "MLME_UNSUPPORTED_ATTRIBUTE"; - case MLME_INVALID_ADDRESS: - return "MLME_INVALID_ADDRESS"; - case MLME_INVALID_INDEX: - return "MLME_INVALID_INDEX"; - case MLME_LIMIT_REACHED: - return "MLME_LIMIT_REACHED"; - case MLME_READ_ONLY: - return "MLME_READ_ONLY"; - case MLME_SCAN_IN_PROGRESS: - return "MLME_SCAN_IN_PROGRESS"; - case MLME_DATA_POLL_NOTIFICATION: - return "MLME_DATA_POLL_NOTIFICATION"; - default: - return NULL; - } -} - -int channel_from_mask(uint32_t channel_mask, int index) -{ - int expected_index = 0; - for (int i = 0; i < 27; ++i) { - if ((channel_mask >> i) & 1) { - if (expected_index == index) { - return i; - } - ++expected_index; - } - } - return -1; -} diff --git a/TEST_APPS/device/nfcapp/NFCCommands.cpp b/TEST_APPS/device/nfcapp/NFCCommands.cpp deleted file mode 100644 index d9c6a609f1c..00000000000 --- a/TEST_APPS/device/nfcapp/NFCCommands.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2018 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include -#include -#include -#include -#include "mbed_events.h" -#include "mbed-client-cli/ns_cmdline.h" -#include "rtos/Thread.h" -#include "NFCTestShim.h" -#include "NFCCommands.h" - -#if MBED_CONF_NFCEEPROM -#include "NFCEEPROMDriver.h" -#include "NFCProcessEEPROM.h" -#endif - -using mbed::nfc::nfc_rf_protocols_bitmask_t; - -events::EventQueue HandleTestCommand::_nfcQueue; - -rtos::Thread nfcThread; -bool human_trace_enabled = true; - -NFCTestShim *HandleTestCommand::new_testshim() -{ -#if MBED_CONF_NFCEEPROM - mbed::nfc::NFCEEPROMDriver &eeprom_driver = get_eeprom_driver(_nfcQueue); - - return ((NFCTestShim *)(new NFCProcessEEPROM(_nfcQueue, eeprom_driver))); -#else - return ((NFCTestShim *)(new NFCProcessController(_nfcQueue))); -#endif // EEPROM - -} - -void HandleTestCommand::nfc_routine() -{ - _nfcQueue.dispatch_forever(); -} - -void trace_printf(const char *fmt, ...) -{ - if (human_trace_enabled) { - va_list ap; - va_start(ap, fmt); - cmd_vprintf(fmt, ap); - va_end(ap); - } -} - -HandleTestCommand::HandleTestCommand() -{ - osStatus status = nfcThread.start(mbed::callback(&HandleTestCommand::nfc_routine)); - MBED_ASSERT(status == osOK); -} - -int HandleTestCommand::cmd_get_last_nfc_error(int argc, char *argv[]) -{ - _nfcQueue.call(NFCTestShim::cmd_get_last_nfc_error); - return (CMDLINE_RETCODE_EXCUTING_CONTINUE); -} - -/** returns compile time flag if NFC EEPROM was compiled */ -int HandleTestCommand::cmd_get_conf_nfceeprom(int argc, char *argv[]) -{ - _nfcQueue.call(NFCTestShim::cmd_get_conf_nfceeprom); - return (CMDLINE_RETCODE_EXCUTING_CONTINUE); -} - - - -int HandleTestCommand::cmd_set_trace(int argc, char *argv[]) -{ - human_trace_enabled = false; - if (argc > 1) { - static char buffer[7]; - char *p_buffer = buffer; - strncpy(buffer, argv[1], sizeof(buffer) - 1); - buffer[sizeof(buffer) - 1] = 0; - while (*p_buffer) { - *p_buffer = toupper(*p_buffer); - p_buffer++; - } - cmd_printf(buffer); - human_trace_enabled = (0 == strcmp(buffer, "TRUE")) || (0 == strcmp(buffer, "1")) || (0 == strcmp(buffer, "ON")); - } - cmd_printf("set trace '%s'", (human_trace_enabled ? "true" : "false")); - return (CMDLINE_RETCODE_SUCCESS); -} - - -//////////////////////////////////////////////////////////////////////////////////// - -int HandleTestCommand::cmd_set_last_nfc_error(int argc, char *argv[]) -{ - if (argc <= 1) { - cmd_printf("setlastnfcerror() invalid parameter(s)\r\n"); - return (CMDLINE_RETCODE_INVALID_PARAMETERS); - } else { - int value = strtol(argv[1], NULL, 10); - _nfcQueue.call(NFCTestShim::cmd_set_last_nfc_error, value); - } - return (CMDLINE_RETCODE_EXCUTING_CONTINUE); -} - - -int HandleTestCommand::cmd_get_max_ndef(int argc, char *argv[]) -{ - if (pNFC_Test_Shim) { - _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_get_max_ndef); - return CMDLINE_RETCODE_EXCUTING_CONTINUE; - } - return CMDLINE_RETCODE_FAIL; -} - - -int HandleTestCommand::cmd_init_nfc(int argc, char *argv[]) -{ - if (pNFC_Test_Shim) { - cmd_printf("WARN init called again!\r\n"); // only legal here, if eeprom driver stops talking - } else { - pNFC_Test_Shim = new_testshim(); - } - _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_init); - return (CMDLINE_RETCODE_EXCUTING_CONTINUE); -} - -int HandleTestCommand::cmd_read_message(int argc, char *argv[]) -{ - _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_read_nfc_contents); - - return (CMDLINE_RETCODE_EXCUTING_CONTINUE); -} - -int HandleTestCommand::cmd_set_smartposter(int argc, char *argv[]) -{ - // args are "setsmartposter", "" - if (argc <= 1) { - cmd_printf("setlastnfcerror() invalid parameter(s)\r\n"); - return (CMDLINE_RETCODE_INVALID_PARAMETERS); - } else { - // parse arg and queue it up - char *uri = (char *) malloc(strlen(argv[1]) + 1); - if (uri) { - strcpy(uri, argv[1]); - _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_set_smartposter, - uri); // called thread must free - } else { - cmd_printf("WARN out of memory!\r\n"); - return (CMDLINE_RETCODE_FAIL); - } - } - return (CMDLINE_RETCODE_EXCUTING_CONTINUE); -} - -int HandleTestCommand::cmd_erase(int argc, char *argv[]) -{ - _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_erase); - return (CMDLINE_RETCODE_EXCUTING_CONTINUE); -} - -int HandleTestCommand::cmd_write_long_ndef_message(int argc, char *argv[]) -{ - size_t length, idx, sourceLength; - static const char alphabet[] = "thequickbrownfoxjumpedoverthelazydog"; - char *data; - const char *sourceMessage; - - // expect 2 or 3 args " [optional-text]" - if (argc < 2) { - cmd_printf("supply length of message\r\n"); - return (CMDLINE_RETCODE_INVALID_PARAMETERS); - } - - int converted = sscanf(argv[1], "%d", &length); - if (1 != converted) { - cmd_printf("Cannot convert value to int\r\n"); - return (CMDLINE_RETCODE_INVALID_PARAMETERS); - } - // check that it would not overflow - if (length > MBED_CONF_APP_TEST_NDEF_MSG_MAX) { - cmd_printf("Buffer length may not exceed %d !\r\n", (int)MBED_CONF_APP_TEST_NDEF_MSG_MAX); - return (CMDLINE_RETCODE_FAIL); - } - - data = (char *) malloc(length + 1); - if (!data) { - cmd_printf("WARN out of memory!\r\n"); - return (CMDLINE_RETCODE_FAIL); - } - if (argc > 2) { - // user provided text to copy into text NDEF record - sourceMessage = argv[2]; - } else { - // use our internal default message to copy into the text NDEF - sourceMessage = alphabet; - } - sourceLength = strlen(sourceMessage); - for (idx = 0; idx < length; idx++) { - data[idx] = sourceMessage[idx % sourceLength]; - } - data[length] = '\0'; - - // method must release buffer - _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_write_long, data); - return (CMDLINE_RETCODE_EXCUTING_CONTINUE); -} - -int HandleTestCommand::cmd_start_discovery(int argc, char *argv[]) -{ - if ((argc > 1) && (0 == strcmp(argv[1], "man"))) { - trace_printf("User must restart discovery manually()\r\n"); - _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_start_discovery, false); - } else { - trace_printf("App will restart discovery loop on auto()\r\n"); - _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_start_discovery, true); - } - return (CMDLINE_RETCODE_EXCUTING_CONTINUE); -} - -int HandleTestCommand::cmd_stop_discovery(int argc, char *argv[]) -{ - _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_stop_discovery); - return (CMDLINE_RETCODE_EXCUTING_CONTINUE); -} - -int HandleTestCommand::cmd_get_supported_rf_protocols(int argc, char *argv[]) -{ - _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_get_rf_protocols); - return (CMDLINE_RETCODE_EXCUTING_CONTINUE); -} - -bool HandleTestCommand::set_protocol_target( - nfc_rf_protocols_bitmask_t &bitmask, const char *protocolName) -{ - bool parsed = false; - if (0 == strcmp(protocolName, "t1t")) { - parsed = bitmask.target_t1t = true; - } - if (0 == strcmp(protocolName, "t2t")) { - parsed = bitmask.target_t2t = true; - } - if (0 == strcmp(protocolName, "t3t")) { - parsed = bitmask.target_t3t = true; - } - if (0 == strcmp(protocolName, "t5t")) { - parsed = bitmask.target_t5t = true; - } - if (0 == strcmp(protocolName, "isodep")) { - parsed = bitmask.target_iso_dep = true; - } - if (0 == strcmp(protocolName, "nfcdep")) { - parsed = bitmask.target_nfc_dep = true; - } - return (parsed); -} - -int HandleTestCommand::cmd_configure_rf_protocols(int argc, char *argv[]) -{ - nfc_rf_protocols_bitmask_t protocols = { 0 }; - - int argindex = argc; - while (argindex > 1) { - if (!set_protocol_target(protocols, argv[argindex - 1])) { - cmd_printf("Unknown protocol %s", argv[argindex - 1]); - return (CMDLINE_RETCODE_INVALID_PARAMETERS); - } - argindex--; - } - _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_configure_rf_protocols, - protocols); - return (CMDLINE_RETCODE_EXCUTING_CONTINUE); -} - diff --git a/TEST_APPS/device/nfcapp/NFCCommands.h b/TEST_APPS/device/nfcapp/NFCCommands.h deleted file mode 100644 index ffa9746f3ec..00000000000 --- a/TEST_APPS/device/nfcapp/NFCCommands.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2018 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _NFCCOMMANDS_H_INCLUDED -#define _NFCCOMMANDS_H_INCLUDED - -#if MBED_CONF_NFCEEPROM -#include "NFCProcessEEPROM.h" -#else -#include "NFCProcessCtrl.h" -#endif - -// see https://support.microsoft.com/en-my/help/208427/maximum-url-length-is-2-083-characters-in-internet-explorer -#define MAX_URL_LENGTH 2000 - -#ifndef MBED_CONF_NFCEEPROM -#define MBED_CONF_NFCEEPROM false -#endif - - -/** - * \brief adds human-readable traces not needed by the framework, filter is via a switch set_trace_enable() - * \param fmt standard printf formatter - * \param varargs - */ -void trace_printf(const char *fmt, ...); - -/** - * \brief turns on human readable traces - * \param enabled : set to false to disable the extra traces - */ -void set_trace_enable(bool enabled = true); - -/** - * HandleTestCommand turns all the typed-in/serial commands into function calls sent via a eventqueue to the driver - * shim/wrapper class. - * Methods with cmd_ prefix map to the serial commands, and are building blocks for test cases and scenarios. The - * first function a test must call is typically the initnfc command. Commands report back a test verdict, and a - * NFC status code. The test verdict is always success unless the command is not allowed. Tests much check the - * NFC error code for NFC_OK or zero; this pattern allows us to write negative tests which expect a specific NFC error. - * - * Handlers are statics because the test framework is not supporting C++ - */ -class HandleTestCommand { -public: - HandleTestCommand(); - - /** return and clear the last result code. Type "help getlastnfcerror" for a list of error codes */ - static int cmd_get_last_nfc_error(int argc, char *argv[]); - - /** internal function to test getlastnfcerror */ - static int cmd_set_last_nfc_error(int argc, char *argv[]); - - /** returns compile time flag if NFC EEPROM was compiled */ - static int cmd_get_conf_nfceeprom(int argc, char *argv[]); - - static int cmd_set_trace(int argc, char *argv[]); - - /** For EEPROM, returns the driver max_ndef value, else returns the app config MBED_CONF_APP_TEST_NDEF_MSG_MAX */ - static int cmd_get_max_ndef(int argc, char *argv[]); - - /** Init must be called before invoking any other calls, obtains a driver reference and initializes driver */ - static int cmd_init_nfc(int argc, char *argv[]); - /** write a smartposter url, 'Sp' NDEF to the target */ - static int cmd_set_smartposter(int argc, char *argv[]); - /** erases the EEPROM if present */ - static int cmd_erase(int argc, char *argv[]); - - /** Returns a CSV list of protocols supported */ - static int cmd_get_supported_rf_protocols(int argc, char *argv[]); - /** Sets the protocols supported (unimplemented) */ - static int cmd_configure_rf_protocols(int argc, char *argv[]); - /** starts the NFC discovery loop if controller, has no effect on EEPROM */ - static int cmd_start_discovery(int argc, char *argv[]); - /** stops the NFC discovery loop if controller */ - static int cmd_stop_discovery(int argc, char *argv[]); - - /** read raw EEPROM contents, reads a buffer if a controller is used */ - static int cmd_read_message(int argc, char *argv[]); - /** write a text 'T' NDEF message to the target */ - static int cmd_write_long_ndef_message(int argc, char *argv[]); - -private: - /** set corresponding mask bit on in referenced structure, return false if the supplied string cannot parse */ - static bool set_protocol_target(mbed::nfc::nfc_rf_protocols_bitmask_t &bitmask, const char *protocolName); - static NFCTestShim *new_testshim(); - static void nfc_routine(); - - static events::EventQueue _nfcQueue; -}; - - -// un-implemented or sparse support in drivers, so not covered -int cmd_is_iso7816_supported(int argc, char *argv[]); -int cmd_add_iso7816_application(int argc, char *argv[]); -int cmd_set_tagtype(int argc, char *argv[]); -int cmd_get_tagtype(int argc, char *argv[]); - -#endif // _NFCCOMMANDS_H_INCLUDED diff --git a/TEST_APPS/device/nfcapp/NFCProcessCtrl.cpp b/TEST_APPS/device/nfcapp/NFCProcessCtrl.cpp deleted file mode 100644 index 30fabb10368..00000000000 --- a/TEST_APPS/device/nfcapp/NFCProcessCtrl.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2018 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include -#include -#include -#include "mbed_events.h" -#include "mbed-client-cli/ns_cmdline.h" - -#include "nfc/stack/nfc_errors.h" - -#include "nfc/ndef/common/Text.h" -#include "nfc/ndef/common/URI.h" -#include "nfc/ndef/common/Mime.h" -#include "nfc/ndef/MessageBuilder.h" -#include "nfc/ndef/common/util.h" - - -#include "NFCCommands.h" -#include "NFCProcessCtrl.h" -#include "SmartPoster.h" - -using mbed::Span; -#if ! MBED_CONF_NFCEEPROM -using mbed::nfc::nfc_rf_protocols_bitmask_t; -using mbed::nfc::ndef::MessageBuilder; -using mbed::nfc::ndef::RecordType; -using mbed::nfc::ndef::Record; -using mbed::nfc::ndef::RecordID; -using mbed::nfc::ndef::RecordPayload; -using mbed::nfc::ndef::common::span_from_cstr; -using mbed::nfc::ndef::common::Mime; -using mbed::nfc::ndef::common::Text; -using mbed::nfc::ndef::common::URI; -using mbed::nfc::NFCController; - -/** - * Implements NFCRemoteInitiator::Delegate, NFCController::Delegate - */ - -NFCProcessController::NFCProcessController(events::EventQueue &queue) : - NFCTestShim(queue), - // pins: mosi, miso, sclk, ssel, irq, rst - _pn512_transport(D11, D12, D13, D10, A1, A0), _pn512_driver( - &_pn512_transport), - _nfc_controller(&_pn512_driver, &queue, _ndef_buffer) -{ -} - -/** - * Initialise and configure the NFC controller. - * - * @return NFC_OK in case of success or a meaningful error code in case of - * failure. - */ -nfc_err_t NFCProcessController::init() -{ - trace_printf("init()\r\n"); - - // register callbacks - _nfc_controller.set_delegate(this); - return _nfc_controller.initialize(); -} - - -void NFCProcessController::cmd_get_max_ndef() -{ - cmd_printf("{{maxndef=%d}}\r\n", (int)MBED_CONF_APP_TEST_NDEF_MSG_MAX); - cmd_ready(CMDLINE_RETCODE_SUCCESS); -} - -/** - * Start the discovery of peers. - * - * @return NFC_OK in case of success or a meaningful error code in case of - * failure. - */ -nfc_err_t NFCProcessController::start_discovery() -{ - trace_printf("start_discovery()\r\n"); - - return _nfc_controller.start_discovery(); -} - -/** - * Stop discovery. - * - * @return NFC_OK in case of success or a meaningful error code in case of - * failure. - */ -nfc_err_t NFCProcessController::stop_discovery() -{ - trace_printf("stop_discovery()\r\n"); - return _nfc_controller.cancel_discovery(); -} - -nfc_rf_protocols_bitmask_t NFCProcessController::get_rf_protocols() -{ - trace_printf("get_supported_rf_protocols()\r\n"); - return _nfc_controller.get_supported_rf_protocols(); -} - -nfc_err_t NFCProcessController::set_rf_protocols( - nfc_rf_protocols_bitmask_t protocols) -{ - trace_printf("configure_rf_protocols()\r\n"); - - return _nfc_controller.configure_rf_protocols(protocols); -} - - -/* ------------------------------------------------------------------------ - * Implementation of NFCRemoteInitiator::Delegate - */ -void NFCProcessController::on_connected() -{ - cmd_printf("on_connected()\r\n"); -} - -void NFCProcessController::on_disconnected() -{ - cmd_printf("on_disconnected()\r\n"); - - // reset the state of the remote initiator - _nfc_remote_initiator->set_delegate(NULL); - _nfc_remote_initiator.reset(); - - // restart peer discovery - _nfc_controller.start_discovery(); -} - -void NFCProcessController::parse_ndef_message( - const Span &buffer) -{ - size_t len = buffer.size(); - // copy remotely written message into our dummy buffer - if (len <= sizeof(_ndef_write_buffer)) { - trace_printf("Store remote ndef message of size %d\r\n", len); - memcpy(_ndef_write_buffer, buffer.data(), len); - _ndef_write_buffer_used = len; - } else { - trace_printf("Remote ndef message of size %d too large!\r\n", len); - } -} - -size_t NFCProcessController::build_ndef_message(const Span &buffer) -{ - trace_printf("Copying message %d bytes to query buffer\r\n", - _ndef_write_buffer_used); - memcpy(buffer.data(), _ndef_write_buffer, _ndef_write_buffer_used); - for (size_t k = 0; k < _ndef_write_buffer_used; k++) { - cmd_printf("%02x ", buffer[k]); - } - return _ndef_write_buffer_used; -} - -const char *NFCProcessController::str_discovery_terminated_reason( - nfc_discovery_terminated_reason_t reason) -{ - static const char *reasons[4] = { "completed", "cancelled", "rf error"}; - switch (reason) { - case nfc_discovery_terminated_completed : - case nfc_discovery_terminated_canceled: - case nfc_discovery_terminated_rf_error: - return reasons[reason]; - } - return "unexpected!"; -} - - -void NFCProcessController::on_discovery_terminated( - nfc_discovery_terminated_reason_t reason) -{ - trace_printf("on_discovery_terminated(%s)\r\n", - str_discovery_terminated_reason(reason)); - if (reason != nfc_discovery_terminated_completed - && this->_discovery_restart) { - start_discovery(); - } -} - -void NFCProcessController::on_nfc_initiator_discovered( - const SharedPtr &nfc_initiator) -{ - trace_printf("on_nfc_initiator_discovered()\r\n"); - - // setup the local remote initiator - _nfc_remote_initiator = nfc_initiator; - _nfc_remote_initiator->set_delegate(this); - _nfc_remote_initiator->connect(); -} - -#endif // #if ! MBED_CONF_NFCEEPROM - diff --git a/TEST_APPS/device/nfcapp/NFCProcessCtrl.h b/TEST_APPS/device/nfcapp/NFCProcessCtrl.h deleted file mode 100644 index 2f610bc08ce..00000000000 --- a/TEST_APPS/device/nfcapp/NFCProcessCtrl.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2018 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _NFCPROCESS_H_INCLUDED -#define _NFCPROCESS_H_INCLUDED - -#include -#include -#include -#include -#include "mbed_events.h" -#include "nfc/ndef/MessageBuilder.h" -#include "nfc/ndef/common/URI.h" -#include "nfc/ndef/common/util.h" -#include "NFCTestShim.h" - -#if !MBED_CONF_NFCEEPROM - -#include "nfc/nfcdefinitions.h" -#ifdef TARGET_PN512 -#include "nfc/controllers/PN512Driver.h" -#include "nfc/controllers/PN512SPITransportDriver.h" -#endif -#include "nfc/NFCRemoteInitiator.h" -#include "nfc/NFCController.h" -#include "nfc/ndef/common/util.h" - -/** - * Wrapper class handles calls and callbacks for NFC controller drivers. Note, that users must call "start" - * in order to start the discovery loop for controllers. An internal buffer stores the NFC message and records. - */ -class NFCProcessController: NFCTestShim, - mbed::nfc::NFCRemoteInitiator::Delegate, - mbed::nfc::NFCController::Delegate { -public: - NFCProcessController(events::EventQueue &queue); - - void cmd_get_max_ndef(); - nfc_err_t init(); - nfc_err_t start_discovery(); - nfc_err_t stop_discovery(); - mbed::nfc::nfc_rf_protocols_bitmask_t get_rf_protocols(); - nfc_err_t set_rf_protocols(mbed::nfc::nfc_rf_protocols_bitmask_t protocols); - - virtual void parse_ndef_message(const mbed::Span &buffer); - virtual size_t build_ndef_message(const mbed::Span &buffer); - const char *str_discovery_terminated_reason( - nfc_discovery_terminated_reason_t reason); - -private: - // these events are handled, to restart discovery - /** - * Implementation of NFCRemoteEndpoint::Delegate */ - virtual void on_connected(); - /** - * Implementation of NFCRemoteEndpoint::Delegate */ - virtual void on_disconnected(); - /** - * Implementation of NFCController::Delegate */ - virtual void on_discovery_terminated( - nfc_discovery_terminated_reason_t reason); - /** - * Implementation of NFCController::Delegate */ - virtual void on_nfc_initiator_discovered( - const SharedPtr &nfc_initiator); - -private: - mbed::nfc::PN512SPITransportDriver _pn512_transport; - mbed::nfc::PN512Driver _pn512_driver; - mbed::nfc::NFCController _nfc_controller; - SharedPtr _nfc_remote_initiator; -}; -#endif // Controller - -#endif // _NFCPROCESS_H_INCLUDED diff --git a/TEST_APPS/device/nfcapp/NFCProcessEEPROM.cpp b/TEST_APPS/device/nfcapp/NFCProcessEEPROM.cpp deleted file mode 100644 index f475ccc65cf..00000000000 --- a/TEST_APPS/device/nfcapp/NFCProcessEEPROM.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2018 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include -#include -#include -#include -#include "mbed_events.h" -#include "mbed-client-cli/ns_cmdline.h" - -#include "nfc/stack/nfc_errors.h" -#include "nfc/ndef/common/Text.h" -#include "nfc/ndef/common/URI.h" -#include "nfc/ndef/common/Mime.h" -#include "nfc/ndef/MessageBuilder.h" -#include "nfc/ndef/common/util.h" -#if MBED_CONF_NFCEEPROM -#include "NFCEEPROMDriver.h" - -#include "NFCProcessEEPROM.h" -#include "SmartPoster.h" - -using mbed::Span; -using mbed::nfc::ndef::MessageBuilder; -using mbed::nfc::ndef::RecordType; -using mbed::nfc::ndef::Record; -using mbed::nfc::ndef::RecordID; -using mbed::nfc::ndef::RecordPayload; -using mbed::nfc::ndef::common::span_from_cstr; -using mbed::nfc::ndef::common::Mime; -using mbed::nfc::ndef::common::Text; -using mbed::nfc::ndef::common::URI; -using mbed::nfc::NFCEEPROM; -using mbed::nfc::NFCEEPROMDriver; - -// implements : mbed::nfc::NFCEEPROM::Delegate -NFCProcessEEPROM::NFCProcessEEPROM(events::EventQueue &queue, NFCEEPROMDriver &eeprom_driver) : - NFCTestShim(queue), _eeprom(&eeprom_driver, &queue, _ndef_buffer), _ptr_eeprom_driver(&eeprom_driver) -{} - -nfc_err_t NFCProcessEEPROM::init() -{ - nfc_err_t err = _eeprom.initialize(); - if (err != NFC_OK) { - cmd_printf("NFCProcessEEPROM::init() (error: %d)!\r\n", err); - _queue.break_dispatch(); - } else { - cmd_printf("NFCProcessEEPROM::init() OK\r\n"); - } - _eeprom.set_delegate(this); - return (err); -} - - -void NFCProcessEEPROM::cmd_get_max_ndef() -{ - cmd_printf("{{maxndef=%d}}\r\n", (int)_ptr_eeprom_driver->read_max_size()); - cmd_ready(CMDLINE_RETCODE_SUCCESS); -} - -void NFCProcessEEPROM::queue_write_call() -{ - cmd_printf("NFCProcessEEPROM::queue_write_call() entry\r\n"); - _queue.call(&_eeprom, &NFCEEPROM::write_ndef_message); -} - -void NFCProcessEEPROM::queue_read_call() -{ - cmd_printf("NFCProcessEEPROM::queue_read_call() entry\r\n"); - _queue.call(&_eeprom, &NFCEEPROM::read_ndef_message); -} - -void NFCProcessEEPROM::queue_erase_call() -{ - cmd_printf("NFCProcessEEPROM::queue_erase_call() entry\r\n"); - _queue.call(&_eeprom, &NFCEEPROM::erase_ndef_message); -} - -void NFCProcessEEPROM::on_ndef_message_written(nfc_err_t result) -{ - set_last_nfc_error(result); - if (result == NFC_OK) { - cmd_printf("message written successfully\r\n"); - } else { - cmd_printf("Failed to write (error: %d)!\r\n", result); - } - // complete the async test method here - cmd_ready(CMDLINE_RETCODE_SUCCESS); -} - -void NFCProcessEEPROM::on_ndef_message_read(nfc_err_t result) -{ - set_last_nfc_error(result); - if (result == NFC_OK) { - cmd_printf("message read successfully\r\n"); - } else { - cmd_printf("Failed to read (error: %d)!\r\n", result); - } - // complete the async test method here - cmd_ready(CMDLINE_RETCODE_SUCCESS); -} - -void NFCProcessEEPROM::on_ndef_message_erased(nfc_err_t result) -{ - set_last_nfc_error(result); - if (result == NFC_OK) { - cmd_printf("message erased successfully\r\n"); - } else { - cmd_printf("Failed to erase (error: %d)!\r\n", result); - } - // complete the async test method here - cmd_ready(CMDLINE_RETCODE_SUCCESS); -} - -void NFCProcessEEPROM::parse_ndef_message(const Span &buffer) -{ - cmd_printf("Received an ndef message of size %d\r\n", buffer.size()); - print_ndef_message(buffer, buffer.size()); -} - -size_t NFCProcessEEPROM::build_ndef_message(const Span &buffer) -{ - cmd_printf("Copying ndef message %d bytes into buffer\r\n", _ndef_write_buffer_used); - // make a copy into our buffer - memcpy(buffer.data(), _ndef_write_buffer, _ndef_write_buffer_used); - for (size_t k = 0; k < _ndef_write_buffer_used; k++) { - cmd_printf("%02x ", buffer[k]); - } - return _ndef_write_buffer_used; -} - -#endif // MBED_CONF_NFCEEPROM - diff --git a/TEST_APPS/device/nfcapp/NFCProcessEEPROM.h b/TEST_APPS/device/nfcapp/NFCProcessEEPROM.h deleted file mode 100644 index c56fec72483..00000000000 --- a/TEST_APPS/device/nfcapp/NFCProcessEEPROM.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2018 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _NFCPROCESS_H_INCLUDED -#define _NFCPROCESS_H_INCLUDED - -#include -#include -#include -#include - -#include "nfc/ndef/MessageBuilder.h" -#include "nfc/ndef/common/URI.h" -#include "nfc/ndef/common/util.h" -#include "NFCTestShim.h" - -#if MBED_CONF_NFCEEPROM -#include "NFCEEPROM.h" -#include "EEPROMDriver.h" - - -/** - * Wrapper class handles events specific to the EEPROM driver. - */ -class NFCProcessEEPROM : NFCTestShim, mbed::nfc::NFCEEPROM::Delegate { -public: - NFCProcessEEPROM(events::EventQueue &queue, mbed::nfc::NFCEEPROMDriver &eeprom_driver); - virtual nfc_err_t init(); - void queue_write_call(); - void queue_write_long_call(); - void queue_read_call(); - void queue_erase_call(); - virtual void cmd_get_max_ndef(); - - -private: - virtual void on_ndef_message_written(nfc_err_t result); - virtual void on_ndef_message_read(nfc_err_t result); - virtual void parse_ndef_message(const mbed::Span &buffer); - virtual size_t build_ndef_message(const mbed::Span &buffer); - virtual void on_ndef_message_erased(nfc_err_t result); -private: - mbed::nfc::NFCEEPROM _eeprom; - mbed::nfc::NFCEEPROMDriver *_ptr_eeprom_driver; -}; - -#endif // eeprom - -#endif // _NFCPROCESS_H_INCLUDED diff --git a/TEST_APPS/device/nfcapp/NFCTestShim.cpp b/TEST_APPS/device/nfcapp/NFCTestShim.cpp deleted file mode 100644 index c62482f210a..00000000000 --- a/TEST_APPS/device/nfcapp/NFCTestShim.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright (c) 2018 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include -#include -#include -#include -#include "mbed-client-cli/ns_cmdline.h" -#include "nfc/ndef/common/Text.h" -#include "nfc/ndef/common/URI.h" -#include "nfc/ndef/common/Mime.h" -#include "nfc/ndef/MessageBuilder.h" -#include "nfc/ndef/common/util.h" -#include "nfc/nfcdefinitions.h" - -#include "NFCEEPROMDriver.h" -#include "NFCCommands.h" -#include "NFCTestShim.h" -#include "SmartPoster.h" - -using mbed::Span; -using mbed::nfc::ndef::MessageBuilder; -using mbed::nfc::ndef::RecordType; -using mbed::nfc::ndef::common::span_from_cstr; -using mbed::nfc::ndef::common::Text; -using mbed::nfc::ndef::common::URI; -using mbed::nfc::nfc_rf_protocols_bitmask_t; - - -// statics -namespace { - -char const *uri_prefix_string[] = { "", - "http://www.", - "https://www.", - "http://", - "https://", - "tel:", - "mailto:", - "ftp://anonymous:anonymous@", - "ftp://ftp.", - "ftps://", - "sftp://", - "smb://", - "nfs://", - "ftp://", - "dav://", - "news:", - "telnet://", - "imap:", - "rstp://", - "urn:", - "pop:", - "sip:", - "sips:", - "tftp:", - "btspp://", - "btl2cap://", - "btgoep://", - "tcpobex://", - "irdaobex://", - "file://", - "urn:epc:id:", - "urn:epc:tag:", - "urn:epc:pat:", - "urn:epc:raw:", - "urn:epc:", - "urn:nfc:" - }; - - -} - - -int NFCTestShim::last_nfc_error = 0; -NFCTestShim *pNFC_Test_Shim = NULL; - -NFCTestShim::NFCTestShim(events::EventQueue &queue) : - _ndef_write_buffer_used(0), _ndef_poster_message(_ndef_write_buffer), - _discovery_restart(true), // on disconnect, will restart discovery - _queue(queue) -{ -} - -void NFCTestShim::cmd_get_last_nfc_error() -{ - get_last_nfc_error(); -} - -void NFCTestShim::cmd_set_last_nfc_error(int err) -{ - set_last_nfc_error(err); - cmd_ready(CMDLINE_RETCODE_SUCCESS); -} - -void NFCTestShim::cmd_get_conf_nfceeprom() -{ - get_conf_nfceeprom(); -} - -/** \brief The last failed NFC API call status, gets cleared upon reading it. - * \return void The NFC error is set asyncronously by sending text back over serial - */ -void NFCTestShim::get_last_nfc_error() -{ - int last = last_nfc_error; - last_nfc_error = 0; - // return data as text to the plugin framework - cmd_printf("{{lastnfcerror=%d}}\r\n", last); - cmd_ready(CMDLINE_RETCODE_SUCCESS); -} - -void NFCTestShim::set_last_nfc_error(int err) -{ - last_nfc_error = err; - cmd_printf("\r\n{{lastnfcerror=%d}}\r\n", last_nfc_error); -} - -// if an NFC EEPROM driver is configured -void NFCTestShim::get_conf_nfceeprom() -{ - set_last_nfc_error(NFC_OK); - // return data as text to the plugin framework - cmd_printf("{{iseeprom=%s}}\r\n", (MBED_CONF_NFCEEPROM ? "true" : "false")); - cmd_ready(CMDLINE_RETCODE_SUCCESS); -} - -void NFCTestShim::print_ndef_message(const Span &buffer, - size_t length) -{ - // return data as text to the plugin framework - cmd_printf("{{nfcmessage="); - for (size_t k = 0; k < length; k++) { - cmd_printf("%02x ", buffer.data()[k]); - } - cmd_printf("}}\r\n"); -} - -URI::uri_identifier_code_t NFCTestShim::get_ndef_record_type(char const *url) -{ - size_t i; - int len, bestLen = -1, index = -1; - // find largest matching prefix - for (i = 1; i < sizeof(uri_prefix_string) / sizeof(uri_prefix_string[0]); i++) { - len = strlen(uri_prefix_string[i]); - if (0 == strncmp(uri_prefix_string[i], url, len)) { - if (len > bestLen) { - index = i; - bestLen = len; - } - } - } - return (URI::uri_identifier_code_t)index; -} - -char const *NFCTestShim::get_ndef_record_type_prefix(URI::uri_identifier_code_t id) -{ - if ((id < 1) | (id > sizeof(uri_prefix_string) / sizeof(uri_prefix_string[0]))) { - return (""); // unknown case - } - return (::uri_prefix_string[(int)id]); -} - -void NFCTestShim::cmd_init() -{ - nfc_err_t ret = init(); - set_last_nfc_error(ret); - - if (NFC_OK != ret) { - cmd_ready(CMDLINE_RETCODE_FAIL); - } else { - cmd_ready(CMDLINE_RETCODE_SUCCESS); - } -} - -void NFCTestShim::cmd_get_rf_protocols() -{ -#if MBED_CONF_NFCEEPROM - cmd_printf("EEPROM cannot get protocol()\r\n"); - set_last_nfc_error(NFC_ERR_UNSUPPORTED); - cmd_ready(CMDLINE_RETCODE_INVALID_PARAMETERS); - -#else - nfc_rf_protocols_bitmask_t protocols = get_rf_protocols(); - - static char strSupported[7 * 6 + 1] = ""; - if (protocols.target_t1t) { - strcat(strSupported, "t1t,"); - } - if (protocols.target_t2t) { - strcat(strSupported, "t2t,"); - } - if (protocols.target_t3t) { - strcat(strSupported, "t3t,"); - } - if (protocols.target_iso_dep) { - strcat(strSupported, "isodep,"); - } - if (protocols.target_nfc_dep) { - strcat(strSupported, "nfcdep,"); - } - if (protocols.target_t5t) { - strcat(strSupported, "t5t,"); - } - if (strlen(strSupported)) { - strSupported[strlen(strSupported) - 1] = '\0'; // strip trailing comma - } - // return data as text to the plugin framework - cmd_printf("{{protocols=%s}}", strSupported); - set_last_nfc_error(NFC_OK); - cmd_ready(CMDLINE_RETCODE_SUCCESS); -#endif -} - -void NFCTestShim::cmd_configure_rf_protocols( - nfc_rf_protocols_bitmask_t protocols) -{ -#if MBED_CONF_NFCEEPROM - cmd_printf("EEPROM cannot set protocol()\r\n"); - set_last_nfc_error(NFC_ERR_UNSUPPORTED); - cmd_ready(CMDLINE_RETCODE_INVALID_PARAMETERS); -#else - - nfc_err_t err = set_rf_protocols(protocols); - set_last_nfc_error(err); - if (NFC_OK != err) { - cmd_ready(CMDLINE_RETCODE_FAIL); - } else { - cmd_ready(CMDLINE_RETCODE_SUCCESS); - } -#endif -} - -/** \brief Copy data from the Controller buffer, or if EEPROM will initiate a read of the - * eeprom contents which get dumped as a string {{bytes=XX XX XX XX.. }} and parsed by - * the framework - * \return void An ICETEA error code and NFC error is set asyncronously - */ -void NFCTestShim::cmd_read_nfc_contents() -{ -#if MBED_CONF_NFCEEPROM - ((NFCProcessEEPROM *)this)->queue_read_call(); - trace_printf("NFCTestShim::cmd_read_nfc_contents() exit\r\n"); - -#else - // returns last message "written", since we cannot read - print_ndef_message(_ndef_write_buffer, _ndef_write_buffer_used); - trace_printf("Controller buffer data size=%d\r\n", _ndef_write_buffer_used); - set_last_nfc_error(NFC_OK); - - trace_printf("NFCTestShim::cmd_read_nfc_contents() exit\r\n"); - cmd_ready(CMDLINE_RETCODE_SUCCESS); -#endif -} - -void NFCTestShim::cmd_erase() -{ -#if MBED_CONF_NFCEEPROM - ((NFCProcessEEPROM *)this)->queue_erase_call(); -#else - trace_printf("Erase (reset) controller msg buffer\r\n"); - _ndef_write_buffer_used = 0; - memset(_ndef_write_buffer, 0, sizeof(_ndef_write_buffer)); - set_last_nfc_error(NFC_OK); - cmd_ready(CMDLINE_RETCODE_SUCCESS); -#endif -} - -/** \brief Writes a Text T record buffer with really long message - length checks to be done by driver only. - * If an NFC controller, no write to the chip happens, we copy the data into a Controller buffer - * \param text_string This method must free the passed in pointer - * \return void An ICETEA error code and NFC error is set asynchronously - */ -void NFCTestShim::cmd_write_long(char *text_string) -{ - MessageBuilder builder(_ndef_poster_message); - Text text(Text::UTF8, span_from_cstr("en-US"), - span_from_cstr((const char *)(text_string))); - - text.append_as_record(builder, true); - _ndef_write_buffer_used = builder.get_message().size(); - trace_printf("Composed NDEF message %d bytes\r\n", _ndef_write_buffer_used); - -#if MBED_CONF_NFCEEPROM - ((NFCProcessEEPROM *)this)->queue_write_call(); -#else - // not on a wire, and we just stored the message in _ndef_write_buffer above - set_last_nfc_error(NFC_OK); - cmd_ready(CMDLINE_RETCODE_SUCCESS); -#endif - free(text_string); // free buffer allocated by the command class now - trace_printf("NFCTestShim::write_long() exit\r\n"); -} - -/** \brief Write a URI Use case would be to prompt to install an app from the appstore using the tag - * \param uri This method must free the passed in pointer - * \return void An ICETEA error code and NFC error is set asyncronously - */ -void NFCTestShim::cmd_set_smartposter(char *cmdUri) -{ - MessageBuilder builder(_ndef_poster_message); - - struct SPBuilder: MessageBuilder::PayloadBuilder { - SPBuilder(char *cmd_uri) - { - URI::uri_identifier_code_t uri_id = get_ndef_record_type(cmd_uri); - char *urlbegin = cmd_uri - + strlen(get_ndef_record_type_prefix(uri_id)); - uri = URI(uri_id, span_from_cstr(urlbegin)); - cmd_printf("{{uri_id=%d}}\r\n", (int) uri_id); - } - - virtual size_t size() const - { - return uri.get_record_size(); - } - - virtual void build(const Span &buffer) const - { - MessageBuilder smart_poster_builder(buffer); - - uri.append_as_record(smart_poster_builder, true); - } - URI uri; - }; - - builder.append_record( - RecordType(RecordType::well_known_type, span_from_cstr("Sp")), - SPBuilder(cmdUri), true); - - _ndef_write_buffer_used = builder.get_message().size(); - trace_printf("Composed NDEF message %d bytes\r\n", _ndef_write_buffer_used); - -#if MBED_CONF_NFCEEPROM - ((NFCProcessEEPROM *)this)->queue_write_call(); -#else - // not on a wire, so the call just stores the message in a buffer - set_last_nfc_error(NFC_OK); - cmd_ready(CMDLINE_RETCODE_SUCCESS); -#endif - trace_printf("NFCTestShim::setsmartposter() exit\r\n"); - free(cmdUri); -} - -// disabled in EEPROMs, overridden if controller present -void NFCTestShim::cmd_start_discovery(bool manual) -{ -#if MBED_CONF_NFCEEPROM - cmd_printf("EEPROM cannot start_discovery()\r\n"); - set_last_nfc_error(NFC_ERR_UNSUPPORTED); - cmd_ready(CMDLINE_RETCODE_INVALID_PARAMETERS); - -#else - - // todo: Jira logged. remove hard coded protocol - nfc_rf_protocols_bitmask_t protocols = { 0 }; - protocols.target_iso_dep = 1; - - nfc_err_t err = set_rf_protocols(protocols); - - if (manual) { - set_discovery_restart_manual(); - } else { - set_discovery_restart_auto(); - } - err = start_discovery(); - set_last_nfc_error(err); - if (NFC_OK != err) { - cmd_ready(CMDLINE_RETCODE_FAIL); - } else { - cmd_ready(CMDLINE_RETCODE_SUCCESS); - } -#endif -} - -// disabled in EEPROMs, overridden if controller present -void NFCTestShim::cmd_stop_discovery() -{ - -#if MBED_CONF_NFCEEPROM - cmd_printf("EEPROM cannot stop_discovery()\r\n"); - set_last_nfc_error(NFC_ERR_UNSUPPORTED); - cmd_ready(CMDLINE_RETCODE_INVALID_PARAMETERS); -#else - nfc_err_t err = stop_discovery(); - set_last_nfc_error(err); - if (NFC_OK != err) { - cmd_ready(CMDLINE_RETCODE_FAIL); - } else { - cmd_ready(CMDLINE_RETCODE_SUCCESS); - } - -#endif -} - diff --git a/TEST_APPS/device/nfcapp/NFCTestShim.h b/TEST_APPS/device/nfcapp/NFCTestShim.h deleted file mode 100644 index 6aba9b820bd..00000000000 --- a/TEST_APPS/device/nfcapp/NFCTestShim.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2018 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _NFCTESTSHIM_H_INCLUDED -#define _NFCTESTSHIM_H_INCLUDED - -#include -#include -#include -#include - -#include "mbed_config.h" -#include "nfc/ndef/MessageBuilder.h" -#include "nfc/ndef/common/URI.h" -#include "nfc/ndef/common/util.h" -#include "nfc/NFCDefinitions.h" - -/** - * Test app driver wrapper. This is a base class containing shared EEPROM and Controller test data + logic. - * Variations for the 2 different kinds of driver supported are delegated to derived classes. - */ -class NFCTestShim { -public: - NFCTestShim(events::EventQueue &queue); - - static void cmd_get_last_nfc_error(); - static void cmd_set_last_nfc_error(int err); - static void cmd_get_conf_nfceeprom(); - /** - * For an EEPROM, this queries and responds with the flash size, - * For a Controller, responds with the config macro TEST_NDEF_MSG_MAX - */ - virtual void cmd_get_max_ndef() = 0; - - static void get_last_nfc_error(); - static void set_last_nfc_error(int err); - static void get_conf_nfceeprom(); - static void print_ndef_message(const mbed::Span &buffer, - size_t length); - static mbed::nfc::ndef::common::URI::uri_identifier_code_t get_ndef_record_type(char const *url); - static char const *get_ndef_record_type_prefix(mbed::nfc::ndef::common::URI::uri_identifier_code_t id); - - void cmd_init(); - - void cmd_set_smartposter(char *cmdUri); - void cmd_erase(); - void cmd_write_long(char *text_string); - void cmd_read_nfc_contents(); - void cmd_start_discovery(bool manual = false); - void cmd_stop_discovery(); - void cmd_configure_rf_protocols(mbed::nfc::nfc_rf_protocols_bitmask_t protocols); - void cmd_get_rf_protocols(); - -protected: - // implement/declare EEPROM and Controller model underlying common BH and delegate specializations - virtual nfc_err_t init() = 0; - virtual nfc_err_t set_rf_protocols(mbed::nfc::nfc_rf_protocols_bitmask_t protocols) - { - return NFC_ERR_UNSUPPORTED ; - }; - virtual mbed::nfc::nfc_rf_protocols_bitmask_t get_rf_protocols() - { - mbed::nfc::nfc_rf_protocols_bitmask_t none; - memset((void *)&none, 0, sizeof(none)); - return none; - }; - virtual nfc_err_t start_discovery() - { - return NFC_ERR_UNSUPPORTED ; - }; - virtual nfc_err_t stop_discovery() - { - return NFC_ERR_UNSUPPORTED ; - }; - void set_discovery_restart_auto() - { - _discovery_restart = true; - }; - void set_discovery_restart_manual() - { - _discovery_restart = false; - }; - -protected: - size_t _ndef_write_buffer_used; - mbed::Span _ndef_poster_message; // message to build and send - uint8_t _ndef_write_buffer[MBED_CONF_APP_TEST_NDEF_MSG_MAX]; // if this buffer is smaller than the EEPROM, the driver may crash see IOTPAN-297 - uint8_t _ndef_buffer[MBED_CONF_APP_TEST_NDEF_MSG_MAX]; // driver I/O buffer - bool _discovery_restart; // default true, restart discovery loop again on remote disconnect - events::EventQueue &_queue; -private: - static int last_nfc_error; -}; - -// forward declare single instance -extern NFCTestShim *pNFC_Test_Shim; - -#endif // _NFCTESTSHIM_H_INCLUDED diff --git a/TEST_APPS/device/nfcapp/SmartPoster.cpp b/TEST_APPS/device/nfcapp/SmartPoster.cpp deleted file mode 100644 index c09cf8488ae..00000000000 --- a/TEST_APPS/device/nfcapp/SmartPoster.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* Copyright (c) 2018 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#include "SmartPoster.h" - -#include "nfc/ndef/common/Text.h" -#include "nfc/ndef/common/URI.h" -#include "nfc/ndef/common/Mime.h" -#include "nfc/ndef/MessageBuilder.h" -#include "nfc/ndef/common/util.h" - -using mbed::Span; - -using mbed::nfc::ndef::MessageBuilder; -using mbed::nfc::ndef::RecordType; -using mbed::nfc::ndef::Record; -using mbed::nfc::ndef::RecordID; -using mbed::nfc::ndef::RecordPayload; -using mbed::nfc::ndef::common::span_from_cstr; -using mbed::nfc::ndef::common::Mime; -using mbed::nfc::ndef::common::Text; -using mbed::nfc::ndef::common::URI; - -// todo: this class probably needs to be in the nfc module itself - -namespace { -static RecordType smart_poster_record_type() -{ - return RecordType(RecordType::well_known_type, span_from_cstr("Sp")); -} - -static RecordType action_record_type() -{ - return RecordType(RecordType::well_known_type, span_from_cstr("act")); -} - -static RecordType size_record_type() -{ - return RecordType(RecordType::well_known_type, span_from_cstr("s")); -} - -static RecordType type_record_type() -{ - return RecordType(RecordType::well_known_type, span_from_cstr("T")); -} - -static size_t compute_record_size(const RecordType &type, - const RecordPayload &payload) -{ - return MessageBuilder::compute_record_size( - Record(type, payload, RecordID(), false, false)); -} - -} // end of anonymous namespace - -SmartPoster::SmartPoster(const URI &uri) : - _uri(uri), _action(), _resource_size(0), _action_set(false), _resource_size_set( - false) -{ -} - -void SmartPoster::set_title(const Text &text) -{ - _title = text; -} - -void SmartPoster::set_icon(const Mime &icon) -{ - _icon = icon; -} - -void SmartPoster::set_action(action_t action) -{ - _action = action; - _action_set = true; -} - -void SmartPoster::set_resource_size(uint32_t size) -{ - _resource_size = size; - _resource_size_set = true; -} - -void SmartPoster::set_resource_type(Span &type) -{ - _type.set_text(Text::UTF8, Span(), type); -} - -bool SmartPoster::append_record(MessageBuilder &ndef_builder, - bool is_last_record) const -{ - if (_uri.get_uri_field().empty()) { - return false; - } - - struct PayloadBuilder: MessageBuilder::PayloadBuilder { - PayloadBuilder(const SmartPoster &sp) : - sp(sp) - { - } - - virtual size_t size() const - { - return sp.get_uri_record_size() + sp.get_title_record_size() - + sp.get_icon_record_size() + sp.get_action_record_size() - + sp.get_resource_size_record_size() - + sp.get_type_record_size(); - } - - virtual void build(const Span &buffer) const - { - MessageBuilder smart_poster_builder(buffer); - sp.append_title(smart_poster_builder); - sp.append_icon(smart_poster_builder); - sp.append_resource_size(smart_poster_builder); - sp.append_type(smart_poster_builder); - sp.append_action(smart_poster_builder); - sp.append_uri(smart_poster_builder); - } - - const SmartPoster &sp; - }; - - bool result = ndef_builder.append_record(smart_poster_record_type(), - PayloadBuilder(*this), is_last_record); - return result; -} - -void SmartPoster::append_uri(MessageBuilder &builder) const -{ - _uri.append_as_record(builder, true); -} - -size_t SmartPoster::get_uri_record_size() const -{ - return _uri.get_record_size(); -} - -void SmartPoster::append_title(MessageBuilder &builder) const -{ - if (_title.get_text().empty()) { - return; - } - _title.append_as_record(builder); -} - -size_t SmartPoster::get_title_record_size() const -{ - if (_title.get_text().empty()) { - return 0; - } - - return _title.get_record_size(); -} - -void SmartPoster::append_icon(MessageBuilder &builder) const -{ - if (_icon.get_mime_content().empty()) { - return; - } - _icon.append_as_record(builder); -} - -size_t SmartPoster::get_icon_record_size() const -{ - if (_icon.get_mime_content().empty()) { - return 0; - } - - return _icon.get_record_size(); -} - -void SmartPoster::append_action(MessageBuilder &builder) const -{ - if (!_action_set) { - return; - } - - const uint8_t action_value[1] = { _action }; - builder.append_record(action_record_type(), action_value); -} - -size_t SmartPoster::get_action_record_size() const -{ - if (!_action_set) { - return 0; - } - - const uint8_t action_value[1] = { _action }; - - return compute_record_size(action_record_type(), action_value); -} - -void SmartPoster::append_resource_size(MessageBuilder &builder) const -{ - if (!_resource_size_set) { - return; - } - - uint8_t value[4]; - std::reverse_copy(&_resource_size, &_resource_size + 4, value); - - builder.append_record(size_record_type(), value); -} - -size_t SmartPoster::get_resource_size_record_size() const -{ - if (!_resource_size_set) { - return 0; - } - - uint8_t value[4]; - - return compute_record_size(size_record_type(), value); -} - -void SmartPoster::append_type(MessageBuilder &builder) const -{ - if (_type.get_text().empty()) { - return; - } - - builder.append_record(type_record_type(), _type.get_text()); -} - -size_t SmartPoster::get_type_record_size() const -{ - if (_type.get_text().empty()) { - return 0; - } - - return compute_record_size(type_record_type(), _type.get_text()); -} - diff --git a/TEST_APPS/device/nfcapp/SmartPoster.h b/TEST_APPS/device/nfcapp/SmartPoster.h deleted file mode 100644 index 065abdceac9..00000000000 --- a/TEST_APPS/device/nfcapp/SmartPoster.h +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (c) 2018 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SMARTPOSTER_H_ -#define SMARTPOSTER_H_ - -#include "nfc/ndef/common/Text.h" -#include "nfc/ndef/common/URI.h" -#include "nfc/ndef/common/Mime.h" -#include "nfc/ndef/MessageBuilder.h" - -/** - * Smart poster object. - * - * A smart poster is one of the basic use case of NFC. It encapsulates a URI to - * a resource and meta-data of the resource. - * - * Meta-data are optional, they can be: - * - title: name of the resource - * - icon: image/media associated to the resource - * - action: Action the peer should execute upon reception of the smart poster - * - size: The size of the resource. - * - type: Mime type of the resource. - * - * @note It obeys to value semantic and can be copied around. - */ -class SmartPoster { -public: - typedef mbed::nfc::ndef::common::Mime Mime; - typedef mbed::nfc::ndef::common::Text Text; - typedef mbed::nfc::ndef::common::URI URI; - typedef mbed::nfc::ndef::MessageBuilder MessageBuilder; - - /** - * Type of actions that should be executed upon smart poster reception. - */ - enum action_t { - EXECUTE, //!< EXECUTE - SAVE, //!< SAVE - EDIT //!< EDIT - }; - - /** - * Construct a smart poster. - * - * @param uri The URI to the resource. - */ - SmartPoster(const URI &uri); - - /** - * Set the title of the resource. - * - * @param text The title of the resource to set. - */ - void set_title(const Text &text); - - /** - * Set the icon of the resource. - * - * @param icon The icon to set. - */ - void set_icon(const Mime &icon); - - /** - * Set the action to trigger upon smart poster reception. - * - * @param action The action to do upon reception. - */ - void set_action(action_t action); - - /** - * Set the size of the resource. - * - * @param size The size of the resource. - */ - void set_resource_size(uint32_t size); - - /** - * Set the type of the resource. - * - * @param resource_type The type of the resource pointed by the URI. - */ - void set_resource_type(mbed::Span &resource_type); - - /** - * Append the smart poster as a ndef record. - * - * @param ndef_builder The message builder where the record is appended. - * @param is_last_record Indicates if this message is the last one. - * - * @return true if the message has been appended to the builder or false - * otherwise. - */ - bool append_record(MessageBuilder &ndef_builder, bool is_last_record) const; - -private: - void append_uri(MessageBuilder &builder) const; - size_t get_uri_record_size() const; - - void append_title(MessageBuilder &builder) const; - size_t get_title_record_size() const; - - void append_icon(MessageBuilder &builder) const; - size_t get_icon_record_size() const; - - void append_action(MessageBuilder &builder) const; - size_t get_action_record_size() const; - - void append_resource_size(MessageBuilder &builder) const; - size_t get_resource_size_record_size() const; - - void append_type(MessageBuilder &builder) const; - size_t get_type_record_size() const; - - URI _uri; - Text _title; - Mime _icon; - action_t _action; - uint32_t _resource_size; - Text _type; - - bool _action_set : 1; - bool _resource_size_set : 1; -}; - -#endif /* SMARTPOSTER_H_ */ diff --git a/TEST_APPS/device/nfcapp/main.cpp b/TEST_APPS/device/nfcapp/main.cpp deleted file mode 100644 index 72f6ead2d59..00000000000 --- a/TEST_APPS/device/nfcapp/main.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2018 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include -#include -#include -#include -#include -#include "platform/Span.h" -#include "mbed_events.h" -#include "mbed-client-cli/ns_cmdline.h" -#include "NFCTestShim.h" -#include "NFCCommands.h" - -#if MBED_CONF_NFCEEPROM -using mbed::nfc::NFCEEPROM; -using mbed::nfc::NFCEEPROMDriver; -#else -#ifndef TARGET_PN512 -#warning [NOT_SUPPORTED] NFC not supported for this target -#endif - -#endif // MBED_CONF_NFCEEPROM - -const char *errorcodes = // descriptions from nfc/stack/nfc_errors.h - " 0 NFC_OK\r\n" - " 1 NFC_ERR_UNKNOWN\r\n" - " 2 NFC_ERR_LENGTH\r\n" - " 3 NFC_ERR_NOT_FOUND\r\n" - " 4 NFC_ERR_UNSUPPORTED\r\n" - " 5 NFC_ERR_PARAMS\r\n" - " 6 NFC_ERR_BUFFER_TOO_SMALL\r\n" - " 7 NFC_ERR_TIMEOUT\r\n" - " 8 NFC_ERR_CRC\r\n" - " 9 NFC_ERR_NOPEER\r\n" - "10 NFC_ERR_PARITY\r\n" - "11 NFC_ERR_FIELD\r\n" - "12 NFC_ERR_COLLISION\r\n" - "13 NFC_ERR_WRONG_COMM\r\n" - "14 NFC_ERR_PROTOCOL\r\n" - "15 NFC_ERR_BUSY\r\n" - "16 NFC_ERR_CONTROLLER\r\n" - "17 NFC_ERR_HALTED\r\n" - "18 NFC_ERR_MAC\r\n" - "19 NFC_ERR_UNDERFLOW\r\n" - "20 NFC_ERR_DISCONNECTED\r\n" - "21 NFC_ERR_ABORTED\r\n"; - - -void wrap_printf(const char *f, va_list a) -{ - vprintf(f, a); -} - - -/** Disables VT100 etc. for easy manual UI interaction */ -int set_easy_printer(int argc, char *argv[]) -{ - const char msg[][20] = - { "echo off", "set --retcode true", "set --vt100 off" }; - for (size_t i = 0; i < (sizeof(msg) / sizeof(msg[0])); i++) { - cmd_exe((char *) msg[i]); - } - return (CMDLINE_RETCODE_SUCCESS); -} - - -/** - * This test app can be used standalone interactively with at 115200 baud terminal. It is designed to work with the - * IceTea test framework https://os.mbed.com/docs/latest/tools/icetea-testing-applications.html . This app does - * not run test cases, it wraps functions in the API in ways that let us test multiple cases and scenarios. - * Test commands are routed in the CommandHandler class to an eventqueue, so it interfaces to the driver - * on a separate driver thread, which means test functions complete asynchronously. - * The driver is only called in a thread in the shim or wrapper class called NFCTestShim, which handles driver - * callbacks and completes the async part of a test function. NFCTestShim has specializations for NFC controllers - * and EEPROMS. The classes NFCProcessController and NFCProcessEEPROM respectively implement the needed specialization. - * - * If using an NFC EEPROM, an extra library is needed. Please see the documentation in the README.MD for instructions - * on how to modify this test for new drivers/targets, and the steps to run this test suite. - */ -int main() -{ - cmd_init(&wrap_printf); - HandleTestCommand handleCommands; // For handling test commands and set nfc message queue - - cmd_add("getlastnfcerror", HandleTestCommand::cmd_get_last_nfc_error, - "last NFC error code", errorcodes); - cmd_add("setlastnfcerror", HandleTestCommand::cmd_set_last_nfc_error, - "self-test", "for self-test only"); - cmd_add("iseeprom", HandleTestCommand::cmd_get_conf_nfceeprom, - "get NFC configEEPROM present", - "true if config exists, else false"); - cmd_add("initnfc", HandleTestCommand::cmd_init_nfc, "init NFC driver", - "call first"); - cmd_add("getmaxndef", HandleTestCommand::cmd_get_max_ndef, "get max NDEF record target supports", - "returns the eeprom size, or max buffer if a controller"); - cmd_add("init", HandleTestCommand::cmd_init_nfc, "alias initnfc", - "call first"); - cmd_add("setsmartposter", HandleTestCommand::cmd_set_smartposter, - "send smartposter NDEF", ""); - cmd_add("readmessage", HandleTestCommand::cmd_read_message, - "read EEPROM else return last message", "returns hex dump"); - cmd_add("read", HandleTestCommand::cmd_read_message, "alias readmessage", - "returns hex dump"); - cmd_add("erase", HandleTestCommand::cmd_erase, - "erase EEPROM or clear last message", "erase entire flash/buffer"); - cmd_add("writelong", HandleTestCommand::cmd_write_long_ndef_message, - "fill T NDEF with pattern up to ", - "writelong [messagetorepeat='thequickbrownfoxisadog']"); - cmd_add("start", HandleTestCommand::cmd_start_discovery, - "start discovery [auto=autorestart|man=manual]", - "loop restarts by default, man to disable"); - cmd_add("stop", HandleTestCommand::cmd_stop_discovery, "stop discovery", - "[wait=0] with optional wait for session end"); - - cmd_add("getprotocols", HandleTestCommand::cmd_get_supported_rf_protocols, - "get supported protocols", "returns CSV list, see setprotocols"); - cmd_add("setprotocols", HandleTestCommand::cmd_configure_rf_protocols, - "set rf protocols", "-p [t1t]/[t2t]/[t3t]/[isodep]/[nfcdep]/[t5t]"); - cmd_add("easy", set_easy_printer, "Use human readable terminal output", - "echo off,vt100 off,return-codes visible"); - cmd_add("trace", HandleTestCommand::cmd_set_trace, "detailed tracing on/off, ", - "Defaults to enabled; values like 'on','true','1' all turn it on, anything else turns off detailed tracing."); - -#if MBED_CONF_NFCEEPROM - cmd_printf("MBED NFC EEPROM defined\r\n"); -#else - cmd_printf("MBED NFC Controller tests\r\n"); -#endif - -#ifdef TARGET_M24SR - cmd_printf("Using driver: M24SR\r\n"); -#endif -#ifdef TARGET_PN512 - cmd_printf("Using driver: PN512\r\n"); -#endif - { - int c; - while ((c = getc(stdin)) != EOF) { - cmd_char_input(c); - } - } - return 0; -} diff --git a/TEST_APPS/device/nfcapp/mbed_app.json b/TEST_APPS/device/nfcapp/mbed_app.json deleted file mode 100644 index 291ce371f0d..00000000000 --- a/TEST_APPS/device/nfcapp/mbed_app.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "config": { - "TEST_NDEF_MSG_MAX": { - "help": "NFC-Driver buffer (EEPROM and Controller) maximum MAX Size of NFC message(s) driver buffer", - "value": 4096 - } - }, - "target_overrides": { - "DISCO_L475VG_IOT01A": { - "target.extra_labels_add": ["M24SR"], - "MBED_NFC_M24SR.nfceeprom": true - }, - "NUCLEO_F401RE": { - "target.extra_labels_add": ["PN512"], - "MBED_NFC_M24SR.nfceeprom": false - }, - "NUCLEO_F746ZG": { - "target.extra_labels_add": ["M24SR"], - "MBED_NFC_M24SR.X_NUCLEO_NFC01A1": true, - "MBED_NFC_M24SR.nfceeprom": true - }, - "NUCLEO_F429ZI": { - "target.extra_labels_add": ["M24SR"], - "MBED_NFC_M24SR.X_NUCLEO_NFC01A1": true, - "MBED_NFC_M24SR.nfceeprom": true - } - } -} diff --git a/TEST_APPS/device/nfcapp/uart.cpp b/TEST_APPS/device/nfcapp/uart.cpp deleted file mode 100644 index 807d0d2aee4..00000000000 --- a/TEST_APPS/device/nfcapp/uart.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2018 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include -#include "platform/FileHandle.h" -#include "drivers/BufferedSerial.h" - -/** - * Macros for setting console flow control. - */ -#define CONSOLE_FLOWCONTROL_RTS 1 -#define CONSOLE_FLOWCONTROL_CTS 2 -#define CONSOLE_FLOWCONTROL_RTSCTS 3 -#define mbed_console_concat_(x) CONSOLE_FLOWCONTROL_##x -#define mbed_console_concat(x) mbed_console_concat_(x) -#define CONSOLE_FLOWCONTROL mbed_console_concat(MBED_CONF_TARGET_CONSOLE_UART_FLOW_CONTROL) - -#define SERIAL_CONSOLE_BAUD_RATE 115200 - -mbed::FileHandle *mbed::mbed_override_console(int) -{ - static mbed::BufferedSerial console( - STDIO_UART_TX, STDIO_UART_RX, SERIAL_CONSOLE_BAUD_RATE - ); -#if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS - mbed::console.set_flow_control(SerialBase::RTS, STDIO_UART_RTS, NC); -#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS - mbed::console.set_flow_control(SerialBase::CTS, NC, STDIO_UART_CTS); -#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS - mbed::console.set_flow_control(SerialBase::RTSCTS, STDIO_UART_RTS, STDIO_UART_CTS); -#endif - return &console; -} diff --git a/TEST_APPS/icetea_plugins/__init__.py b/TEST_APPS/icetea_plugins/__init__.py deleted file mode 100644 index b09b705cde2..00000000000 --- a/TEST_APPS/icetea_plugins/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -Copyright (c) 2020 Arm Limited -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" diff --git a/TEST_APPS/icetea_plugins/ip_test_parsers.py b/TEST_APPS/icetea_plugins/ip_test_parsers.py deleted file mode 100644 index 7f215be8d7d..00000000000 --- a/TEST_APPS/icetea_plugins/ip_test_parsers.py +++ /dev/null @@ -1,159 +0,0 @@ -""" -Copyright 2018 ARM Limited -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" -import re -import time -from collections import OrderedDict -from datetime import datetime - -from icetea_lib.Plugin.PluginBase import PluginBase - - -class IpTestParsers(PluginBase): - # constructor - def __init__(self): - super(IpTestParsers, self).__init__() - - def get_parsers(self): - return { - 'ifconfig': self.__ifconfigParser, - 'ifup': self.__ifconfigParser, - 'ethup': self.__ifconfigParser, - 'dut1': self.__ifconfigParser, - 'dut2': self.__ifconfigParser, - 'dut3': self.__ifconfigParser, - 'dut4': self.__ifconfigParser, - 'dut5': self.__ifconfigParser, - 'dut6': self.__ifconfigParser, - 'socket': self.__mbedossocketParser, - 'ticker': self.__ticker_parser - } - - # socket command for mbedos - def __mbedossocketParser(self, response): - results = {'socket_id': None, - 'data_type': None, - 'data': "", - 'printed_bytes': None, - 'sent_bytes': None, - 'received_bytes': None, - 'address': None, - 'port': None, - 'loop_id': None - } - respLines = response.lines - part = None - for line in respLines: - ret = PluginBase.find_one(line, ".*sid: ([0-9]+)") - if ret is not False: - results['socket_id'] = ret - - ret = PluginBase.find_one(line, ".*(hex|string) data, printing .* bytes:") - if ret is not False: - results['data_type'] = ret - - ret = PluginBase.find_one(line, ".*data, printing (.*) bytes:") - if ret is not False: - part = "data" - - ret = PluginBase.find_one(line, "^Printed (.*) bytes$") - if ret is not False: - results['printed_bytes'] = int(ret) - part = None - - if part == "data": - ret = PluginBase.find_one(line, "^\d{4}: (.*)$") - if ret is not False: - results['data'] = results['data'] + ret - - ret = PluginBase.find_one(line, ".*sent: ([0-9]+) bytes") - if ret is not False: - results['sent_bytes'] = int(ret) - - ret = PluginBase.find_one(line, ".*received: ([0-9]+) bytes") - if ret is not False: - results['received_bytes'] = int(ret) - - ret = PluginBase.find_one(line, ".*address: ([0-9a-fxA-F:.]+)") - if ret is not False: - results['address'] = ret - - ret = PluginBase.find_one(line, ".*port: ([0-9]+)") - if ret is not False: - results['port'] = ret - - ret = PluginBase.find_one(line, ".*lid: ([0-9]+)") - if ret is not False: - results['loop_id'] = ret - - return results - - # response parser for ifup - def __ifconfigParser(self, response): - results = {} - lines = response.traces - part = None - - results['address'] = { - 'll': '', - 'globals': [], - 'ipv4': None, - 'ipv6': [] - } - - for line in lines: - # print "ifcfgparser: %s" % line - match = re.search('IPv6 if addr', line) - if match: - part = "address" - match = re.search('IPv4 if addr', line) - if match: - part = "address" - match = re.search('MAC-48\:[\W]{1,}(.*)', line) - if match: - mac48 = match.group(1) - # Validate the MAC-48 syntax as well - match = re.search("([0-9a-fA-F]{2}:??){5}([0-9a-fA-F]{2})", mac48) - if match: - results['MAC'] = mac48 - - if part == "address": - match = re.search('.*\[(\d)\]:\W([abcdefg\d\:]{5,})', line) - if match: - addr = match.group(2) - if re.search('^fe80\:\:', addr): - results['address']['ll'] = addr - else: - results['address']["globals"].append(addr) - - match = re.search('\[(\d)\]:\W([a-fA-F\d\:]{5,})', line) - if match: - results['address']['ipv6'].append(match.group(2)) - - match = re.search('(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$', line) - if match: - results['address']['ipv4'] = match.group(1) - - return results - - def __ticker_parser(self, response): - results = {} - respLines = response.lines - for line in respLines: - ret = PluginBase.find_one(line, 'Ticker id: ([0-9]+)') - if ret is not False: - results['ticker_id'] = ret - return results diff --git a/TEST_APPS/icetea_plugins/nfc_test_parsers.py b/TEST_APPS/icetea_plugins/nfc_test_parsers.py deleted file mode 100644 index 633ced1542e..00000000000 --- a/TEST_APPS/icetea_plugins/nfc_test_parsers.py +++ /dev/null @@ -1,139 +0,0 @@ -""" -Copyright 2018 ARM Limited -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - - -from icetea_lib.Plugin.PluginBase import PluginBase -import re -import os - -class NfcTestParsers(PluginBase): - # constructor - def __init__(self): - super(NfcTestParsers, self).__init__() - - def get_parsers(self): - return { - 'iseeprom': self.status_parser, - 'getmaxndef': self.status_parser, - 'getlastnfcerror': self.trace_parser, - 'setlastnfcerror': self.trace_parser, - 'initnfc': self.trace_parser, # all commands that return an NFC error code - 'readmessage' : self.trace_parser, - 'erase' : self.trace_parser, - 'writelong' : self.trace_parser, - 'stop' : self.trace_parser, - 'start' : self.trace_parser, - 'setsmartposter': self.trace_parser, - 'getprotocols': self.trace_parser, - 'setprotocols': self.trace_parser - } - - def status_parser(self, response): - """ - commands that do NOT return an NFC result-code - """ - results = {'iseeprom': None, # 'true' if EEPROM - 'lastnfcerror':0, # ignored here - 'maxndef':None # actual driver buffer size - } - respLines = response.lines - for line in respLines: - try: - # iseeprom - value = PluginBase.find_one(line, "{{iseeprom=([\w]+)}}") - if value is not False: - if ("TRUE" == value.upper() or "1" == value): - results['iseeprom'] = True - else: - results['iseeprom'] = False - # max ndef - value = PluginBase.find_one(line, "{{maxndef=([0-9]+)}}") - if value is not False: - results['maxndef'] = int(value) - except re.error as e: # the framework gobbles errors in the plugin - print("Regex error",e,"occured in",os.path.basename(__file__), "!!") - raise e - return results - - def convert_from_hex(self, data): - value = [] - for byte in data.split(' '): - if bool(byte): - if len(byte) > 2: # the line wrapping code for huge lines appears to munch the space character between 2 bytes - value.append( int(byte[:2], 16)) - value.append( int(byte[2:4], 16)) - else: - value.append( int(byte, 16)) - return value - - # regex findall with additional filtering - @staticmethod - def find_all_hex_data(line, lookup): - """ - regexp search with one value to return. - - :param line: Line - :param lookup: regexp - :return: List of match groups or False - """ - results = re.findall(lookup, line) - if results is not False: - results = [m for m in results if len(m) > 2] # remove empty matches and - # non hex-data result entries - return results - return False - - def trace_parser(self, response): - results = {'iseeprom': None, # 'true' if EEPROM - 'lastnfcerror':None, # 0=OK >0 = error - 'nfcmessage':None, # NDEF array of bytes - 'protocols':None, # csv list - 'uri_id':None} # nfc URI type identifier - respLines = response.lines - started_read_data = False - partial_data = "" - for line in respLines: - try: - value = PluginBase.find_one(line, "{{lastnfcerror=([0-9]+)}}") - if value is not False: - results['lastnfcerror'] = int(value) - # {{nfcmessage=([0-9a-f\s]*)}} - # message may be split over multiple lines, so we will start a search and wait until we get a }} pair - data = PluginBase.find_one(line, "{{nfcmessage=([0-9a-f\s]*).*") - if data is not False: - started_read_data = True - if started_read_data: # read data until we see a }} pair - if "{{nfcmessage=" in line: - line = line[13:] # trim header - if PluginBase.find_one(line, ".*(}})") is not False: # search for end marker - started_read_data = False - line = line[:-2] # trim closing }} - partial_data += line - if not started_read_data: - results['nfcmessage'] = self.convert_from_hex(partial_data) - # t1t,t2t,t3t,isodep,nfcdef,t5t - value = PluginBase.find_one(line, "{{protocols=(([\w]*,?)*)}}") - if value is not False: - results['protocols'] = value # a csv list - # smartposter uri - value = PluginBase.find_one(line, "{{uri_id=([0-9]+)}}") - if value is not False: - results['uri_id'] = int(value) - except re.error as e: # the framework gobbles errors in the plugin - print("Regex error",e,"occured in",os.path.basename(__file__), "!!") - raise e - return results diff --git a/TEST_APPS/icetea_plugins/plugins_to_load.py b/TEST_APPS/icetea_plugins/plugins_to_load.py deleted file mode 100644 index bc8b9be74a2..00000000000 --- a/TEST_APPS/icetea_plugins/plugins_to_load.py +++ /dev/null @@ -1,24 +0,0 @@ -""" -Copyright 2018 ARM Limited -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" -from ip_test_parsers import IpTestParsers -from nfc_test_parsers import NfcTestParsers - - -plugins_to_load = { - "ip_test_parsers": IpTestParsers, - "nfc_test_parsers": NfcTestParsers -} diff --git a/TEST_APPS/readme.md b/TEST_APPS/readme.md deleted file mode 100644 index 01c9c417511..00000000000 --- a/TEST_APPS/readme.md +++ /dev/null @@ -1,101 +0,0 @@ -## Running Icetea tests located under mbed-os - -### Structure - -Mbed OS has a folder called `TEST_APPS` that contains everything related to Icetea testing. - -There are currently three folders: - -- `device` - contains all the different test applications you can flash to your board. -- `icetea_plugins` - contains plugins that are being used by some of the testcases, needed for the test execution. -- `testcases` - contains Icetea testcases written in Python. - -The testcases depend on test applications. - -### Preparing your work environment - -#### Prerequisites - -You need Icetea and version 1.8.0 or higher of Mbed CLI installed. - -#### Selecting the network interface to use - -Depending on the device, there might be a default network interface type defined in `mbed-os/targets/targets.json`, which you can use to locate a default test-config file. - -If the default network interface type is not defined or you want to use a different interface than the default, you need to provide a test-config file to the mbed test with `--test-config` option. - -The test-config file contains the necessary information for the test application. There are some test-config files located under `mbed-os/tools/test_configs`. - -Devices that have their network drivers residing inside `mbed-os` can use generic `test_configs`, such as `HeapBlockDeviceAndEthernetInterface.json` and `HeapBlockDeviceAndWifiInterface.json`. Otherwise, you need to use a device-specific test-config. - -### Running the tests - -Now that you have selected the interface, you can run the Icetea tests from the `mbed-os` root on your command-line by running the following command: - -`mbed test -m -t --icetea` - -This command compiles the OS, compiles the test applications, creates a test suite and then starts running the tests. - -If you only want to run some specific tests, you can use the `-n` option. You can choose multiple tests by separating them with a comma (`,`): - -`mbed test -m -t --icetea -n test1,test2` - -#### Running the tests with a specific test-config - -Some devices may offer multiple network interfaces to operate with. The tests can be run for either one of those using already existing test-config -files. - -To run the tests with the Wi-Fi interface: - -`mbed test -m -t --icetea --test-config tools/test_configs/HeapBlockDeviceAndWifiInterface.json` - -To run the tests with the ethernet interface: - -`mbed test -m -t --icetea --test-config tools/test_configs/HeapBlockDeviceAndEthernetInterface.json` - -#### Providing Wi-Fi access point information - -If you are using the Wi-Fi interface for running the tests, you need to also provide information about the used access point. - -The information can be provided in the used test-config file. - -Example of access point information: - -``` - "target_overrides": { - "*": { - "target.network-default-interface-type": "WIFI", - "nsapi.default-wifi-ssid": "\"ssid\"", - "nsapi.default-wifi-password": "\"password\"", - "nsapi.default-wifi-security": "WPA_WPA2" - } - } -``` - -### Test results - -Icetea prints the results from the test run to the command-line, and the final result looks similar to this: - -``` -+--------------------------------+---------+-------------+-------------+-----------+----------+ -| Testcase | Verdict | Fail Reason | Skip Reason | platforms | duration | -+--------------------------------+---------+-------------+-------------+-----------+----------+ -| test_cmdline | pass | | | K64F | 8.555 | -| UDPSOCKET_BIND_PORT | pass | | | K64F | 19.614 | -| TCPSOCKET_BIND_PORT | pass | | | K64F | 15.852 | -| TCPSERVER_ACCEPT | pass | | | K64F | 41.629 | -| TCPSOCKET_ECHOTEST_BURST_SHORT | pass | | | K64F | 19.926 | -+--------------------------------+---------+-------------+-------------+-----------+----------+ -+---------------+----------------+ -| Summary | | -+---------------+----------------+ -| Final Verdict | PASS | -| count | 5 | -| passrate | 100.00 % | -| pass | 5 | -| Duration | 0:01:45.576000 | -+---------------+----------------+ -``` - -You can also find the results from the tests in the `mbed-os/log` folder. - -You probably want to add the log folder to your `.mbedignore` file to prevent issues with build commands becoming too long over the time. diff --git a/TEST_APPS/testcases/README.md b/TEST_APPS/testcases/README.md deleted file mode 100644 index a3aec02ff4a..00000000000 --- a/TEST_APPS/testcases/README.md +++ /dev/null @@ -1,14 +0,0 @@ -Icetea tests -============ - -This folder contains all the test cases done with Icetea residing in `mbed-os`. -The tests are divided in to subfolders and each subfolder contains a set of testcases. -The subfolder has a description of all the testcases it contains. - -Testcases ---------- - -Current testcases: - -- [`example`](https://github.com/ARMmbed/mbed-os/blob/master/TEST_APPS/testcases/example) -- [`nanostack_mac_tester`](https://github.com/ARMmbed/mbed-os/blob/master/TEST_APPS/testcases/nanostack_mac_tester) diff --git a/TEST_APPS/testcases/__init__.py b/TEST_APPS/testcases/__init__.py deleted file mode 100644 index b09b705cde2..00000000000 --- a/TEST_APPS/testcases/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -Copyright (c) 2020 Arm Limited -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" diff --git a/TEST_APPS/testcases/example/README.md b/TEST_APPS/testcases/example/README.md deleted file mode 100644 index 1b5cddac678..00000000000 --- a/TEST_APPS/testcases/example/README.md +++ /dev/null @@ -1,22 +0,0 @@ -##Example tests - -This folder contains example tests for Icetea -The test located under this folder is dependent of the application [`exampleapp`](https://github.com/ARMmbed/mbed-os/blob/master/TEST_APPS/device/exampleapp) -The exampleapp is disabled by default, to be able to run the test_cmdline with the exampleapp, either remove the preprocessor macro from exampleapp.cpp or add `-DICETEA_EXAMPLE_ENABLED` to the mbed test command - -## Test cases - -### `test_cmdline` - -**Description:** -Send command line commands to target over serial interface. -This test introduces the Icetea test case structure to the user. - -**Test steps:** -Send "echo hello world" to the target. -Target sends "hello world" back to the host machine. -Send help to the target. -Target prints out the command line commands the application supports. - -**Expected result:** -The test exits without timeouts. diff --git a/TEST_APPS/testcases/example/__init__.py b/TEST_APPS/testcases/example/__init__.py deleted file mode 100644 index b09b705cde2..00000000000 --- a/TEST_APPS/testcases/example/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -Copyright (c) 2020 Arm Limited -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" diff --git a/TEST_APPS/testcases/example/test_cmdline.py b/TEST_APPS/testcases/example/test_cmdline.py deleted file mode 100644 index 6988f0b0ca3..00000000000 --- a/TEST_APPS/testcases/example/test_cmdline.py +++ /dev/null @@ -1,52 +0,0 @@ -""" -Copyright 2018 ARM Limited -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -from icetea_lib.bench import Bench - - -class Testcase(Bench): - def __init__(self): - Bench.__init__(self, - name="test_cmdline", - title="Smoke test for command line interface", - status="released", - purpose="Verify Command Line Interface", - component=["cmdline"], - type="smoke", - requirements={ - "duts": { - '*': { - "count": 1, - "type": "hardware", - "application": { - "name": "TEST_APPS-device-exampleapp" - } - }, - "1": {"nick": "dut1"}, - } - } - ) - - def setup(self): - pass - - def case(self): - self.command("dut1", "echo hello world") - self.command("dut1", "help") - - def teardown(self): - pass diff --git a/TEST_APPS/testcases/nanostack_mac_tester/ED_scan.py b/TEST_APPS/testcases/nanostack_mac_tester/ED_scan.py deleted file mode 100644 index eef8d96bdc1..00000000000 --- a/TEST_APPS/testcases/nanostack_mac_tester/ED_scan.py +++ /dev/null @@ -1,139 +0,0 @@ -""" -Copyright (c) 2017, Arm Limited and affiliates. -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -import threading -import os,sys -from icetea_lib.bench import Bench -from icetea_lib.TestStepError import TestStepFail - -class Testcase(Bench): - def __init__(self): - Bench.__init__(self, name = "ED_scan", - title = "ED scan test", - status = "released", - type = "smoke", - subtype = "", - execution = { - "skip": { - "value": False, - "reason": "" - } - }, - author = "Valtteri Erkkila", - purpose = "Tests reading the ED values from channels 11-16", - feature = ["MLME-SCAN (ED)"], - component = ["MAC"], - requirements = { - "duts": { - '*': { - "count":3, - "type": "hardware", - "allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW41Z"], - "application": { - "name": "TEST_APPS-device-nanostack_mac_tester" - } - }, - "1":{"nick": "First"}, - "2":{"nick": "Second"}, - "3":{"nick": "Third"} - }} - ) - - def setUp(self): - self.channel = 11 - - def spam_channel(self, event): - while not event.wait(0.1): - self.lock_th.acquire() - self.command("First", "data --dst_addr 01:02:03:00:00:00:00:03 --msdu {} --msdu_length {} --wait_for_confirm false".format(self.payload, len(self.payload))) - self.command("Third", "data --dst_addr 01:02:03:00:00:00:00:01 --msdu {} --msdu_length {} --wait_for_confirm false".format(self.payload, len(self.payload))) - self.lock_th.release() - - def mask_from_channel_list(self, channels): - res = 0 - for ch in channels: - res = res | ( 1 << ch) - return hex(res) - - def do_test_iteration(self): - self.lock_th = threading.Lock() - self.command("First", "mlme-reset") - self.command("Second", "mlme-reset") - self.command("Third", "mlme-reset") - - self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01") - self.command("Second", "addr --64-bit 01:02:03:00:00:00:00:02") - self.command("Third", "addr --64-bit 01:02:03:00:00:00:00:03") - - self.payload = "01234567890123456789012345678901234567890123456789" - - # Start PAN coordinator - self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel)) - # Start PAN beacon - self.command("Second", "start --pan_coordinator false --logical_channel {}".format(self.channel)) - self.command("Third", "start --pan_coordinator false --logical_channel {}".format(self.channel)) - - #No reason to print their spamming - self.command("First", "silent-mode on") - self.command("Third", "silent-mode on") - - self.stop_event = threading.Event() - self.th = threading.Thread(target=self.spam_channel, args=(self.stop_event,)) - self.th.start() - self.stopped = True - channels = range(11,27) - for i in range(0, 3): - self.lock_th.acquire() - # Reset MAC settings - self.command("First", "mlme-reset") - # Start PAN coordinator - self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel)) - self.command("Third", "mlme-reset") - # Start PAN beacon - self.command("Third", "start --pan_coordinator false --logical_channel {}".format(self.channel)) - self.lock_th.release() - # Scan all channels - self.command("Second", "scan --scan_type 0 --scan_duration 7 --channel_mask {}".format(self.mask_from_channel_list(channels))) - # Energy detection analysis - self.command("Second", "analyze-ed --channel {} --above 100".format(self.channel)) - - def case(self): - # Try tests few times because of potential RF failures - loop = 0 - while loop < 5: - try: - self.do_test_iteration() - break - except TestStepFail: - self.logger.info("Warning, iteration failed #" + str(loop+1)) - loop = loop + 1 - if (loop < 5): - self.stop_event.set() - self.th.join() - self.delay(5) - - else: - raise TestStepFail("Too many failed iterations!") - - def tearDown(self): - self.command("First", "silent-mode off") - self.command("Third", "silent-mode off") - self.stop_event.set() - self.th.join() - del self.th - self.reset_dut() - diff --git a/TEST_APPS/testcases/nanostack_mac_tester/README.md b/TEST_APPS/testcases/nanostack_mac_tester/README.md deleted file mode 100644 index a7edcf73f7c..00000000000 --- a/TEST_APPS/testcases/nanostack_mac_tester/README.md +++ /dev/null @@ -1,298 +0,0 @@ -## Nanostack MAC RF tests - -This folder contains nanostack MAC RF tests for Icetea. -The test located under this folder is dependent of the application [`nanostack_mac_tester`](https://github.com/ARMmbed/mbed-os/blob/master/TEST_APPS/device/nanostack_mac_tester). -The nanostack MAC tester is disabled by default. To run the test cases with the application, either remove the preprocessor macro from main.cpp or add `-DICETEA_MAC_TESTER_ENABLED` to the `mbed test` command. - -Icetea test cases are processed by passing commands through the `mbed-client-cli` command line. It is possible to manually replicate most test cases by following the instructions below. - -In test cases with more than one device under test (DUT) the target device is given in the instructions as DUT1, DUT2 or DUT3. - -## Test cases - -### `address_read_and_write` - -**Description:** - -Write addresses to MAC interface, verify successful write. - -**Preconditions:** - -None - -**Test steps:** - -1. Set 64-bit MAC address to 01:02:03:00:00:00:00:01: - `addr --64-bit 01:02:03:00:00:00:00:01` -2. Set 16-bit MAC address to 0xABCD: - `addr --16-bit 0xABCD` -3. Set MAC PAN ID to 0xCDCD: - `mlme-set --attr 0x50 --value_bytes CD:CD --value_size 2` -4. Read and verify 64-bit address: - `addr` - -**Expected result:** - -The address that was read is the same as the one that was written. - -The test exits with status `PASS` without timeouts. - -### `create_and_join_PAN` - -**Description:** - -Create two Personal Area Networks (PAN) and verify beacon transmission. - -Requires 3 devices. - -**Preconditions:** - -1. All devices have 802.15.4 tranceivers and are in sufficient proximity. -2. RF channel and adjacent channel are sufficiently clear. - The RF channel is set in the test case method setUp(). The adjacent - channel is automatically the next higher one, except for channel 26, - where the adjacent channel becomes the next lower one. This is because - 26 is the highest available of the 16 channels in the 2.4-GHz band. - -**Test steps:** - -1. DUT1: Set MAC beacon payload to "mac-tester": - `mlme-set --attr 0x45 --value_ascii mac-tester --value_size 10` -2. DUT1: Set payload length: - `mlme-set --attr 0x46 --value_uint8 10 --value_size 1` -3. DUT2: Set MAC beacon payload to "second-mac-tester": - `mlme-set --attr 0x45 --value_ascii second-mac-tester --value_size 17` -4. DUT2: Set payload length: - `mlme-set --attr 0x46 --value_uint8 17 --value_size 1` -5. DUT1: Start PAN coordinator in chosen channel: - `start --pan_coordinator true --logical_channel ` -6. DUT2: Start PAN coordinator in adjacent channel: - `start --pan_coordinator true --logical_channel ` -7. DUT3: Scan with channel mask: - `scan --channel_mask ` - Channel mask is given as a left bitshifted channel number in hexadecimal format. - For channels 11 and 12, the channel mask becomes 0x1800. -8. DUT3: Search beacon data for DUT1's beacon: - `find-beacon --data mac-tester` -9. DUT3: Search beacon data for DUT2's beacon: - `find-beacon --data second-mac-tester` - -**Expected result:** - -DUT1 and DUT2 start beacon transmissions on respective channels. - -DUT3 receives and parses beacon transmissions. - -The test exits with status `PASS` without timeouts. - -### `ED_scan` - -**Description:** - -Perform Energy Detection (ED) scan to find Personal Area Networks (PAN). - -The test case requires that a lot of data is sent on the RF channel. In the test case -this is done automatically at a rate that is hard to perform manually, which makes -it difficult to run the test case manually. - -Requires 3 devices. - -**Preconditions:** - -1. All devices have 802.15.4 tranceivers and are in sufficient proximity. -2. RF channel is sufficiently clear. - -**Test steps:** - -1. Set addresses for devices: - DUT1: `addr --64-bit 01:02:03:00:00:00:00:01` - DUT2: `addr --64-bit 01:02:03:00:00:00:00:02` - DUT3: `addr --64-bit 01:02:03:00:00:00:00:03` -2. DUT1: Start PAN coordinator: - `start --pan_coordinator true --logical_channel ` -3. DUT2,DUT3: Start PAN beacon: - `start --pan_coordinator false --logical_channel ` -4. (optional) Silence beacon traces: - `silent-mode on` -5. Start repeatedly sending data between DUT1 and DUT3: - DUT1: `data --dst_addr 01:02:03:00:00:00:00:03 --msdu --msdu_length --wait_for_confirm false` - DUT3: `data --dst_addr 01:02:03:00:00:00:00:01 --msdu --msdu_length --wait_for_confirm false` - In the test case this repeats every 100ms. -6. DUT1,DUT3: Reset MAC settings: - `mlme-reset` -7. DUT1: Start PAN coordinator: - `start --pan_coordinator true --logical_channel ` -8. DUT3: Start PAN beacon: - `start --pan_coordinator false --logical_channel ` -9. DUT2: Scan channels 11-26: - `scan --scan_type 0 --scan_duration 7 --channel_mask 0x7fff800` - Channel mask is given as a left bitshifted channel numbers in hexadecimal format. -10. DUT2: Do Energy Detection analysis on data: - `analyze-ed --channel --above 100` - -Test case repeats steps 5 to 10 three times. - -**Expected result:** - -Devices start beacon transmissions and send data on channel. - -DUT2 scans channels for activity, and verifies that ED value for test channel is above 100. - -The test exits with status `PASS` without timeouts. - -### `send_data` - -**Description:** - -Send data between two devices over single RF hop. - -Requires 2 devices. - -**Preconditions:** - -1. All devices have 802.15.4 tranceivers and are in sufficient proximity. -2. RF channel is sufficiently clear. - -**Test steps:** - -1. DUT1: Set 64-bit MAC address to 01:02:03:00:00:00:00:01: - `addr --64-bit 01:02:03:00:00:00:00:01` -2. DUT2: Set 64-bit MAC address to 01:02:03:00:00:00:00:02: - `addr --64-bit 01:02:03:00:00:00:00:02` -3. DUT1: Start PAN coordinator: - `start --pan_coordinator true --logical_channel ` -4. DUT2: Start PAN beacon: - `start --pan_coordinator false --logical_channel ` -5. DUT1: Send data to DUT2: - `data --dst_addr 01:02:03:00:00:00:00:02 --msdu_length 5 --msdu abcde` -6. DUT1: Send data to DUT2: - `data --dst_addr 01:02:03:00:00:00:00:01 --msdu_length 5 --msdu 12345` - -**Expected result:** - -Data send commands succeeds. - -The test exits with status `PASS` without timeouts. - -### `send_data_indirect` - -**Description:** - -Send data between two devices over two RF hops with one relay. - -Requires 3 devices. - -**Preconditions:** - -1. All devices have 802.15.4 tranceivers and are in sufficient proximity. -2. RF channel is sufficiently clear. - -**Test steps:** - -1. DUT1: Set 64-bit MAC address to 01:02:03:00:00:00:00:01: - `addr --64-bit 01:02:03:00:00:00:00:01` -2. DUT2: Set 64-bit MAC address to 01:02:03:00:00:00:00:02: - `addr --64-bit 01:02:03:00:00:00:00:02` -3. DUT3: Set 64-bit MAC address to 01:02:03:00:00:00:00:03: - `addr --64-bit 01:02:03:00:00:00:00:03` -4. DUT1: Start PAN coordinator: - `start --pan_coordinator true --logical_channel ` -5. DUT2: Start PAN beacon: - `start --pan_coordinator false --logical_channel ` -6. DUT3: Start PAN beacon: - `start --pan_coordinator false --logical_channel ` -7. DUT2,DUT3: Set MAC RX on-while-idle off: - `mlme-set --attr 0x52 --value_uint8 0 --value_size 1` -8. DUT1: Add DUT2 and DUT3 as neighbours: - `add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:02 --pan_id 0x1234 --index 0` - `add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:03 --pan_id 0x1234 --index 1` -9. DUT2,DUT3: Add DUT1 as neighbour: - `add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:01 --pan_id 0x1234 --index 0` -10. DUT2: Configure indirect data: - `config-status --data_ind abcde` -10. DUT3: Configure indirect data: - `config-status --data_ind 12345` -11. DUT1,DUT2,DUT3: Mute traces (can cause timing issues): - `silent-mode on` -12. DUT1: Send data indirectly to DUT2: - `data --dst_addr 01:02:03:00:00:00:00:02 --msdu_length 5 --msdu abcde --indirect_tx true --wait_for_confirm false` -13. DUT2: Poll DUT1 (coordinator) for data: - `poll --coord_address 01:02:03:00:00:00:00:01` -14. DUT1: Resend data twice: - `data` - `data` -15. DUT2: Poll data twice: - `poll` - `poll` -16. DUT2: Set expected poll return status to 0xEB (No data after poll): - `config-status --poll 235")` -17. DUT2: Expected fail for poll command: - `poll` -16. DUT2: Set expected poll return status to 0xEB (No data after poll): - `config-status --poll 235")` -17. DUT1: Send data indirectly to DUT3 (other values set before are preserved): - `data --dst_addr 01:02:03:00:00:00:00:03 --msdu 12345` -19. DUT2: Expected fail for poll command: - `poll` -20. DUT3: Poll DUT1 (coordinator) for data: - `poll --coord_address 01:02:03:00:00:00:00:01` - -**Expected result:** - -DUT2 receives data from DUT1 when polling after send. - -DUT2 does not receive data from DUT1 when no data available. - -DUT2 does not receive data from DUT1 when data available for DUT3. - -DUT3 receives data from DUT1 when polling after send. - -The test exits with status `PASS` without timeouts. - -### `send_large_payloads` - -**Description:** - -Send large payloads between two devices. - -Requires 2 devices. - -**Preconditions:** - -1. All devices have 802.15.4 tranceivers and are in sufficient proximity. -2. RF channel is sufficiently clear. - -**Test steps:** - -1. DUT1: Set 64-bit MAC address to 01:02:03:00:00:00:00:01: - `addr --64-bit 01:02:03:00:00:00:00:01` -2. DUT2: Set 64-bit MAC address to 01:02:03:00:00:00:00:02: - `addr --64-bit 01:02:03:00:00:00:00:02` -3. DUT1: Start PAN coordinator: - `start --pan_coordinator true --logical_channel ` -4. DUT2: Start PAN beacon: - `start --pan_coordinator false --logical_channel ` -5. Create large payload: - 104 characters, headers are 2+1+2+8+8+2=23 bytes, resulting in a packet size of 127 (max): - `large_payload = "0123456789abcdefghjiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZZZZZZZZZ0123456789012345678901234567891234"` -6. DUT1,DUT2: Set indirect data: - `config-status --data_ind ` -7. DUT1: Send payload: - `data --dst_addr 01:02:03:00:00:00:00:02 --msdu_length --msdu ` -8. DUT2: wait for transmission to finish: - `wait --timeout 500` -9. DUT2: send data : - `data --dst_addr 01:02:03:00:00:00:00:01 --msdu_length --msdu ` -10. DUT1: wait for transmission to finish: - `wait --timeout 500` -11. DUT1,DUT2: Take turns waiting and transmitting: - `data` - `wait` - -Test case repeats step 11 25 times for both devices. - -**Expected result:** - -Data send commands succeed. - -The test exits with status `PASS` without timeouts. diff --git a/TEST_APPS/testcases/nanostack_mac_tester/__init__.py b/TEST_APPS/testcases/nanostack_mac_tester/__init__.py deleted file mode 100644 index 7473ca9ad43..00000000000 --- a/TEST_APPS/testcases/nanostack_mac_tester/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python -""" -Copyright (c) 2020 Arm Limited -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" diff --git a/TEST_APPS/testcases/nanostack_mac_tester/address_read_and_write.py b/TEST_APPS/testcases/nanostack_mac_tester/address_read_and_write.py deleted file mode 100644 index 8467fb985d1..00000000000 --- a/TEST_APPS/testcases/nanostack_mac_tester/address_read_and_write.py +++ /dev/null @@ -1,82 +0,0 @@ -""" -Copyright (c) 2017, Arm Limited and affiliates. -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -import os,sys -from icetea_lib.bench import Bench -from icetea_lib.TestStepError import TestStepFail - -class Testcase(Bench): - def __init__(self): - Bench.__init__(self, name = "address_read_and_write", - title = "MAC address and PAN id read/write test", - status = "released", - type = "smoke", - subtype = "", - execution = { - "skip": { - "value": False, - "reason": "" - } - }, - author = "Valtteri Erkkila", - purpose = "Tests reading a MAC address from the driver, and writing to the modifiable MAC address", - feature = ["MLME-SET"], - component = ["MAC"], - requirements = { - "duts": { - '*': { - "count":1, - "type": "hardware", - "allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW41Z"], - "application": { - "name": "TEST_APPS-device-nanostack_mac_tester" - } - }, - "1":{"nick": "First"} - }} - ) - - def setUp(self): - pass - - def do_test_iteration(self): - self.command("First", "mlme-reset") - self.command("First", "addr") - self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01") - self.command("First", "addr --16-bit 0xABCD") - # Set MAC PAN ID - self.command("First", "mlme-set --attr 0x50 --value_bytes CD:CD --value_size 2") - self.command("First", "addr") - self.verify_trace(1, "MAC64: 01:02:03:00:00:00:00:01") - - def case(self): - # Try tests few times because of potential RF failures - loop = 0 - while loop < 5: - try: - self.do_test_iteration() - break - except TestStepFail: - self.logger.info("Warning, iteration failed #" + str(loop+1)) - loop = loop + 1 - self.delay(5) - else: - raise TestStepFail("Too many failed iterations!") - - def tearDown(self): - self.reset_dut() - diff --git a/TEST_APPS/testcases/nanostack_mac_tester/create_and_join_PAN.py b/TEST_APPS/testcases/nanostack_mac_tester/create_and_join_PAN.py deleted file mode 100644 index 7dd0def7626..00000000000 --- a/TEST_APPS/testcases/nanostack_mac_tester/create_and_join_PAN.py +++ /dev/null @@ -1,107 +0,0 @@ -""" -Copyright (c) 2017, Arm Limited and affiliates. -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -import os,sys -from icetea_lib.bench import Bench -from icetea_lib.TestStepError import TestStepFail - -class Testcase(Bench): - def __init__(self): - Bench.__init__(self, name = "create_and_join_PAN", - title = "Create a PAN and have a device join it", - status = "released", - type = "smoke", - subtype = "", - execution = { - "skip": { - "value": False, - "reason": "" - } - }, - author = "Valtteri Erkkila", - purpose = "", - feature = ["MLME-START", "MLME-SCAN (active)"], - component = ["MAC"], - requirements = { - "duts": { - '*': { - "count":3, - "type": "hardware", - "allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW41Z"], - "application": { - "name": "TEST_APPS-device-nanostack_mac_tester" - } - }, - "1":{"nick": "First"}, - "2":{"nick": "Second"}, - "3":{"nick": "Third"} - }} - ) - - def mask_from_channel_list(self, channels): - res = 0 - for ch in channels: - res = res | ( 1 << ch) - return hex(res) - - def setUp(self): - self.channel = 11 - - def do_test_iteration(self): - self.command("First", "mlme-reset") - self.command("Second", "mlme-reset") - self.command("Third", "mlme-reset") - - # Beacon payload - self.command("First", "mlme-set --attr 0x45 --value_ascii mac-tester --value_size 10") - # Beacon payload length - self.command("First", "mlme-set --attr 0x46 --value_uint8 10 --value_size 1") - - self.command("Second", "mlme-set --attr 0x45 --value_ascii second-mac-tester --value_size 17") - self.command("Second", "mlme-set --attr 0x46 --value_uint8 17 --value_size 1") - - # Start PAN coordinator - self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel)) - self.command("Second", "start --pan_coordinator true --logical_channel {}".format(int(self.channel)+1)) - self.delay(3) - if self.channel == 11: - channels = [11,12] - elif self.channel == 26: - channels = [25,26] - else: - channels = [self.channel, self.channel+1] - self.command("Third", "scan --channel_mask {}".format(self.mask_from_channel_list(channels))) - self.delay(0.2) - self.command("Third", "find-beacon --data mac-tester") - self.command("Third", "find-beacon --data second-mac-tester") - - def case(self): - # Try tests few times because of potential RF failures - loop = 0 - while loop < 5: - try: - self.do_test_iteration() - break - except TestStepFail: - self.logger.info("Warning, iteration failed #" + str(loop+1)) - loop = loop + 1 - self.delay(5) - else: - raise TestStepFail("Too many failed iterations!") - - def tearDown(self): - self.reset_dut() diff --git a/TEST_APPS/testcases/nanostack_mac_tester/send_data.py b/TEST_APPS/testcases/nanostack_mac_tester/send_data.py deleted file mode 100644 index 95e5fea5020..00000000000 --- a/TEST_APPS/testcases/nanostack_mac_tester/send_data.py +++ /dev/null @@ -1,89 +0,0 @@ -""" -Copyright (c) 2017, Arm Limited and affiliates. -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -import os,sys -from icetea_lib.bench import Bench -from icetea_lib.TestStepError import TestStepFail - -class Testcase(Bench): - def __init__(self): - Bench.__init__(self, name = "send_data", - title = "Simple data transmission test", - status = "released", - type = "smoke", - subtype = "", - execution = { - "skip": { - "value": False, - "reason": "" - } - }, - author = "Valtteri Erkkila", - purpose = "Tests that sending data works", - feature = ["MCPS-DATA"], - component = ["MAC"], - requirements = { - "duts": { - '*': { - "count":2, - "type": "hardware", - "allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW41Z"], - "application": { - "name": "TEST_APPS-device-nanostack_mac_tester" - } - }, - "1":{"nick": "First"}, - "2":{"nick": "Second"} - }} - ) - - def setUp(self): - self.channel = 11 - - def do_test_iteration(self): - self.command("First", "mlme-reset") - self.command("Second", "mlme-reset") - - self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01") - self.command("Second", "addr --64-bit 01:02:03:00:00:00:00:02") - - # Start PAN coordinator - self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel)) - # Start PAN beacon - self.command("Second", "start --pan_coordinator false --logical_channel {}".format(self.channel)) - - # Send data - self.command("First", "data --dst_addr 01:02:03:00:00:00:00:02 --msdu_length 5 --msdu abcde") - self.command("Second", "data --dst_addr 01:02:03:00:00:00:00:01 --msdu_length 5 --msdu 12345") - - def case(self): - # Try tests few times because of potential RF failures - loop = 0 - while loop < 5: - try: - self.do_test_iteration() - break - except TestStepFail: - self.logger.info("Warning, iteration failed #" + str(loop+1)) - loop = loop + 1 - self.delay(5) - else: - raise TestStepFail("Too many failed iterations!") - - def tearDown(self): - self.reset_dut() - diff --git a/TEST_APPS/testcases/nanostack_mac_tester/send_data_indirect.py b/TEST_APPS/testcases/nanostack_mac_tester/send_data_indirect.py deleted file mode 100644 index f884818a98b..00000000000 --- a/TEST_APPS/testcases/nanostack_mac_tester/send_data_indirect.py +++ /dev/null @@ -1,134 +0,0 @@ -""" -Copyright (c) 2017, Arm Limited and affiliates. -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -import os,sys -from icetea_lib.bench import Bench -from icetea_lib.TestStepError import TestStepFail - -class Testcase(Bench): - def __init__(self): - Bench.__init__(self, name = "send_data_indirect", - title = "Indirect data transmission test", - status = "released", - type = "smoke", - subtype = "", - execution = { - "skip": { - "value": False, - "reason": "" - } - }, - author = "Valtteri Erkkila", - purpose = "Tests sending data indirectly, i.e polling the coordinator for data", - feature = ["MCPS-DATA", "MLME-POLL"], - component = ["MAC"], - requirements = { - "duts": { - '*': { - "count":3, - "type": "hardware", - "allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW41Z"], - "application": { - "name": "TEST_APPS-device-nanostack_mac_tester" - } - }, - "1":{"nick": "First"}, - "2":{"nick": "Second"}, - "3":{"nick": "Third"} - }} - ) - - def setUp(self): - self.channel = 11 - - def do_test_iteration(self): - self.channel = 11 - self.command("First", "mlme-reset") - self.command("Second", "mlme-reset") - self.command("Third", "mlme-reset") - - self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01") - self.command("Second", "addr --64-bit 01:02:03:00:00:00:00:02") - self.command("Third", "addr --64-bit 01:02:03:00:00:00:00:03") - - # Start PAN coordinator - self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel)) - # Start PAN beacon - self.command("Second", "start --pan_coordinator false --logical_channel {}".format(self.channel)) - self.command("Third", "start --pan_coordinator false --logical_channel {}".format(self.channel)) - - # Set MAC RX on-while-idle off - self.command("Second", "mlme-set --attr 0x52 --value_uint8 0 --value_size 1") - self.command("Third", "mlme-set --attr 0x52 --value_uint8 0 --value_size 1") - - # Add neighbours - self.command("First", "add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:02 --pan_id 0x1234 --index 0") - self.command("First", "add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:03 --pan_id 0x1234 --index 1") - self.command("Second", "add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:01 --pan_id 0x1234 --index 0") - self.command("Third", "add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:01 --pan_id 0x1234 --index 0") - - # Configure indirect data - self.command("Second", "config-status --data_ind abcde") - self.command("Third", "config-status --data_ind 12345") - - # Runs into timing issues if extensive printing is enabled - self.command("*", "silent-mode on") - - # Send data indirectly to DUT2 - self.command("First", "data --dst_addr 01:02:03:00:00:00:00:02 --msdu_length 5 --msdu abcde --indirect_tx true --wait_for_confirm false") - # Poll DUT1 for data - self.command("Second", "poll --coord_address 01:02:03:00:00:00:00:01") - - # Send more data - self.command("First", "data") - self.command("First", "data") - # Poll more data - self.command("Second", "poll") - self.command("Second", "poll") - # Set expected poll return status to 0xEB(no data after poll) - self.command("Second", "config-status --poll 235") - # No data should remain to be polled for - self.command("Second", "poll") - - # Set expected poll return status to 0xEB(no data after poll) - self.command("Second", "config-status --poll 235") - # Send data to DUT3 - self.command("First", "data --dst_addr 01:02:03:00:00:00:00:03 --msdu 12345") - # Poll(expected failure) - self.command("Second", "poll") - # Poll DUT1 for data(expected success) - self.command("Third", "poll --coord_address 01:02:03:00:00:00:00:01") - self.command("*", "silent-mode off") - - def case(self): - # Try tests few times because of potential RF failures - loop = 0 - while loop < 5: - try: - self.do_test_iteration() - break - except TestStepFail: - self.logger.info("Warning, iteration failed #" + str(loop+1)) - loop = loop + 1 - self.delay(5) - else: - raise TestStepFail("Too many failed iterations!") - - def tearDown(self): - self.command("*", "silent-mode off") - self.reset_dut() - diff --git a/TEST_APPS/testcases/nanostack_mac_tester/send_large_payloads.py b/TEST_APPS/testcases/nanostack_mac_tester/send_large_payloads.py deleted file mode 100644 index 74427caf3ee..00000000000 --- a/TEST_APPS/testcases/nanostack_mac_tester/send_large_payloads.py +++ /dev/null @@ -1,107 +0,0 @@ -""" -Copyright (c) 2017, Arm Limited and affiliates. -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -import os,sys -from icetea_lib.bench import Bench -from icetea_lib.TestStepError import TestStepFail - -class Testcase(Bench): - def __init__(self): - Bench.__init__(self, name = "send_large_payloads", - title = "Data transmission test with large packets", - status = "released", - type = "reliability", - subtype = "", - execution = { - "skip": { - "value": False, - "reason": "" - } - }, - author = "Valtteri Erkkila", - purpose = "Repeatedly sends long packets, checking that the payload is correct in each one", - feature = ["MCPS-DATA"], - component = ["MAC"], - requirements = { - "duts": { - '*': { - "count":2, - "type": "hardware", - "allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW41Z"], - "application": { - "name": "TEST_APPS-device-nanostack_mac_tester" - } - }, - "1":{"nick": "First"}, - "2":{"nick": "Second"} - }} - ) - - def setUp(self): - self.channel = 11 - - def do_test_iteration(self): - self.command("First", "mlme-reset") - self.command("Second", "mlme-reset") - - self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01") - self.command("Second", "addr --64-bit 01:02:03:00:00:00:00:02") - - #104 characters, headers are 2+1+2+8+8+2=23 bytes, resulting in a packet size of 127 (max) - large_payload = "0123456789abcdefghjiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZZZZZZZZZ0123456789012345678901234567891234" - # Start PAN coordinator - self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel)) - # Start PAN beacon - self.command("Second", "start --pan_coordinator false --logical_channel {}".format(self.channel)) - - # Set indirect data - self.command("First", "config-status --data_ind {}".format(large_payload)) - self.command("Second", "config-status --data_ind {}".format(large_payload)) - - # Send data to DUT2 - self.command("First", "data --dst_addr 01:02:03:00:00:00:00:02 --msdu_length {} --msdu {}".format(len(large_payload), large_payload)) - # Wait for transmission to finish - self.command("Second", "wait --timeout 500") - - # Send data to DUT1 - self.command("Second", "data --dst_addr 01:02:03:00:00:00:00:01 --msdu_length {} --msdu {}".format(len(large_payload), large_payload)) - # Wait for transmission to finish - self.command("First", "wait --timeout 500") - # Loop with previous settings - for i in range(0, 25): - self.command("First", "data") - self.command("Second", "wait") - self.command("Second", "data") - self.command("First", "wait") - - def case(self): - # Try tests few times because of potential RF failures - loop = 0 - while loop < 5: - try: - self.do_test_iteration() - break - except TestStepFail: - self.logger.info("Warning, iteration failed #" + str(loop+1)) - loop = loop + 1 - self.delay(5) - else: - raise TestStepFail("Too many failed iterations!") - - def tearDown(self): - self.reset_dut() - diff --git a/TEST_APPS/testcases/nanostack_mac_tester/template b/TEST_APPS/testcases/nanostack_mac_tester/template deleted file mode 100644 index 4335851efd0..00000000000 --- a/TEST_APPS/testcases/nanostack_mac_tester/template +++ /dev/null @@ -1,65 +0,0 @@ -""" -Copyright (c) 2017, Arm Limited and affiliates. -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" -import os,sys -# ensure that test/ directory is first choice for imports -test_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) -if not test_dir in sys.path: - sys.path.insert(0, test_dir) -from GenericTestcase import Bench -from Error import TestStepFail - -class Testcase(Bench): - def __init__(self): - Bench.__init__(self, name = "template", # Name should be the same as the filename - title = "TITLE", - status = "development", - type = "TYPE", - subtype = "", - execution = { - "skip": { - "value": False, - "reason": "" - } - }, - author = "Valtteri Erkkila", - purpose = "", - feature = [""], - component = ["MAC"], - requirements = { - "duts": { - '*': { - "count":2, # Count must reflect the amount of specified devices below - "type": "hardware", - "application":{ "name":"generalTestApplication", "version": "1.0"}, - "rf_channel": 11 - }, - "1":{"nick": "First"}, - "2":{"nick": "Second"} - }} - ) - - def setUp(self): - pass - - def case(self): - pass - - def tearDown(self): - pass - -if __name__=='__main__': - sys.exit( Testcase().run() ) diff --git a/TEST_APPS/testcases/nfc/README.md b/TEST_APPS/testcases/nfc/README.md deleted file mode 100644 index 6d9082e9700..00000000000 --- a/TEST_APPS/testcases/nfc/README.md +++ /dev/null @@ -1,336 +0,0 @@ -# NFC tests. - -A CI test suite for NFC component. These tests validate card mbed emulation cases. The key use case is an NFC smart poster supporting commissioning workflow. -The SUT (system under test) is the NFC target. Tests exercise the framework and NDEF transactions when a NFC controller driver is used, or when the stack is configured for an NFC EEPROM chip in the system integration. - -This project is called CreamScone, which is an ice tea framework based cli-driven python test. - - - -- [NFC tests.](#nfc-tests) -- [Overview](#overview) -- [System Test high level requirement](#system-test-high-level-requirement) -- [Low level design](#low-level-design) -- [User Guide](#user-guide) - - [Test cases](#test-cases) - - [cli commands](#cli-commands) - - [How to](#how-to) - - [Running the tests](#running-the-tests) -- [Alternate NFC drivers note:](#alternate-nfc-drivers-note) -- [Known issues](#known-issues) - - - -# Overview -A set of tests run in CI, which can provide: -- Internal confidence -- Faster iterations -- More efficient work -- Clear escalation path - -A [Ice-tea](https://github.com/ARMmbed/mbed-os-5-docs/blob/development/docs/tools/testing/testing_icetea.md) based test suite. In it's simplest form, the suite merely drives API's for the NFC tag reader/writer, and validates a tag simulation running on an idle target, allows test cases in discovery, connection and read/write NDEF records. - -In order to mitigate the costs associated with system testing, use existing frameworks or parts and make it easy to test each individually. The [nfcpy](https://nfcpy.readthedocs.io/) Python library is used as the core of the *CreamScone* component which uses a PN53* device [SCL3711 usb reader](https://www.identiv.com/products/smart-card-readers/rfid-nfc-contactless/scl3711/) over USB to read the mbed simulated tag. This library is used to drive host interactions because it is portable (windows/GNULinux.) Remote NFC interactions will raise events in the mbed application. Connection and read/write events which get handled in user application on the target get wired up to asynchronously return responses and the data values (NDEF messages) to the ice tea framework. These events and data are thus tested/checked in the code (python) running on host. The target test app wraps the API, allowing many new test-scenarios to be written purely in Python. - -**NFC compliance** - -This suite only assists in NFC forum compliance. Developers must self certify using test tools from a provider to uncover early issues and get an external test vendor to achieve certification. - -**Mobiles and inter-op** - -Not in scope. Test procedures using a mobile phone app for Android and for IOS were not in scope for this test suite. - -![Basic Overview](img/simple-overview.png) - -Because the commissioning workflow application quality is the end goal, the NFC suite includes learnings to design the CI setup needed for future system testing that bring a mobile phone into the test-rig. The use of a mobile and bluetooth pairing as well as the continuous integration system is not included. - - - -# System Test high level requirement -Mitigate risks identified, to the product from an internal view to supporting releases. Help customers develop a driver or a design, and reduce their production risks. In summary: -- Architecture risks and Api breaks -- Partner cannot NFC forum Certify -- Partner driver has bugs -- Code regressions in O/S -- Arm mbed provided driver or HAL has bugs -- Security vulnerabilities - -In short, “Empower engineers to efficiently ship quality code with confidence.” - -**Design requirements: ** -- Identify and use tools to allow running in CI system, on many targets/configurations -- Be portable (can run in the CI system) using NFC explorer boards in lab for correctly co-located targets. -- Be able to set up and run locally in development - -# Low level design -**Components** - -API standalone Self tests [test_self.py](TEST_APPS\testcases\nfc\test_self.py) - -API E2E (wireless) tests [test_nfc.py](TEST_APPS\testcases\nfc\test_nfc.py) - -An [icetea](https://github.com/ARMmbed/icetea/blob/master/README.md) framework test program. Commandline (serial port) driven [target app](TEST_APPS\devices\nfcapp\main.cpp) aka _'CreamScone'_ which allows manual interactions with the driver. The app will send all API return data over serial link. - -An icetea plugin [nfc_test_parsers.py](TEST_APPS\icetea_plugins\nfc_test_parsers.py) which parses API responses over the serial port into python variables. - -MbedOS cli test app [main.cpp](TEST_APPS\device\nfcapp\main.cpp). The CLI commands return results asynchronously for most commands which get passed to and handled on a driver thread. - -**Future: ** A complete inter-op ready design intended to include a switch-box to allow the reader to connect to NFC enabled targets nearby using flying cables and a sticky-back antenna. The switch should allow selecting either alternative tags, or NFC peers, and provide inter-operability coverage. The switch-box may be controlled using GPIO either driven from spare IO pins on the target DUT itself (preferred option), or perhaps from a Raspberry pi. - -![inter-op](img/inter-op-view.png) - -![future](img/creamscone-mobile.png) - - -** Reference: ** - -[ARMmbed NFC design](https://github.com/ARMmbed/mbed-os/blob/master/docs/design-documents/nfc/nfc_design.md) - -[ARMmbed NFC code](https://github.com/ARMmbed/mbed-os/tree/master/features/nfc/nfc) - -[ARMmbed NFC example application](https://github.com/ARMmbed/mbed-os-example-nfc/) - -[Python NFC library](https://nfcpy.readthedocs.io/en/latest/topics/get-started.html) - -[NFC forum](https://nfc-forum.org/) - -# User Guide -This section covers the test case specification and how to run the test suite. - -The SUT target is rebooted between tests, since tests modify the target hardware state. - -## Test cases -CLI commands used by each test case describe the steps in a test. -** Basic local only cases ** -- test_nfc_error_codes : inintnfc , setlastnfcerror \ , getlastnfcerror - - Verify that the test CLI engine can initialize the stack, and can return NFC codes -- test_nfc_eeprom : iseeprom - - prints "true" if the target has an EEPROM configured stack, else prints "false" diagnostic only -- test_nfc_get_controller_protocols - - set nfc protocols supported -- test_nfc_set_controller_protocols - - get nfc protocols supported -- test_nfc_setsmartposter : setsmartposter \<-u> \ - - Sets a smartposter message, does not verify over wireless! (Only https protocol tested.) -- test_nfc_erase : initnfc, erase, readmessage - - Erase entire EEPROM, (behaviour for controller stack is null) -- test_nfc_write_long : initnfc, erase, writelong \, readmessage - - Write a very large text T record, and verify expected length written -- test_nfc_reprogrammed : iseeprom, initnfc, erase, wirelessly reprogram, wirelessly verify - - Use a reader/writer to program the tag using the default M24SR chip password -** End-to-End cases ** -- test_nfce2e_target_found - - tag can actually be detected wireless -test_nfce2e_type4_found - - correct tag detected -- test_nfce2e_discovery_loop - - Start or Stop discovery loop or disable depending on stack -test_nfce2e_read_stress - - read large message from device -test_nfce2e_reprogrammed - - modify large message from device -test_nfce2e_reprogrammed_stress - - write moderate message wirelessly -test_nfce2e_smartposter - - as with the basic test, but wirelessly - -** unimplemented due to limited support ** -- test_nfc_iso7816_supported -- test_nfc_add_iso7816_application -- test_nfc_set_tagtype -- test_nfc_get_tagtype - - -## cli commands -cli commands take parameters, its possible to type help at the cli for a list of commands. -``` -mbed sterm --baudrate 115200 -help -... -getlastnfcerror last NFC error code -setlastnfcerror self-test -initnfc init NFC driver -setsmartposter send smartposter NDEF -iseeprom NFC configEEPROM present -readmessage read EEPROM else return last message -erase erase EEPROM or clear last message -writelong fill entire FILE with pattern -... -``` -Note: Most commands also return a NFC status value (type "getlastnfcerror help" in console) which allow us to build negative test cases. -Note: Some commands only apply to NFC controllers, these commands fail with the appropriate not-supported code NFC_ERR_UNSUPPORTED and additionally return -2 error code to ice-tea. Commands like the erase command is a no-op on a NFC Controller target in the test app, for test-writting convenience. - - -**unimplemented CLI commands** -commands that were not implemented in the test app -- set/get tag type -- get/set iso7816 app - -**Excluded** -- power consumption -- throughput -- memory consumption - -## How to -**Wirring diagram for NFC Explorer with PN512** - -If using the Raspbery Pi explorer (PN512) board, use this pinout mapping diagram to connect the shield to the reference target. In this case a ST NucleoF401RE pinout is shown. -``` - Nucleo F401RE Explore NFC - (Arduino header) (pin1 on shield shown with a <|) - +-------+ +-------+ +--------+ - | [NC] | | [B8] | |[ 2][ 1]| - | [IOREF| | [B9] | |[ 4][ 3]| - | [RST] | | [AVDD]| |[ 6][ 5]| -1<---+ [3V3] | | [GND] | |[ 8][ 7]| - | [5V] | | [A5] +--->23 |[10][ 9]| - | [GND] | | [A6] +--->21 |[12][11]| -25<--+ [GND] | | [A7] +--->19 |[14][13]| - | [VIN] | | [B6] +--->3 |[16][15]| - | | | [C7] | |[18][17]| -26<--+ [A0] | | [A9] | |[20][19]| -16<--+ [A1] | | [A9] | |[22][21]| - | ... | | | |[24][23]| - | | | [A8] | |[26][25]| - +-------+ | ... | +--------+ - | | - | | - +-------+ - -Patch using jumper wires to the -indicated pins on the Shield. - -``` -Schematic (https://www.element14.com/community/docs/DOC-76384/l/explore-nfc-board-schematic) -To change pinouts, if your reference design or shield pins differ for the PN512 controller driver, open nfcProcessCtrl.cpp and find the code -```json -NFCProcessController::NFCProcessController(events::EventQueue &queue) : - // pins: mosi, miso, sclk, ssel, irq, rst - _pn512_transport(D11, D12, D13, D10, A1, A0), _pn512_driver( - &_pn512_transport), _queue(queue), _nfc_controller( - &_pn512_driver, &queue, _ndef_buffer) { -} -``` -modify pins as needed. - -**Compilation target drivers** - -If using the EEPROM driver, the mbed_app.json will contain -```json - "target_overrides": { - "DISCO_L475VG_IOT01A": { - "target.extra_labels_add": ["M24SR"] - } - } -... -``` -If using the Explorer Shield or PN512 driver mbed_app.json will add -```json - "target_overrides": { - "NUCLEO_F401RE": { - "target.extra_labels_add": ["PN512"] - } - } -... -``` - -## Running the tests -1. Wire an [explorer shield](https://cpc.farnell.com/nxp/explore-nfc/add-on-board-nfc-for-raspberry/dp/SC13404) up to and compile the target application. -2. Flash the binary to target and verify that it responds with an _`action NDEF record http://www.mbed.com`_ by using a mobile phone to scan over the antenna. -3. Install python (2.7) and install the nfcpy library, [see](https://nfcpy.readthedocs.io/en/latest/topics/get-started.html) . NFC reader can be connected to a serial port, or more commonly a USB dongle. Verify the dongle is functioning. -4. Place the scanner near the explorer shield. Run various test program commands like so: -- python ice_device -command describe - -**run the suite** -In a working folder, run - -`git clone https://github.com/ARMmbed/mbed-os.git` - - -If using the EEPROM driver, ( ST Discovery and the M24SR driver), you need the driver: -`git clone https://github.com/ARMmbed/mbed-nfc-m24sr.git' - - -And copy the files into your mbed root: -`xcopy ..\mbed-nfc-m24sr\*.* .\eeprom_driver\' - -To run the End2End tests, type: -`mbed test --icetea --app-config .\TEST_APPS\device\nfcapp\mbed_app.json -n test_nfce2e` - -To run only the standalone (readerless tests if you do not have a card reader), type: -`mbed test --icetea --app-config .\TEST_APPS\device\nfcapp\mbed_app.json -n test_nfc_eeprom,test_nfc_error_codes,test_nfc_setsmartposter,test_nfc_erase,test_nfc_write_long` - -# Alternate NFC drivers note: - -Please see the example json file .\TEST_APPS\testcases\nfc\mbed_app.json . The test does not check that you have any needed shield installed, so if it "hangs" at the point the "initnfc" command is used, the driver or shield may be the fault. The test assumes that MBED_CONF_NFCEEPROM is set to 1, if not it assumes that a NFC Controller driver is in use. To test drivers other than PN512 and M24SR, it is required to make test code changes that reference the driver. The driver can be instantiated once only. - -If the new driver you add is for Eeprom, open nfccommands.cpp and find the code and modify line as shown +++ -```C++ -NFCTestShim* new_testshim() { -#if MBED_CONF_NFCEEPROM ---- mbed::nfc::NFCEEPROMDriver& eeprom_driver = get_eeprom_driver(nfcQueue); - -+++ mbed::nfc::NFCEEPROMDriver& eeprom_driver = get_myeeprom_driver(nfcQueue); - - return ( (NFCTestShim *)(new NFCProcessEEPROM(nfcQueue, eeprom_driver)) ); -#else - return ((NFCTestShim *) (new NFCProcessController(nfcQueue))); -#endif // EEPROM -``` - -If the driver you add is a Controller driver, open nfcProcessCtrl.cpp and find the code -```C++ -NFCProcessController::NFCProcessController(events::EventQueue &queue) : - // pins: mosi, miso, sclk, ssel, irq, rst - _pn512_transport(D11, D12, D13, D10, A1, A0), _pn512_driver( - &_pn512_transport), _queue(queue), _nfc_controller( - &_pn512_driver, &queue, _ndef_buffer) { -} -``` -1. You will want to replace this and reference the desired controller driver. Likewise, this code is where pinout changes have to be made if using the supplied Controller driver. -2. Search for occurrences of guard macros `#ifdef TARGET_PN512` , and `#endif`. Add a new guard macro and code for your specific controller driver at the same point. - - -Note: If the target uses an EEPROM, it need not be powered/running, to be read, mbedOS is not running at that point. - -**Device API error codes** - -You can issue the command "getlastnfcerror help" to see a list of error codes that are returned by most commands. -```C++ -#define NFC_OK 0 ///< No error -#define NFC_ERR_UNKNOWN 1 ///< Unknown error -#define NFC_ERR_LENGTH 2 ///< Length of parameter is wrong -#define NFC_ERR_NOT_FOUND 3 ///< Could not find item -#define NFC_ERR_UNSUPPORTED 4 ///< This action is not supported -#define NFC_ERR_PARAMS 5 ///< These parameters are not correct -#define NFC_ERR_BUFFER_TOO_SMALL 6 ///< The buffer is too small to store all data (buffer overflow) -#define NFC_ERR_TIMEOUT 7 ///< Timeout -#define NFC_ERR_CRC 8 ///< Checksum does not match -#define NFC_ERR_NOPEER 9 ///< No target/initiator in vicinity -#define NFC_ERR_PARITY 10 ///< Parity error -#define NFC_ERR_FIELD 11 ///< No RF field detected (or RF field lost) -#define NFC_ERR_COLLISION 12 ///< Collision detected -#define NFC_ERR_WRONG_COMM 13 ///< Communication error -#define NFC_ERR_PROTOCOL 14 ///< Protocol is not conformant -#define NFC_ERR_BUSY 15 ///< Resource is busy -#define NFC_ERR_CONTROLLER 16 ///< Controller failure -#define NFC_ERR_HALTED 17 ///< Target has been halted -#define NFC_ERR_MAC 18 ///< MAC does not match -#define NFC_ERR_UNDERFLOW 19 ///< Could not send data in time -#define NFC_ERR_DISCONNECTED 20 ///< Link has disconnected -#define NFC_ERR_ABORTED 21 ///< Command was aborted -``` -# Known issues - -1. The test app defines large buffer to store the maximum realistic message of 8K by default. For targets with limited memory (< ~32K) will need to modify the app config. Open mbed_app.config and modify the setting -` "TEST_NDEF_MSG_MAX" : 8192` to suit by overriding it on specific targets. The test cases (python code) which stress read/write will need updates if the buffer is reduced to 2K by editing test_nfc.py and modifying the line(s) to fall within the new macro value. -```python - # Values > 4 k incur large time costs - STRESS_BUFFLEN = 2050 -``` - -2. The test app and the supplied drivers only support Type4 tags. The test app thus does not exercise the different protocols and always sets iso-dep level functionality (Type4) for NFC Controller initialization. - -1. Test test_nfce2e_discovery_loop fails on NFC controller. The NFC controller driver discovery loop cannot be stopped manually. No major functionality is lost, it only prevents a complete disable of NFC at runtime. A bug ticket #IOTPAN-313 was logged to fix the stop function. The Controller still restarts discovery loop normally under app control after a peer disconnects. - -1. The smartposter NDEF record wrapper class `smartposter.h` is also provided as part of the NFC examples. The examples are not needed to compile the test app, but this example class may be useful to customers. This file may thus move into the NFC component in future. diff --git a/TEST_APPS/testcases/nfc/__init__.py b/TEST_APPS/testcases/nfc/__init__.py deleted file mode 100644 index b09b705cde2..00000000000 --- a/TEST_APPS/testcases/nfc/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -Copyright (c) 2020 Arm Limited -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" diff --git a/TEST_APPS/testcases/nfc/img/creamscone-mobile.png b/TEST_APPS/testcases/nfc/img/creamscone-mobile.png deleted file mode 100644 index 114a622099f..00000000000 Binary files a/TEST_APPS/testcases/nfc/img/creamscone-mobile.png and /dev/null differ diff --git a/TEST_APPS/testcases/nfc/img/inter-op-view.png b/TEST_APPS/testcases/nfc/img/inter-op-view.png deleted file mode 100644 index 5bf98715bb9..00000000000 Binary files a/TEST_APPS/testcases/nfc/img/inter-op-view.png and /dev/null differ diff --git a/TEST_APPS/testcases/nfc/img/simple-overview.png b/TEST_APPS/testcases/nfc/img/simple-overview.png deleted file mode 100644 index 3c02dd9f86d..00000000000 Binary files a/TEST_APPS/testcases/nfc/img/simple-overview.png and /dev/null differ diff --git a/TEST_APPS/testcases/nfc/mobileapi.md b/TEST_APPS/testcases/nfc/mobileapi.md deleted file mode 100644 index 46c9e592621..00000000000 --- a/TEST_APPS/testcases/nfc/mobileapi.md +++ /dev/null @@ -1,94 +0,0 @@ -# NFC test SDK comparison - -A comparison of the SDKs exposed to manage NFC tags on Android IOs and Python module PyNFC. - - - -- [NFC test SDK comparison](#nfc-test-sdk-comparison) -- [Overview](#overview) -- [Comparison](#comparison) - - [IOS (objective C)](#ios-objective-c) - - [Android (Java)](#android-java) - - [pynfc (python)](#pynfc-python) -- [Observe](#observe) - - - -# Overview -A comparison which analyses NFC use cases on mobile, as background to the test case design/implementation in the commissioning workflow :NFC-Bluetooth-pairing application. -- Analyse the [Apple API](https://developer.apple.com/documentation/corenfc) -- Analyse the [Android API](https://developer.android.com/guide/topics/connectivity/nfc/advanced-nfc#java) -- Python test [pynfc modules](https://nfcpy.readthedocs.io/en/latest/modules/index.html) - - -# Comparison -From the lowest level, each programmer interface has a definition for Errors, Link, NDEF, Tags and Sessions. -Note: Comparisons are high level and use past experience and old docs. - - -## IOS (objective C) -1. Errors: - are a struct with 3 members:
- int:value,
struct:string:usererror
struct:string:localized -1. isodep: - - not supported -1. NDEF support parameters with - - payload
and Typename, -4. Tags: - - Are an Object representing tag -5. Sessions are managed using - - Delegate &callbacks - -## Android (Java) -1. Errors: - - thrown as IOException with cause and message, there are no returned error datas -2. isodep: - - get/set communication parameters and RAW. -3. NDEF: - - Includes SNEP -4. Tags : - - (3)A,(3)B,(4)F,V and isoDep layer -5. Sessions - - Intents and Actions, runtime registration of PendingIntent() allows hooking using tag filters - -## pynfc (python) -1. Errors : - - raises Exceptions nfc.clf.Error and others per class -2. isodep: - - get/set communication parameters and RAW. -3. NDEF: - - full implementation and types. Includes SNEP -4. Tags : - - 1,2,(3)A,(3)B,(4)F isoDep layer -5. Sessions : - - using delegate class callbacks - -# Observe -Negative test cases would be better designed around the user cases, than around the implementations, base error conditions at the API layer look more like -- UnsupportedTarget -- Communication -- Protocol -- (w) Transmission -- (w) Timeout -- (w) BrokenLink -- ValueError - -Valuable test data cases shall be for valid and boundary cases for the smartposter NDEF record: -- uri – URI string ASCII only -- title – Smart poster title(s), (additional internationalizations with IANA codes not tested) -- icons – omitted -- action – The recommended action , a string diff --git a/TEST_APPS/testcases/nfc/nfc_clf_wrapper.py b/TEST_APPS/testcases/nfc/nfc_clf_wrapper.py deleted file mode 100644 index 8a47dbfca19..00000000000 --- a/TEST_APPS/testcases/nfc/nfc_clf_wrapper.py +++ /dev/null @@ -1,98 +0,0 @@ -""" -Copyright (c) 2017, Arm Limited and affiliates. -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -import time -import nfc -from nfc.clf import RemoteTarget -import logging - -""" - Wrap calls to nfcpi testing module, handle loading the driver -""" - - - -def debug_nfc_data(key, value): - """ - print useful data values for the host/user {{in between}} easy to spot brackets. - """ - text = "{{%s=%s}}" % (key, value) - logger.info(text) - - -logger = logging.getLogger() - - -class NfcWrapper: - """ - Finds the NFC reader USB front-end and prepares it for use. - """ - def __init__(self): - # will need a parameter here to help with libusb detection? - # clf.open("usb:04e6:5591") will open the SCL3711-NFC - logger.info("Initializing the NFC tag reader...") - self.clf = nfc.ContactlessFrontend() - if (self.clf.open("usb") ): # the NFC reader was not detected on any USB port! - logger.info("NFC Frontend found OK") - else: - logger.error("The NFC reader was not detected on any USB port!") - self.clfResponse = None - - def connect(self): - # note: only supporting type4 - time.sleep(0.5) - after5s = lambda: time.time() - started > 5 - started = time.time() - - tag = self.clf.connect( rdwr={'on-connect': lambda tag: False}, - terminate = after5s) - if tag: # None if timeout expires - logging.info("NFCReader: connected " + str(tag)) - else: - logging.info("NFCReader: warning, no tag detected ") - return tag - - def mute(self): - """turn off the reader radio""" - if (self.clf.device is not None): - logging.info("NFCReader: radio mute" + self.clf.device.product_name) - self.clf.device.mute() - else: - logging.warning("NFCReader: reader not initialized!") - - def disconnect(self): - logging.info("NFCReader: close frontend.") - self.clf.close() - -""" -Handle interactions with the NFC reader, and singleton -""" -class ContactlessCommandRunner(): - - """ - Lazy initialization singleton to open the reader once only - else when the framework scans for - tests, it causes us to open the reader. This breaks the Windows driver. - """ - def __getattr__(self, name): - if name == 'nfc': - - if ContactlessCommandRunner.__nfc_wrapper is None: - ContactlessCommandRunner.__nfc_wrapper = NfcWrapper() - return ContactlessCommandRunner.__nfc_wrapper - - __nfc_wrapper = None - diff --git a/TEST_APPS/testcases/nfc/nfc_cli_helper.py b/TEST_APPS/testcases/nfc/nfc_cli_helper.py deleted file mode 100644 index 8d49dc9044f..00000000000 --- a/TEST_APPS/testcases/nfc/nfc_cli_helper.py +++ /dev/null @@ -1,80 +0,0 @@ -""" -Copyright (c) 2017, Arm Limited and affiliates. -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -# ice-tea cli commands decorator class - - -from nfc_messages import NfcErrors -import logging -import icetea_lib.tools.asserts as asserts - -# Values > 1 k incur large time costs -LARGE_BUFFLEN = 400 # Value for large buffer tests, a maximum value can be read from the target with a command - -class CliHelper(): - """ - Helper methods, checks the nfc SDK error-code for you, makes writing a negative test much easier - Example: - if (target_is_eeprom): - nfc_command("dev1", "start", expected_retcode=-2, expected_nfc_error= NfcErrors.nfc_err_unsupported) - else: - nfc_command("dev1", "start") - """ - - def nfc_command(self, k, cmd, # pylint: disable=invalid-name - wait=True, - timeout=10, - expected_retcode=0, - asynchronous=False, - report_cmd_fail=True, - expected_nfc_error=NfcErrors.nfc_ok): - """ - By default will assert if the NFC result code is non-zero. - """ - response = self.command(k, cmd, wait, timeout, expected_retcode, asynchronous, report_cmd_fail) - asserts.assertEqual(int(response.parsed['lastnfcerror']), expected_nfc_error.value) - return response - - @staticmethod - def command_is(string, command): - return string.split(' ')[0] == command - - @staticmethod - def debug_nfc_data(key, value): - """ - print useful data values for the host/user with a >> preamble to make it easy to spot - """ - text = ">> %s=%s" % (key, value) - logging.Logger.info(text) - - def assert_binary_equal(self, left, right): - asserts.assertEqual(len(left), len(right), "Buffers are not same length %d %d" % (len(left), len(right))) - i = 0 - while i < len(left): - asserts.assertEqual(left[i], ord(right[i]), ("Missmatch @offset %d 0x%x <> 0x%x" % (i, left[i], ord(right[i]))) ) - i = i + 1 - - def assert_text_equal(self, left, right): - """ - Asserts if the 2 buffers (Text) differ - """ - asserts.assertEqual(len(left), len(right), "Buffers are not same length %d %d" % (len(left), len(right))) - i = 0 - while i < len(left): - asserts.assertEqual(ord(left[i]), ord(right[i]), ("Missmatch @offset %d %d <> %d" % (i, ord(left[i]), ord(right[i]))) ) - i = i + 1 - diff --git a/TEST_APPS/testcases/nfc/nfc_messages.py b/TEST_APPS/testcases/nfc/nfc_messages.py deleted file mode 100644 index 895dab29437..00000000000 --- a/TEST_APPS/testcases/nfc/nfc_messages.py +++ /dev/null @@ -1,89 +0,0 @@ -""" -Copyright (c) 2017, Arm Limited and affiliates. -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -import nfc -from enum import Enum -import logging - - -class NfcErrors(Enum): - nfc_ok = 0 - nfc_err_unknown = 1 - nfc_err_length = 2 - nfc_err_not_found = 3 - nfc_err_unsupported = 4 - nfc_err_params = 5 - nfc_err_buffer_too_small = 6 - nfc_err_timeout = 7 - nfc_err_crc = 8 - nfc_err_nopeer = 9 - nfc_err_parity = 10 - nfc_err_field = 11 - nfc_err_collision = 12 - nfc_err_wrong_comm = 13 - nfc_err_protocol = 14 - nfc_err_busy = 15 - nfc_err_controller = 16 - nfc_err_halted = 17 - nfc_err_mac = 18 - nfc_err_underflow = 19 - nfc_err_disconnected = 20 - nfc_err_aborted = 21 - - -''' -return a 'T'ext text ndef record -''' -def make_textrecord(text, language='en-US'): - return nfc.ndef.Message(nfc.ndef.TextRecord(text, language)) - -''' -Return an NDEF message -resource -- url -titles -- list of : colon delimited titles where an optional language code precedes the title - -if lang codes are omitted, 'en' is assumed -action -- one of default/save/exec/edit -''' -def make_smartposter(resource, titles, action = 'default'): - record = nfc.ndef.SmartPosterRecord(resource) - for title in titles: - lang, text = title.split(':', 1) if ':' in title else ('en', title) - record.title[lang] = text - if not action in ('default', 'exec', 'save', 'edit'): - logging.error("action not one of 'default', 'exec', 'save', 'edit'") - return - record.action = action - - return nfc.ndef.Message(record) - - -''' -Program the provided NDEF messsage into the tag (authentication is not required) -''' -def program_remote_tag(message, tag): - if not tag.ndef.is_writeable: - logging.error("This Tag is not writeable.") - return False - tag.ndef.message = message - logging.info("Programmed tag OK.") - return True - -''' -Builds a long string by repeating a shorter string up to the required length -''' -def repeat_string_to_length(string_to_expand, length): - return (string_to_expand * ((length/len(string_to_expand))+1))[:length] diff --git a/TEST_APPS/testcases/nfc/test_nfc.py b/TEST_APPS/testcases/nfc/test_nfc.py deleted file mode 100644 index cdad33f9e94..00000000000 --- a/TEST_APPS/testcases/nfc/test_nfc.py +++ /dev/null @@ -1,259 +0,0 @@ -""" -Copyright (c) 2017, Arm Limited and affiliates. -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - - -from icetea_lib.bench import Bench -from nfc_clf_wrapper import ContactlessCommandRunner -import nfc_messages -import time -from mbed_clitest.tools.tools import test_case -import icetea_lib.tools.asserts as asserts -from nfc_messages import NfcErrors -from nfc_cli_helper import CliHelper -from nfc_cli_helper import LARGE_BUFFLEN - - -class CreamSconeTests(Bench, CliHelper): - """ - This test wrapper requires a usb connected contactless card reader dongle, and allows E2E testing. - See readme file for details - """ - def __init__(self, **kwargs): - testcase_args = { - 'title':"NFC tests with a reader", - 'status':"development", - 'purpose':"NFC e2e", - 'component':["NFC"], - 'type':"regression", - 'requirements':{ - "duts": { - '*': { - "count": 1, - "type": "hardware", - "application": { - "name": "TEST_APPS-device-nfcapp" - } - }, - "1": {"nick": "dev1"} - } - } - } - testcase_args.update(kwargs) - Bench.__init__(self, **testcase_args) - - def setup(self): - self.logger.info("Test setup: Open Reader and mute...") - try: - self.clf = ContactlessCommandRunner() - self.clf.nfc.mute() # mute if the last test case did not mute - except: - raise asserts.TestStepFail("Could not find NFC reader") - - def teardown(self): - self.logger.info("Test teardown: Reboot target...") - self.reset_dut() - self.clf.nfc.mute() # mute if the last test case did not mute - - def prepare_target(self): - """ - simple set up a clean target device - :return: - """ - response = self.nfc_command("dev1", "iseeprom") - eeprom = response.parsed['iseeprom'] - self.logger.info("Target includes NFCEEPROM: %s" % eeprom) - self.nfc_command("dev1", "initnfc") - if not eeprom: - self.nfc_command("dev1", "start") - - self.nfc_command("dev1", "erase") - - -@test_case(CreamSconeTests) -def test_nfce2e_target_found(self): - """ - smoke - Our emulated tag is detectable - """ - - response = self.nfc_command("dev1", "iseeprom") - eeprom = response.parsed['iseeprom'] - - # Invokes icetea command, this method also checks the NFC api result expected_nfc_error=NFC_OK - # Tester can supply the expected_nfc_error=NFC_XXX parameter, to override. - self.nfc_command("dev1", "initnfc") - if not eeprom: - self.nfc_command("dev1", "start") - - tag = self.clf.nfc.connect() - asserts.assertNotNone(tag, "Could not connect to any tag") - - -@test_case(CreamSconeTests) -def test_nfce2e_smartposter(self): - """ - check - Tag can be set and read via contactless - """ - expectedURI = "https://www.mbed.com" # ensure that these differ per test case - - self.prepare_target() - - # write poster tag to target - self.command("dev1", "setsmartposter %s" % expectedURI) - - tag = self.clf.nfc.connect() - asserts.assertNotNone(tag, "Could not connect to any tag") - asserts.assertEqual(1, len(tag.ndef.records), "expected number NDEF records") - - asserts.assertEqual(tag.ndef.records[0].__class__.__name__, "SmartposterRecord", "expected SmartposterRecord") - asserts.assertEqual(expectedURI, tag.ndef.records[0].uri_records[0].uri, "expected exact URI") - - -@test_case(CreamSconeTests) -def test_nfce2e_reprogrammed(self): - """ - check - Tag can be programmed from a remote and read via contactless - """ - expectedURI = "https://www.google.com" - - self.prepare_target() - - # program a poster tag to target - self.logger.info("Write Smartposter MESSAGE wirelessly") - tag = self.clf.nfc.connect() - asserts.assertNotNone(tag, "Could not connect to any tag") - smartposter = nfc_messages.make_smartposter(expectedURI, ["en-US:Other search engines exist"]) - nfc_messages.program_remote_tag(smartposter, tag) - self.logger.info("Remote programmed %d bytes Smartposter" % len(str(smartposter))) - - self.logger.info("Write back Smartposter MESSAGE wirelessly") - tag = self.clf.nfc.connect() - asserts.assertNotNone(tag, "Could not re-connect to any tag") - - asserts.assertEqual(tag.ndef.records[0].__class__.__name__, "SmartposterRecord", "expected SmartposterRecord") - asserts.assertEqual(expectedURI, tag.ndef.records[0].uri_records[0].uri, "expected exact URI") - self.clf.nfc.mute() # disable radio, to allow a local session - - # verify in target - response = self.nfc_command("dev1", "readmessage") - - # check contents - expected_message = str(smartposter) - self.assert_binary_equal(response.parsed['nfcmessage'], expected_message) - - -@test_case(CreamSconeTests) -def test_nfce2e_read_stress(self): - """ - check - Large record can be programmed in and read via contactless - """ - message_to_repeat = 'thequickbrownfoxjumpedoverthelazydog' # repeating message written - text_length = LARGE_BUFFLEN - # calculate actual message to compare to using the library - expected_text = nfc_messages.repeat_string_to_length(message_to_repeat, text_length) - - self.prepare_target() - # write a large message to the tag via API, then read it wirelessly - self.logger.info("Write/set tag MESSAGE (%d) bytes" % text_length) - self.nfc_command("dev1", "writelong %d %s" % (text_length,message_to_repeat)) - - - # assert that read the eeprom contents gives correct data and length - self.logger.info("Read tag MESSAGE wirelessly" ) - tag = self.clf.nfc.connect() - asserts.assertNotNone(tag, "Could not connect to any tag") - - asserts.assertEqual(tag.ndef.records[0].__class__.__name__, "TextRecord", "expected TextRecord") - self.assert_text_equal(tag.ndef.records[0].text, expected_text) - - -@test_case(CreamSconeTests) -def test_nfce2e_reprogrammed_stress(self): - """ - check - Large record can be programmed from a remote and read via contactless - """ - message_to_repeat = 'thequickbrownfoxjumpedoverthelazydog' # repeating message written - text_length = LARGE_BUFFLEN # large values slow down test runs and may time out - - # calculate actual message to compare to using the library - message = nfc_messages.make_textrecord( nfc_messages.repeat_string_to_length(message_to_repeat, text_length)) - expected_message = str(message) - - self.prepare_target() - # program a large tag to target remotely - self.logger.info("Write tag MESSAGE wirelessly (%d) bytes" % len(str(message))) - tag = self.clf.nfc.connect() - asserts.assertNotNone(tag, "Could not connect to any tag") - nfc_messages.program_remote_tag(message, tag) - self.logger.info("%d bytes chunk of data written to tag remotely" % len(str(message))) - self.clf.nfc.mute() - - # read device locally - self.logger.info("Read back tag MESSAGE wirelessly") - tag = self.clf.nfc.connect() - asserts.assertNotNone(tag, "Could not re-connect to any tag") - asserts.assertEqual(tag.ndef.records[0].__class__.__name__, "TextRecord", "expected TextRecord") - self.clf.nfc.mute() # disable the reader radio, to allow local access - - # verify in target - response = self.nfc_command("dev1", "readmessage") - self.assert_binary_equal(response.parsed['nfcmessage'], expected_message) - - -@test_case(CreamSconeTests) -def test_nfce2e_discovery_loop(self): - """ - check - Controller discovery loop stop/start - fails : blocked by an issue on NFC controllers only - """ - expectedURI = "https://www.nasa.com" # ensure that these differ per test case - - response = self.command("dev1", "iseeprom") # will hold result from the init lib call - eeprom = response.parsed['iseeprom'] - self.logger.info("Target includes NFCEEPROM: %s" % eeprom) - - self.nfc_command("dev1", "initnfc") # this NOT automatically start discovery at the same time, the test command - # "start" must be used on a controller. (Eeeproms always have the loop enabled.) - # By default, the test app automatically starts discovery loop again after a reader disconnects from the controller. - # Automatic resume after disconnect can be turned off by using command "start man" , the default is "start auto" . - - if not eeprom: - # we are muted at this point, and the target is not in discovery mode yet. - tag = self.clf.nfc.connect() - asserts.assertNone(tag, "post-init: Tag discovery loop should be stopped!") - self.nfc_command("dev1", "stop") - time.sleep(1) - - tag = self.clf.nfc.connect() - asserts.assertNone(tag, "post-stop: Tag discovery loop should be stopped!") - self.nfc_command("dev1", "start") - time.sleep(1) - - tag = self.clf.nfc.connect() - asserts.assertNotNone(tag, "Could not connect to any tag") - - self.clf.nfc.mute() - self.nfc_command("dev1", "stop") - time.sleep(10) - tag = self.clf.nfc.connect() - # test blocked by issue raised IOTPAN313 NFC Controller discovery can stop but cannot restart - PN512 - asserts.assertNone(tag, "post-restart: Tag discovery loop should be stopped!") - - else: - # eeprom, so not supported - self.nfc_command("dev1", "start", expected_retcode=-2, expected_nfc_error= NfcErrors.nfc_err_unsupported ) - self.nfc_command("dev1", "stop", expected_retcode=-2, expected_nfc_error= NfcErrors.nfc_err_unsupported ) - diff --git a/TEST_APPS/testcases/nfc/test_self.py b/TEST_APPS/testcases/nfc/test_self.py deleted file mode 100644 index d59eeb3c46d..00000000000 --- a/TEST_APPS/testcases/nfc/test_self.py +++ /dev/null @@ -1,256 +0,0 @@ -""" -Copyright (c) 2017, Arm Limited and affiliates. -SPDX-License-Identifier: Apache-2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -import time -from icetea_lib.bench import Bench -from mbed_clitest.tools.tools import test_case -import icetea_lib.tools.asserts as asserts -import nfc_messages -from nfc_messages import NfcErrors -from nfc_cli_helper import CliHelper -from nfc_cli_helper import LARGE_BUFFLEN -import nfc - -""" -Standalone (no NFC reader needed) tests, which cover API with no end-to-end checks. -""" -class CreamSconeSelfTests(Bench, CliHelper): - def __init__(self, **kwargs): - testcase_args = { - 'title':"NFC tests with no reader", - 'status':"development", - 'purpose':"NFC target-only checks", - 'component':["NFC"], - 'type':"smoke", - 'requirements':{ - "duts": { - '*': { - "count": 1, - "type": "hardware", - "application": { - "name": "TEST_APPS-device-nfcapp" - } - }, - "1": {"nick": "dev1"} - } - } - } - testcase_args.update(kwargs) - Bench.__init__(self, **testcase_args) - - def setup(self): - pass - - def teardown(self): - self.logger.info("Test teardown: Reboot target...") - self.reset_dut() - - -""" -smoke - target app is running, and can exchange simple values -""" -@test_case(CreamSconeSelfTests) -def test_nfc_error_codes(self): - wally = NfcErrors.nfc_err_not_found - for x in range(0, 3): - self.nfc_command("dev1", "setlastnfcerror %d" % wally.value, expected_nfc_error=wally) - self.nfc_command("dev1", "getlastnfcerror", expected_nfc_error=wally) - - self.nfc_command("dev1", "setlastnfcerror %d" % 0) - self.nfc_command("dev1", "getlastnfcerror") - - -""" -smoke - target app reports if NFC eeprom driver present -""" -@test_case(CreamSconeSelfTests) -def test_nfc_eeprom(self): - - response = self.command("dev1", "iseeprom") # will hold result from the init lib call - self.logger.info("Target includes NFCEEPROM: %s" % response.parsed['iseeprom']) - -""" -check - Assert discovery can be started/stopped -""" -@test_case(CreamSconeSelfTests) -def test_nfc_discovery(self): - - self.nfc_command("dev1", "initnfc") - - response = self.nfc_command("dev1", "iseeprom") # will hold result from the init lib call - eeprom = response.parsed['iseeprom'] - self.logger.info("Target includes NFCEEPROM: %s" % eeprom) - if not eeprom: - self.nfc_command("dev1", "start") - self.nfc_command("dev1", "stop") - self.nfc_command("dev1", "start") - self.nfc_command("dev1", "stop") - else: - # eeprom, so not supported - self.nfc_command("dev1", "start", expected_retcode=-2, expected_nfc_error = NfcErrors.nfc_err_unsupported ) - self.nfc_command("dev1", "stop", expected_retcode=-2 , expected_nfc_error= NfcErrors.nfc_err_unsupported ) - -""" -check - Create a SmartPoster but does not read it back -""" -@test_case(CreamSconeSelfTests) -def test_nfc_setsmartposter(self): - - self.nfc_command("dev1", "initnfc") - - self.nfc_command("dev1", "setsmartposter https://www.mbed.com") - -@test_case(CreamSconeSelfTests) -def test_nfc_erase(self): - self.nfc_command("dev1", "initnfc") - response = self.nfc_command("dev1", "iseeprom") - eeprom = response.parsed['iseeprom'] - if eeprom: - self.logger.info("Target includes NFCEEPROM: %s" % eeprom) - self.nfc_command("dev1", "erase", timeout=30) - response = self.nfc_command("dev1", "readmessage") - asserts.assertEqual(response.parsed['nfcmessage'] is None, True) - -''' -check - Build a long message by copying a string to stress the driver with a nominal buffer. Verify contents of entire message -can be read back. -''' -@test_case(CreamSconeSelfTests) -def test_nfc_write_long(self): - messageRep = 'thequickbrownfoxjumpedoverthelazydog' # repeating message written - textLength = LARGE_BUFFLEN # large values take longer - # calculate actual message to compare to using the library - message = nfc_messages.make_textrecord( nfc_messages.repeat_string_to_length(messageRep, textLength)) - expected_message = str(message) - - self.nfc_command("dev1", "initnfc") - response = self.nfc_command("dev1", "iseeprom") - eeprom = response.parsed['iseeprom'] - if eeprom: - self.logger.info("Target includes NFCEEPROM: %s" % eeprom) - self.nfc_command("dev1", "erase") - self.nfc_command("dev1", "writelong %d %s" % (textLength,messageRep)) - response = self.nfc_command("dev1", "readmessage") - # assert that read the eeprom contents gives textlength bytes (including framing bytes which will vary) - self.assert_binary_equal(response.parsed['nfcmessage'], expected_message) - -''' -check - Query supported protocols if we have a controller -''' -@test_case(CreamSconeSelfTests) -def test_nfc_get_controller_protocols(self): - self.nfc_command("dev1", "initnfc") - - response = self.nfc_command("dev1", "iseeprom") - eeprom = response.parsed['iseeprom'] - if eeprom: - self.logger.info("Test ignore - target includes NFCEEPROM: %s" % eeprom) - else: - response = self.nfc_command("dev1", "getprotocols") - self.logger.info("Protocols = %s" % response.parsed['protocols']) - self.assertNotEqual(len(response.parsed['protocols']), 0, "Expected at least 1 protocol supported") - - -''' -check - Can set used protocols if we have a controller -Note: Currently only support Typ4 tags in PN512 driver -''' -@test_case(CreamSconeSelfTests) -def test_nfc_set_controller_protocols(self): - self.nfc_command("dev1", "initnfc") - - response = self.nfc_command("dev1", "iseeprom") - eeprom = response.parsed['iseeprom'] - if eeprom: - # eeproms do not allow target control - self.logger.info("Test ignore - target includes NFCEEPROM: %s" % eeprom) - else: - self.nfc_command("dev1", "setprotocols t1t") - self.nfc_command("dev1", "setprotocols t2t") - self.nfc_command("dev1", "setprotocols t3t") - self.nfc_command("dev1", "setprotocols isodep") - self.nfc_command("dev1", "setprotocols nfcdep") - self.nfc_command("dev1", "setprotocols t5t") - self.nfc_command("dev1", "setprotocols t1t t2t t3t isodep nfcdep t5t") - -''' -check - SmartPoster URI forms are supported (in the test-app) -''' -@test_case(CreamSconeSelfTests) -def test_nfc_check_smartposter_uri_forms(self): - def enum(**enums): - return type('Enum', (), enums) - - IDS = enum(NA=0x00, # Not applicable - HTTP_WWW=0x01, # http://www. - HTTPS_WWW=0x02, # https://www. - HTTP=0x03, # http:// - HTTPS=0x04, # https:// - TEL=0x05, # tel: - MAILTO=0x06, # mailto: - FTP_ANONYMOUS=0x07, # ftp://anonymous:anonymous@ - FTP_FTP=0x08, # ftp://ftp. - FTPS=0x09, # ftps:// - SFTP=0x0A, # sftp:// - SMB=0x0B, # smb:// - NFS=0x0C, # nfs:// - FTP=0x0D, # ftp:// - DAV=0x0E, # dav:// - NEWS=0x0F, # news: - TELNET=0x10, # telnet:// - IMAP=0x11, # imap: - RSTP=0x12, # rstp:// - URN=0x13, # urn: - POP=0x14, # pop: - SIP=0x15, # sip: - SIPS=0x16, # sips: - TFTP=0x17, # tftp: - BTSPP=0x18, # btspp:// - BTL2CAP=0x19, # btl2cap:// - BTGOEP=0x1A, # btgoep:// - TCPOBEX=0x1B, # tcpobex:// - IRDAOBEX=0x1C, # irdaobex:// - FILE=0x1D, # file:// - URN_EPC_ID=0x1E, # urn:epc:id: - URN_EPC_TAG=0x1F, # urn:epc:tag: - URN_EPC_PAT=0x20, # urn:epc:pat: - URN_EPC_RAW=0x21, # urn:epc:raw: - URN_EPC=0x22, # urn:epc: - URN_NFC=0x23, # urn:nfc: - ) - self.nfc_command("dev1", "initnfc") - result = self.nfc_command("dev1", "setsmartposter https://www.mbed.com") - asserts.assertEqual(result.parsed['uri_id'], IDS.HTTPS_WWW, "uri type expected HTTPS_WWW") - result = self.nfc_command("dev1", "setsmartposter http://www.mbed.com") - asserts.assertEqual(result.parsed['uri_id'], IDS.HTTP_WWW) - result = self.nfc_command("dev1", "setsmartposter https://www.topleveldomain") - asserts.assertEqual(result.parsed['uri_id'], IDS.HTTPS_WWW) - result = self.nfc_command("dev1", "setsmartposter tel:555-5551234") - asserts.assertEqual(result.parsed['uri_id'], IDS.TEL) - result = self.nfc_command("dev1", "setsmartposter ftp://www.mbed.com/files/") - asserts.assertEqual(result.parsed['uri_id'], IDS.FTP ) - -''' -smoke - driver buffer size can be retrieved -''' -@test_case(CreamSconeSelfTests) -def test_nfc_get_max_ndef(self): - self.nfc_command("dev1", "initnfc") - max = self.nfc_command("dev1", "getmaxndef").parsed['maxndef'] - self.logger.info("Target NDEF max buffer size %d" % max) - self.logger.info("Teststress size %d" % LARGE_BUFFLEN) - diff --git a/UNITTESTS/CMakeLists.txt b/UNITTESTS/CMakeLists.txt index 8fb608a6ed8..c194021a979 100644 --- a/UNITTESTS/CMakeLists.txt +++ b/UNITTESTS/CMakeLists.txt @@ -56,5 +56,3 @@ if (VALGRIND) endif(VALGRIND) add_subdirectory(stubs) -add_subdirectory(fakes) - diff --git a/UNITTESTS/fakes/CMakeLists.txt b/UNITTESTS/fakes/CMakeLists.txt deleted file mode 100644 index 8c1c4a9f3f5..00000000000 --- a/UNITTESTS/fakes/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) 2020 ARM Limited. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -add_subdirectory(ble) diff --git a/UNITTESTS/stubs/CMakeLists.txt b/UNITTESTS/stubs/CMakeLists.txt index 8fe0d350923..de1b11dc6ce 100644 --- a/UNITTESTS/stubs/CMakeLists.txt +++ b/UNITTESTS/stubs/CMakeLists.txt @@ -3,38 +3,16 @@ add_library(mbed-stubs-headers INTERFACE) add_library(mbed-headers INTERFACE) -add_library(mbed-headers-base INTERFACE) -add_library(mbed-headers-connectivity INTERFACE) target_link_libraries(mbed-headers INTERFACE - mbed-headers-base mbed-headers-platform - mbed-headers-connectivity mbed-headers-drivers mbed-headers-hal mbed-headers-events mbed-headers-rtos ) -target_include_directories(mbed-headers-base - INTERFACE - ${mbed-os_SOURCE_DIR}/UNITTESTS/target_h - ${mbed-os_SOURCE_DIR}/UNITTESTS/target_h/platform - ${mbed-os_SOURCE_DIR}/UNITTESTS/target_h/platform/cxxsupport - ${mbed-os_SOURCE_DIR}/UNITTESTS/target_h/drivers - ${mbed-os_SOURCE_DIR}/UNITTESTS/target_h/rtos/include - ${mbed-os_SOURCE_DIR}/UNITTESTS/target_h/rtos - ${mbed-os_SOURCE_DIR}/UNITTESTS/target_h/sys -) - -target_include_directories(mbed-headers-connectivity - INTERFACE - ${mbed-os_SOURCE_DIR}/connectivity - ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/include - ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/include/ble -) - target_include_directories(mbed-headers INTERFACE ${mbed-os_SOURCE_DIR}/features diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/Include/cmsis_os2.h b/cmsis/CMSIS_5/CMSIS/RTOS2/Include/cmsis_os2.h index e0b602c79a0..76612e29291 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/Include/cmsis_os2.h +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/Include/cmsis_os2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 Arm Limited. All rights reserved. + * Copyright (c) 2013-2020 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -17,7 +17,7 @@ * * ---------------------------------------------------------------------- * - * $Date: 18. June 2018 + * $Date: 12. June 2020 * $Revision: V2.1.3 * * Project: CMSIS-RTOS2 API @@ -86,7 +86,7 @@ typedef enum { osKernelLocked = 3, ///< Locked. osKernelSuspended = 4, ///< Suspended. osKernelError = -1, ///< Error. - osKernelReserved = 0x7FFFFFFFU ///< Prevents enum down-size compiler optimization. + osKernelReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. } osKernelState_t; /// Thread state. @@ -723,7 +723,7 @@ osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t * /// \return maximum number of messages. uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id); -/// Get maximum message size in a Memory Pool. +/// Get maximum message size in a Message Queue. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. /// \return maximum message size in bytes. uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id); diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/Include/os_tick.h b/cmsis/CMSIS_5/CMSIS/RTOS2/Include/os_tick.h index 8f7cdf667b1..3cfd8954759 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/Include/os_tick.h +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/Include/os_tick.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file os_tick.h * @brief CMSIS OS Tick header file - * @version V1.0.1 - * @date 24. November 2017 + * @version V1.0.2 + * @date 19. March 2021 ******************************************************************************/ /* - * Copyright (c) 2017-2017 ARM Limited. All rights reserved. + * Copyright (c) 2017-2021 ARM Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -27,6 +27,11 @@ #include +#ifdef __cplusplus +extern "C" +{ +#endif + /// IRQ Handler. #ifndef IRQHANDLER_T #define IRQHANDLER_T @@ -68,4 +73,8 @@ uint32_t OS_Tick_GetCount (void); /// \return OS Tick overflow status (1 - overflow, 0 - no overflow). uint32_t OS_Tick_GetOverflow (void); +#ifdef __cplusplus +} +#endif + #endif /* OS_TICK_H */ diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Config/RTX_Config.c b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Config/RTX_Config.c index e4871014aa1..737078aae77 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Config/RTX_Config.c +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Config/RTX_Config.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -17,7 +17,7 @@ * * ----------------------------------------------------------------------------- * - * $Revision: V5.1.0 + * $Revision: V5.1.1 * * Project: CMSIS-RTOS RTX * Title: RTX Configuration @@ -40,7 +40,7 @@ __WEAK uint32_t osRtxErrorNotify (uint32_t code, void *object_id) { (void)object_id; switch (code) { - case osRtxErrorStackUnderflow: + case osRtxErrorStackOverflow: // Stack overflow detected for thread (thread_id=object_id) break; case osRtxErrorISRQueueOverflow: diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Config/RTX_Config.h b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Config/RTX_Config.h index 244ed17e34d..4d2f501b4b0 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Config/RTX_Config.h +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Config/RTX_Config.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -17,7 +17,7 @@ * * ----------------------------------------------------------------------------- * - * $Revision: V5.5.1 + * $Revision: V5.5.2 * * Project: CMSIS-RTOS RTX * Title: RTX Configuration definitions @@ -69,7 +69,7 @@ // -// ISR FIFO Queue +// ISR FIFO Queue // <4=> 4 entries <8=> 8 entries <12=> 12 entries <16=> 16 entries // <24=> 24 entries <32=> 32 entries <48=> 48 entries <64=> 64 entries // <96=> 96 entries <128=> 128 entries <196=> 196 entries <256=> 256 entries @@ -143,10 +143,10 @@ #endif // Stack overrun checking -// Enables stack overrun check at thread switch. +// Enables stack overrun check at thread switch (requires RTX source variant). // Enabling this option increases slightly the execution time of a thread switch. #ifndef OS_STACK_CHECK -#define OS_STACK_CHECK 1 +#define OS_STACK_CHECK 0 #endif // Stack usage watermark @@ -156,8 +156,8 @@ #define OS_STACK_WATERMARK 0 #endif -// Processor mode for Thread execution -// <0=> Unprivileged mode +// Processor mode for Thread execution +// <0=> Unprivileged mode // <1=> Privileged mode // Default: Privileged mode #ifndef OS_PRIVILEGE_MODE @@ -367,125 +367,125 @@ // Recording levels for RTX components. // Only applicable if events for the respective component are generated. -// Memory Management +// Memory Management // Recording level for Memory Management events. // Error events // API function call events // Operation events // Detailed operation events -// -#ifndef OS_EVR_MEMORY_LEVEL -#define OS_EVR_MEMORY_LEVEL 0x01U +// +#ifndef OS_EVR_MEMORY_LEVEL +#define OS_EVR_MEMORY_LEVEL 0x81U #endif -// Kernel +// Kernel // Recording level for Kernel events. // Error events // API function call events // Operation events // Detailed operation events -// -#ifndef OS_EVR_KERNEL_LEVEL -#define OS_EVR_KERNEL_LEVEL 0x01U +// +#ifndef OS_EVR_KERNEL_LEVEL +#define OS_EVR_KERNEL_LEVEL 0x81U #endif -// Thread +// Thread // Recording level for Thread events. // Error events // API function call events // Operation events // Detailed operation events -// -#ifndef OS_EVR_THREAD_LEVEL -#define OS_EVR_THREAD_LEVEL 0x05U +// +#ifndef OS_EVR_THREAD_LEVEL +#define OS_EVR_THREAD_LEVEL 0x85U #endif -// Generic Wait +// Generic Wait // Recording level for Generic Wait events. // Error events // API function call events // Operation events // Detailed operation events -// -#ifndef OS_EVR_WAIT_LEVEL -#define OS_EVR_WAIT_LEVEL 0x01U +// +#ifndef OS_EVR_WAIT_LEVEL +#define OS_EVR_WAIT_LEVEL 0x81U #endif -// Thread Flags +// Thread Flags // Recording level for Thread Flags events. // Error events // API function call events // Operation events // Detailed operation events -// -#ifndef OS_EVR_THFLAGS_LEVEL -#define OS_EVR_THFLAGS_LEVEL 0x01U +// +#ifndef OS_EVR_THFLAGS_LEVEL +#define OS_EVR_THFLAGS_LEVEL 0x81U #endif -// Event Flags +// Event Flags // Recording level for Event Flags events. // Error events // API function call events // Operation events // Detailed operation events -// -#ifndef OS_EVR_EVFLAGS_LEVEL -#define OS_EVR_EVFLAGS_LEVEL 0x01U +// +#ifndef OS_EVR_EVFLAGS_LEVEL +#define OS_EVR_EVFLAGS_LEVEL 0x81U #endif -// Timer +// Timer // Recording level for Timer events. // Error events // API function call events // Operation events // Detailed operation events -// -#ifndef OS_EVR_TIMER_LEVEL -#define OS_EVR_TIMER_LEVEL 0x01U +// +#ifndef OS_EVR_TIMER_LEVEL +#define OS_EVR_TIMER_LEVEL 0x81U #endif -// Mutex +// Mutex // Recording level for Mutex events. // Error events // API function call events // Operation events // Detailed operation events -// -#ifndef OS_EVR_MUTEX_LEVEL -#define OS_EVR_MUTEX_LEVEL 0x01U +// +#ifndef OS_EVR_MUTEX_LEVEL +#define OS_EVR_MUTEX_LEVEL 0x81U #endif -// Semaphore +// Semaphore // Recording level for Semaphore events. // Error events // API function call events // Operation events // Detailed operation events -// -#ifndef OS_EVR_SEMAPHORE_LEVEL -#define OS_EVR_SEMAPHORE_LEVEL 0x01U +// +#ifndef OS_EVR_SEMAPHORE_LEVEL +#define OS_EVR_SEMAPHORE_LEVEL 0x81U #endif -// Memory Pool +// Memory Pool // Recording level for Memory Pool events. // Error events // API function call events // Operation events // Detailed operation events -// -#ifndef OS_EVR_MEMPOOL_LEVEL -#define OS_EVR_MEMPOOL_LEVEL 0x01U +// +#ifndef OS_EVR_MEMPOOL_LEVEL +#define OS_EVR_MEMPOOL_LEVEL 0x81U #endif -// Message Queue +// Message Queue // Recording level for Message Queue events. // Error events // API function call events // Operation events // Detailed operation events -// -#ifndef OS_EVR_MSGQUEUE_LEVEL -#define OS_EVR_MSGQUEUE_LEVEL 0x01U +// +#ifndef OS_EVR_MSGQUEUE_LEVEL +#define OS_EVR_MSGQUEUE_LEVEL 0x81U #endif // diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include/rtx_def.h b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include/rtx_def.h new file mode 100644 index 00000000000..26230e70ae2 --- /dev/null +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include/rtx_def.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ----------------------------------------------------------------------------- + * + * Project: CMSIS-RTOS RTX + * Title: RTX derived definitions + * + * ----------------------------------------------------------------------------- + */ + +#ifndef RTX_DEF_H_ +#define RTX_DEF_H_ + +#ifdef _RTE_ +#include "RTE_Components.h" +#endif +#include "RTX_Config.h" + +#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) + #define RTX_OBJ_MEM_USAGE +#endif + +#if (defined(OS_STACK_CHECK) && (OS_STACK_CHECK != 0)) + #define RTX_STACK_CHECK +#endif + +#ifdef RTE_CMSIS_RTOS2_RTX5_ARMV8M_NS + #define DOMAIN_NS 1 +#endif + +#endif // RTX_DEF_H_ diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include/rtx_evr.h b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include/rtx_evr.h index 1dec30a79fd..2a6899e8ce2 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include/rtx_evr.h +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include/rtx_evr.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -26,8 +26,6 @@ #ifndef RTX_EVR_H_ #define RTX_EVR_H_ -#include "cmsis_os2.h" // CMSIS RTOS API -#include "RTX_Config.h" // RTX Configuration #include "rtx_os.h" // RTX OS definitions // Initial Thread configuration covered also Thread Flags and Generic Wait @@ -393,6 +391,17 @@ extern void EvrRtxKernelGetSysTimerFreq (uint32_t freq); #define EvrRtxKernelGetSysTimerFreq(freq) #endif +/** + \brief Event on RTOS kernel system error (Error) + \param[in] code error code. + \param[in] object_id object that caused the error. +*/ +#if (!defined(EVR_RTX_DISABLE) && (OS_EVR_KERNEL != 0) && !defined(EVR_RTX_KERNEL_ERROR_NOTIFY_DISABLE)) +extern void EvrRtxKernelErrorNotify (uint32_t code, void *object_id); +#else +#define EvrRtxKernelErrorNotify(code, object_id) +#endif + // ==== Thread Events ==== diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include/rtx_os.h b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include/rtx_os.h index c54e2f230c3..65e4227aa08 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include/rtx_os.h +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include/rtx_os.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -29,6 +29,7 @@ #include #include #include "cmsis_os2.h" +#include "rtx_def.h" #ifdef __cplusplus extern "C" @@ -38,8 +39,8 @@ extern "C" /// Kernel Information #define osRtxVersionAPI 20010003 ///< API version (2.1.3) -#define osRtxVersionKernel 50050002 ///< Kernel version (5.5.2) -#define osRtxKernelId "RTX V5.5.2" ///< Kernel identification string +#define osRtxVersionKernel 50050003 ///< Kernel version (5.5.3) +#define osRtxKernelId "RTX V5.5.3" ///< Kernel identification string // ==== Common definitions ==== @@ -110,7 +111,7 @@ typedef struct osRtxThread_s { struct osRtxThread_s *delay_next; ///< Link pointer to next Thread in Delay list struct osRtxThread_s *delay_prev; ///< Link pointer to previous Thread in Delay list struct osRtxThread_s *thread_join; ///< Thread waiting to Join - uint32_t delay; ///< Delay Time + uint32_t delay; ///< Delay Time/Round Robin Time Tick int8_t priority; ///< Thread Priority int8_t priority_base; ///< Base Priority uint8_t stack_frame; ///< Stack Frame (EXC_RETURN[7..0]) @@ -296,9 +297,9 @@ typedef struct { osRtxThread_t *delay_list; ///< Delay List osRtxThread_t *wait_list; ///< Wait List (no Timeout) osRtxThread_t *terminate_list; ///< Terminate Thread List + uint32_t reserved; struct { ///< Thread Round Robin Info osRtxThread_t *thread; ///< Round Robin Thread - uint32_t tick; ///< Round Robin Time Tick uint32_t timeout; ///< Round Robin Timeout } robin; } thread; @@ -392,7 +393,8 @@ extern osRtxObjectMemUsage_t osRtxMessageQueueMemUsage; // ==== OS External Functions ==== // OS Error Codes -#define osRtxErrorStackUnderflow 1U ///< Stack overflow, i.e. stack pointer below its lower memory limit for descending stacks. +#define osRtxErrorStackUnderflow 1U ///< \deprecated Superseded by \ref osRtxErrorStackOverflow. +#define osRtxErrorStackOverflow 1U ///< Stack overflow, i.e. stack pointer below its lower memory limit for descending stacks. #define osRtxErrorISRQueueOverflow 2U ///< ISR Queue overflow detected when inserting object. #define osRtxErrorTimerQueueOverflow 3U ///< User Timer Callback Queue overflow detected for timer. #define osRtxErrorClibSpace 4U ///< Standard C/C++ library libspace not available: increase \c OS_THREAD_LIBSPACE_NUM. @@ -400,6 +402,7 @@ extern osRtxObjectMemUsage_t osRtxMessageQueueMemUsage; /// OS Error Callback function extern uint32_t osRtxErrorNotify (uint32_t code, void *object_id); +extern uint32_t osRtxKernelErrorNotify (uint32_t code, void *object_id); /// OS Idle Thread extern void osRtxIdleThread (void *argument); @@ -453,10 +456,12 @@ typedef struct { osRtxMpInfo_t *message_queue; ///< Message Queue Control Blocks } mpi; uint32_t thread_stack_size; ///< Default Thread Stack Size - const + const osThreadAttr_t *idle_thread_attr; ///< Idle Thread Attributes const osThreadAttr_t *timer_thread_attr; ///< Timer Thread Attributes + void (*timer_thread)(void *); ///< Timer Thread Function + int32_t (*timer_setup)(void); ///< Timer Setup Function const osMessageQueueAttr_t *timer_mq_attr; ///< Timer Message Queue Attributes uint32_t timer_mq_mcnt; ///< Timer Message Queue maximum Messages diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_CORTEX_A/irq_ca.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_CORTEX_A/irq_ca.S index e54c42de3c6..daf5fe8372f 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_CORTEX_A/irq_ca.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_CORTEX_A/irq_ca.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2013-2018 Arm Limited. All rights reserved. +; * Copyright (c) 2013-2021 Arm Limited. All rights reserved. ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -18,7 +18,7 @@ ; * ----------------------------------------------------------------------------- ; * ; * Project: CMSIS-RTOS RTX -; * Title: Cortex-A Exception handlers +; * Title: ARMv7-A Exception handlers ; * ; * ----------------------------------------------------------------------------- ; */ @@ -367,16 +367,16 @@ osRtxContextSave STMDB R1!, {R2,R12} ; Push FPSCR, maintain 8-byte alignment VSTMDB R1!, {D0-D15} ; Save D0-D15 - IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32 + IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32 VSTMDB R1!, {D16-D31} ; Save D16-D31 - ENDIF + ENDIF LDRB R2, [LR, #TCB_SP_FRAME] ; Load osRtxInfo.thread.run.curr frame info - IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32 + IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32 ORR R2, R2, #4 ; NEON state - ELSE + ELSE ORR R2, R2, #2 ; VFP state - ENDIF + ENDIF STRB R2, [LR, #TCB_SP_FRAME] ; Store VFP/NEON state osRtxContextSave1 @@ -428,9 +428,9 @@ osRtxContextRestore MCR p15, 0, R2, c1, c0, 2 ; Write CPACR BEQ osRtxContextRestore1 ; No VFP ISB ; Sync if VFP was enabled - IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32 + IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32 VLDMIA LR!, {D16-D31} ; Restore D16-D31 - ENDIF + ENDIF VLDMIA LR!, {D0-D15} ; Restore D0-D15 LDR R2, [LR] VMSR FPSCR, R2 ; Restore FPSCR diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M0/irq_cm0.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M0/irq_cm0.S index c5146b3b81f..a822002f285 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M0/irq_cm0.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M0/irq_cm0.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2013-2018 Arm Limited. All rights reserved. +; * Copyright (c) 2013-2021 Arm Limited. All rights reserved. ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -18,15 +18,22 @@ ; * ----------------------------------------------------------------------------- ; * ; * Project: CMSIS-RTOS RTX -; * Title: Cortex-M0 Exception handlers +; * Title: ARMv6-M Exception handlers ; * ; * ----------------------------------------------------------------------------- ; */ +#ifndef RTX_STACK_CHECK +RTX_STACK_CHECK EQU 0 +#endif + I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset TCB_SP_OFS EQU 56 ; TCB.SP offset +osRtxErrorStackOverflow\ + EQU 1 ; Stack overflow + PRESERVE8 THUMB @@ -44,9 +51,10 @@ SVC_Handler PROC EXPORT SVC_Handler IMPORT osRtxUserSVC IMPORT osRtxInfo - IF :DEF:MPU_LOAD - IMPORT osRtxMpuLoad - ENDIF + IF RTX_STACK_CHECK != 0 + IMPORT osRtxThreadStackCheck + IMPORT osRtxKernelErrorNotify + ENDIF MOV R0,LR LSRS R0,R0,#3 ; Determine return stack from EXC_RETURN bit 2 @@ -57,7 +65,7 @@ SVC_Number LDR R1,[R0,#24] ; Load saved PC from stack SUBS R1,R1,#2 ; Point to SVC instruction LDRB R1,[R1] ; Load SVC number - CMP R1,#0 + CMP R1,#0 ; Check SVC number BNE SVC_User ; Branch if not SVC 0 PUSH {R0,LR} ; Save SP and EXC_RETURN @@ -68,18 +76,42 @@ SVC_Number MOV LR,R3 ; Set EXC_RETURN SVC_Context - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run + LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.thread.run LDMIA R3!,{R1,R2} ; Load osRtxInfo.thread.run: curr & next CMP R1,R2 ; Check if thread switch is required BEQ SVC_Exit ; Branch when threads are the same + SUBS R3,R3,#8 ; Adjust address + STR R2,[R3] ; osRtxInfo.thread.run: curr = next CMP R1,#0 - BEQ SVC_ContextSwitch ; Branch if running thread is deleted + BEQ SVC_ContextRestore ; Branch if running thread is deleted SVC_ContextSave MRS R0,PSP ; Get PSP - SUBS R0,R0,#32 ; Calculate SP + SUBS R0,R0,#32 ; Calculate SP: space for R4..R11 STR R0,[R1,#TCB_SP_OFS] ; Store SP + + IF RTX_STACK_CHECK != 0 + + PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next + MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr + BL osRtxThreadStackCheck ; Check if thread stack is overrun + POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next + CMP R0,#0 + BNE SVC_ContextSaveRegs ; Branch when stack check is ok + + MOVS R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id + BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify + LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run + LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next + STR R2,[R3] ; osRtxInfo.thread.run: curr = next + B SVC_ContextRestore ; Branch to context restore handling + +SVC_ContextSaveRegs + LDR R0,[R1,#TCB_SP_OFS] ; Load SP + + ENDIF + STMIA R0!,{R4-R7} ; Save R4..R7 MOV R4,R8 MOV R5,R9 @@ -87,17 +119,6 @@ SVC_ContextSave MOV R7,R11 STMIA R0!,{R4-R7} ; Save R8..R11 -SVC_ContextSwitch - SUBS R3,R3,#8 ; Adjust address - STR R2,[R3] ; osRtxInfo.thread.run: curr = next - - IF :DEF:MPU_LOAD - PUSH {R2,R3} ; Save registers - MOV R0,R2 ; osRtxMpuLoad parameter - BL osRtxMpuLoad ; Load MPU for next thread - POP {R2,R3} ; Restore registers - ENDIF - SVC_ContextRestore LDR R0,[R2,#TCB_SP_OFS] ; Load SP ADDS R0,R0,#16 ; Adjust address @@ -110,7 +131,7 @@ SVC_ContextRestore SUBS R0,R0,#32 ; Adjust address LDMIA R0!,{R4-R7} ; Restore R4..R7 - MOVS R0,#~0xFFFFFFFD + MOVS R0,#2 ; Binary complement of 0xFFFFFFFD MVNS R0,R0 ; Set EXC_RETURN value BX R0 ; Exit from handler @@ -151,7 +172,7 @@ PendSV_Handler PROC BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler POP {R0,R1} ; Restore EXC_RETURN MOV LR,R1 ; Set EXC_RETURN - B SVC_Context + B SVC_Context ; Branch to context handling ALIGN ENDP @@ -165,7 +186,7 @@ SysTick_Handler PROC BL osRtxTick_Handler ; Call osRtxTick_Handler POP {R0,R1} ; Restore EXC_RETURN MOV LR,R1 ; Set EXC_RETURN - B SVC_Context + B SVC_Context ; Branch to context handling ALIGN ENDP diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M0P/irq_cm0.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M0P/irq_cm0.S index c5146b3b81f..a822002f285 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M0P/irq_cm0.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M0P/irq_cm0.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2013-2018 Arm Limited. All rights reserved. +; * Copyright (c) 2013-2021 Arm Limited. All rights reserved. ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -18,15 +18,22 @@ ; * ----------------------------------------------------------------------------- ; * ; * Project: CMSIS-RTOS RTX -; * Title: Cortex-M0 Exception handlers +; * Title: ARMv6-M Exception handlers ; * ; * ----------------------------------------------------------------------------- ; */ +#ifndef RTX_STACK_CHECK +RTX_STACK_CHECK EQU 0 +#endif + I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset TCB_SP_OFS EQU 56 ; TCB.SP offset +osRtxErrorStackOverflow\ + EQU 1 ; Stack overflow + PRESERVE8 THUMB @@ -44,9 +51,10 @@ SVC_Handler PROC EXPORT SVC_Handler IMPORT osRtxUserSVC IMPORT osRtxInfo - IF :DEF:MPU_LOAD - IMPORT osRtxMpuLoad - ENDIF + IF RTX_STACK_CHECK != 0 + IMPORT osRtxThreadStackCheck + IMPORT osRtxKernelErrorNotify + ENDIF MOV R0,LR LSRS R0,R0,#3 ; Determine return stack from EXC_RETURN bit 2 @@ -57,7 +65,7 @@ SVC_Number LDR R1,[R0,#24] ; Load saved PC from stack SUBS R1,R1,#2 ; Point to SVC instruction LDRB R1,[R1] ; Load SVC number - CMP R1,#0 + CMP R1,#0 ; Check SVC number BNE SVC_User ; Branch if not SVC 0 PUSH {R0,LR} ; Save SP and EXC_RETURN @@ -68,18 +76,42 @@ SVC_Number MOV LR,R3 ; Set EXC_RETURN SVC_Context - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run + LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.thread.run LDMIA R3!,{R1,R2} ; Load osRtxInfo.thread.run: curr & next CMP R1,R2 ; Check if thread switch is required BEQ SVC_Exit ; Branch when threads are the same + SUBS R3,R3,#8 ; Adjust address + STR R2,[R3] ; osRtxInfo.thread.run: curr = next CMP R1,#0 - BEQ SVC_ContextSwitch ; Branch if running thread is deleted + BEQ SVC_ContextRestore ; Branch if running thread is deleted SVC_ContextSave MRS R0,PSP ; Get PSP - SUBS R0,R0,#32 ; Calculate SP + SUBS R0,R0,#32 ; Calculate SP: space for R4..R11 STR R0,[R1,#TCB_SP_OFS] ; Store SP + + IF RTX_STACK_CHECK != 0 + + PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next + MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr + BL osRtxThreadStackCheck ; Check if thread stack is overrun + POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next + CMP R0,#0 + BNE SVC_ContextSaveRegs ; Branch when stack check is ok + + MOVS R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id + BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify + LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run + LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next + STR R2,[R3] ; osRtxInfo.thread.run: curr = next + B SVC_ContextRestore ; Branch to context restore handling + +SVC_ContextSaveRegs + LDR R0,[R1,#TCB_SP_OFS] ; Load SP + + ENDIF + STMIA R0!,{R4-R7} ; Save R4..R7 MOV R4,R8 MOV R5,R9 @@ -87,17 +119,6 @@ SVC_ContextSave MOV R7,R11 STMIA R0!,{R4-R7} ; Save R8..R11 -SVC_ContextSwitch - SUBS R3,R3,#8 ; Adjust address - STR R2,[R3] ; osRtxInfo.thread.run: curr = next - - IF :DEF:MPU_LOAD - PUSH {R2,R3} ; Save registers - MOV R0,R2 ; osRtxMpuLoad parameter - BL osRtxMpuLoad ; Load MPU for next thread - POP {R2,R3} ; Restore registers - ENDIF - SVC_ContextRestore LDR R0,[R2,#TCB_SP_OFS] ; Load SP ADDS R0,R0,#16 ; Adjust address @@ -110,7 +131,7 @@ SVC_ContextRestore SUBS R0,R0,#32 ; Adjust address LDMIA R0!,{R4-R7} ; Restore R4..R7 - MOVS R0,#~0xFFFFFFFD + MOVS R0,#2 ; Binary complement of 0xFFFFFFFD MVNS R0,R0 ; Set EXC_RETURN value BX R0 ; Exit from handler @@ -151,7 +172,7 @@ PendSV_Handler PROC BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler POP {R0,R1} ; Restore EXC_RETURN MOV LR,R1 ; Set EXC_RETURN - B SVC_Context + B SVC_Context ; Branch to context handling ALIGN ENDP @@ -165,7 +186,7 @@ SysTick_Handler PROC BL osRtxTick_Handler ; Call osRtxTick_Handler POP {R0,R1} ; Restore EXC_RETURN MOV LR,R1 ; Set EXC_RETURN - B SVC_Context + B SVC_Context ; Branch to context handling ALIGN ENDP diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M23/irq_armv8mbl.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M23/irq_armv8mbl.S index d8f0fc59ccc..6d932be46ba 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M23/irq_armv8mbl.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M23/irq_armv8mbl.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2016-2020 Arm Limited. All rights reserved. +; * Copyright (c) 2016-2021 Arm Limited. All rights reserved. ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -18,14 +18,18 @@ ; * ----------------------------------------------------------------------------- ; * ; * Project: CMSIS-RTOS RTX -; * Title: ARMv8M Baseline Exception handlers +; * Title: ARMv8-M Baseline Exception handlers ; * ; * ----------------------------------------------------------------------------- ; */ +#ifndef RTX_STACK_CHECK +RTX_STACK_CHECK EQU 0 +#endif + #ifndef DOMAIN_NS -DOMAIN_NS EQU 0 +DOMAIN_NS EQU 0 #endif I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset @@ -34,6 +38,9 @@ TCB_SP_OFS EQU 56 ; TCB.SP offset TCB_SF_OFS EQU 34 ; TCB.stack_frame offset TCB_TZM_OFS EQU 64 ; TCB.tz_memory offset +osRtxErrorStackOverflow\ + EQU 1 ; Stack overflow + PRESERVE8 THUMB @@ -51,13 +58,14 @@ SVC_Handler PROC EXPORT SVC_Handler IMPORT osRtxUserSVC IMPORT osRtxInfo - IF :DEF:MPU_LOAD - IMPORT osRtxMpuLoad - ENDIF - IF DOMAIN_NS = 1 + IF RTX_STACK_CHECK != 0 + IMPORT osRtxThreadStackCheck + IMPORT osRtxKernelErrorNotify + ENDIF + IF DOMAIN_NS != 0 IMPORT TZ_LoadContext_S IMPORT TZ_StoreContext_S - ENDIF + ENDIF MOV R0,LR LSRS R0,R0,#3 ; Determine return stack from EXC_RETURN bit 2 @@ -68,102 +76,137 @@ SVC_Number LDR R1,[R0,#24] ; Load saved PC from stack SUBS R1,R1,#2 ; Point to SVC instruction LDRB R1,[R1] ; Load SVC number - CMP R1,#0 + CMP R1,#0 ; Check SVC number BNE SVC_User ; Branch if not SVC 0 PUSH {R0,LR} ; Save SP and EXC_RETURN - LDM R0,{R0-R3} ; Load function parameters from stack + LDMIA R0,{R0-R3} ; Load function parameters from stack BLX R7 ; Call service function POP {R2,R3} ; Restore SP and EXC_RETURN STMIA R2!,{R0-R1} ; Store function return values MOV LR,R3 ; Set EXC_RETURN SVC_Context - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run + LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.thread.run LDMIA R3!,{R1,R2} ; Load osRtxInfo.thread.run: curr & next CMP R1,R2 ; Check if thread switch is required BEQ SVC_Exit ; Branch when threads are the same - CBZ R1,SVC_ContextSwitch ; Branch if running thread is deleted + SUBS R3,R3,#8 ; Adjust address + STR R2,[R3] ; osRtxInfo.thread.run: curr = next + CBZ R1,SVC_ContextRestore ; Branch if running thread is deleted SVC_ContextSave - IF DOMAIN_NS = 1 + IF DOMAIN_NS != 0 LDR R0,[R1,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,SVC_ContextSave1 ; Branch if there is no secure context + CBZ R0,SVC_ContextSave_NS ; Branch if there is no secure context PUSH {R1,R2,R3,R7} ; Save registers MOV R7,LR ; Get EXC_RETURN BL TZ_StoreContext_S ; Store secure context MOV LR,R7 ; Set EXC_RETURN POP {R1,R2,R3,R7} ; Restore registers - ENDIF + ENDIF -SVC_ContextSave1 +SVC_ContextSave_NS MRS R0,PSP ; Get PSP - SUBS R0,R0,#32 ; Calculate SP + IF DOMAIN_NS != 0 + MOV R3,LR ; Get EXC_RETURN + LSLS R3,R3,#25 ; Check domain of interrupted thread + BMI SVC_ContextSaveSP ; Branch if secure + ENDIF + + IF RTX_STACK_CHECK != 0 + SUBS R0,R0,#32 ; Calculate SP: space for R4..R11 + +SVC_ContextSaveSP STR R0,[R1,#TCB_SP_OFS] ; Store SP + MOV R3,LR ; Get EXC_RETURN + MOV R0,R1 ; osRtxInfo.thread.run.curr + ADDS R0,R0,#TCB_SF_OFS ; Adjust address + STRB R3,[R0] ; Store stack frame information + + PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next + MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr + BL osRtxThreadStackCheck ; Check if thread stack is overrun + POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next + CMP R0,#0 + BNE SVC_ContextSaveRegs ; Branch when stack check is ok + + MOVS R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id + BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify + LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run + LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next + STR R2,[R3] ; osRtxInfo.thread.run: curr = next + B SVC_ContextRestore ; Branch to context restore handling + +SVC_ContextSaveRegs + IF DOMAIN_NS != 0 + MOV R0,R1 ; osRtxInfo.thread.run.curr + ADDS R0,R0,#TCB_SF_OFS ; Adjust address + LDRB R3,[R0] ; Load stack frame information + LSLS R3,R3,#25 ; Check domain of interrupted thread + BMI SVC_ContextRestore ; Branch if secure + ENDIF + LDR R0,[R1,#TCB_SP_OFS] ; Load SP STMIA R0!,{R4-R7} ; Save R4..R7 MOV R4,R8 MOV R5,R9 MOV R6,R10 MOV R7,R11 STMIA R0!,{R4-R7} ; Save R8..R11 - -SVC_ContextSave2 + ELSE + SUBS R0,R0,#32 ; Calculate SP: space for R4..R11 + STMIA R0!,{R4-R7} ; Save R4..R7 + MOV R4,R8 + MOV R5,R9 + MOV R6,R10 + MOV R7,R11 + STMIA R0!,{R4-R7} ; Save R8..R11 + SUBS R0,R0,#32 ; Adjust address +SVC_ContextSaveSP + STR R0,[R1,#TCB_SP_OFS] ; Store SP MOV R0,LR ; Get EXC_RETURN ADDS R1,R1,#TCB_SF_OFS ; Adjust address STRB R0,[R1] ; Store stack frame information - -SVC_ContextSwitch - SUBS R3,R3,#8 ; Adjust address - STR R2,[R3] ; osRtxInfo.thread.run: curr = next - - IF :DEF:MPU_LOAD - PUSH {R2,R3} ; Save registers - MOV R0,R2 ; osRtxMpuLoad parameter - BL osRtxMpuLoad ; Load MPU for next thread - POP {R2,R3} ; Restore registers - ENDIF + ENDIF SVC_ContextRestore - IF DOMAIN_NS = 1 + IF DOMAIN_NS != 0 LDR R0,[R2,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,SVC_ContextRestore1 ; Branch if there is no secure context + CBZ R0,SVC_ContextRestore_NS ; Branch if there is no secure context PUSH {R2,R3} ; Save registers BL TZ_LoadContext_S ; Load secure context POP {R2,R3} ; Restore registers - ENDIF + ENDIF -SVC_ContextRestore1 - MOV R1,R2 - ADDS R1,R1,#TCB_SF_OFS ; Adjust address - LDRB R0,[R1] ; Load stack frame information - MOVS R1,#0xFF - MVNS R1,R1 ; R1=0xFFFFFF00 - ORRS R0,R1 - MOV LR,R0 ; Set EXC_RETURN - - IF DOMAIN_NS = 1 - LSLS R0,R0,#25 ; Check domain of interrupted thread - BPL SVC_ContextRestore2 ; Branch if non-secure - LDR R0,[R2,#TCB_SP_OFS] ; Load SP - MSR PSP,R0 ; Set PSP - BX LR ; Exit from handler - ELSE +SVC_ContextRestore_NS LDR R0,[R2,#TCB_SM_OFS] ; Load stack memory base MSR PSPLIM,R0 ; Set PSPLIM - ENDIF - -SVC_ContextRestore2 + MOV R0,R2 ; osRtxInfo.thread.run.next + ADDS R0,R0,#TCB_SF_OFS ; Adjust address + LDRB R3,[R0] ; Load stack frame information + MOVS R0,#0xFF + MVNS R0,R0 ; R0=0xFFFFFF00 + ORRS R3,R3,R0 + MOV LR,R3 ; Set EXC_RETURN LDR R0,[R2,#TCB_SP_OFS] ; Load SP + IF DOMAIN_NS != 0 + LSLS R3,R3,#25 ; Check domain of interrupted thread + BMI SVC_ContextRestoreSP ; Branch if secure + ENDIF + ADDS R0,R0,#16 ; Adjust address LDMIA R0!,{R4-R7} ; Restore R8..R11 MOV R8,R4 MOV R9,R5 MOV R10,R6 MOV R11,R7 - MSR PSP,R0 ; Set PSP SUBS R0,R0,#32 ; Adjust address LDMIA R0!,{R4-R7} ; Restore R4..R7 + ADDS R0,R0,#16 ; Adjust address + +SVC_ContextRestoreSP + MSR PSP,R0 ; Set PSP SVC_Exit BX LR ; Exit from handler @@ -202,7 +245,7 @@ PendSV_Handler PROC BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler POP {R0,R1} ; Restore EXC_RETURN MOV LR,R1 ; Set EXC_RETURN - B Sys_Context + B SVC_Context ; Branch to context handling ALIGN ENDP @@ -216,117 +259,7 @@ SysTick_Handler PROC BL osRtxTick_Handler ; Call osRtxTick_Handler POP {R0,R1} ; Restore EXC_RETURN MOV LR,R1 ; Set EXC_RETURN - B Sys_Context - - ALIGN - ENDP - - -Sys_Context PROC - EXPORT Sys_Context - IMPORT osRtxInfo - IF :DEF:MPU_LOAD - IMPORT osRtxMpuLoad - ENDIF - IF DOMAIN_NS = 1 - IMPORT TZ_LoadContext_S - IMPORT TZ_StoreContext_S - ENDIF - - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run - LDM R3!,{R1,R2} ; Load osRtxInfo.thread.run: curr & next - CMP R1,R2 ; Check if thread switch is required - BEQ Sys_ContextExit ; Branch when threads are the same - -Sys_ContextSave - IF DOMAIN_NS = 1 - LDR R0,[R1,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,Sys_ContextSave1 ; Branch if there is no secure context - PUSH {R1,R2,R3,R7} ; Save registers - MOV R7,LR ; Get EXC_RETURN - BL TZ_StoreContext_S ; Store secure context - MOV LR,R7 ; Set EXC_RETURN - POP {R1,R2,R3,R7} ; Restore registers - -Sys_ContextSave1 - MOV R0,LR ; Get EXC_RETURN - LSLS R0,R0,#25 ; Check domain of interrupted thread - BPL Sys_ContextSave2 ; Branch if non-secure - MRS R0,PSP ; Get PSP - STR R0,[R1,#TCB_SP_OFS] ; Store SP - B Sys_ContextSave3 - ENDIF - -Sys_ContextSave2 - MRS R0,PSP ; Get PSP - SUBS R0,R0,#32 ; Adjust address - STR R0,[R1,#TCB_SP_OFS] ; Store SP - STMIA R0!,{R4-R7} ; Save R4..R7 - MOV R4,R8 - MOV R5,R9 - MOV R6,R10 - MOV R7,R11 - STMIA R0!,{R4-R7} ; Save R8..R11 - -Sys_ContextSave3 - MOV R0,LR ; Get EXC_RETURN - ADDS R1,R1,#TCB_SF_OFS ; Adjust address - STRB R0,[R1] ; Store stack frame information - -Sys_ContextSwitch - SUBS R3,R3,#8 ; Adjust address - STR R2,[R3] ; osRtxInfo.run: curr = next - - IF :DEF:MPU_LOAD - PUSH {R2,R3} ; Save registers - MOV R0,R2 ; osRtxMpuLoad parameter - BL osRtxMpuLoad ; Load MPU for next thread - POP {R2,R3} ; Restore registers - ENDIF - -Sys_ContextRestore - IF DOMAIN_NS = 1 - LDR R0,[R2,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,Sys_ContextRestore1 ; Branch if there is no secure context - PUSH {R2,R3} ; Save registers - BL TZ_LoadContext_S ; Load secure context - POP {R2,R3} ; Restore registers - ENDIF - -Sys_ContextRestore1 - MOV R1,R2 - ADDS R1,R1,#TCB_SF_OFS ; Adjust offset - LDRB R0,[R1] ; Load stack frame information - MOVS R1,#0xFF - MVNS R1,R1 ; R1=0xFFFFFF00 - ORRS R0,R1 - MOV LR,R0 ; Set EXC_RETURN - - IF DOMAIN_NS = 1 - LSLS R0,R0,#25 ; Check domain of interrupted thread - BPL Sys_ContextRestore2 ; Branch if non-secure - LDR R0,[R2,#TCB_SP_OFS] ; Load SP - MSR PSP,R0 ; Set PSP - BX LR ; Exit from handler - ELSE - LDR R0,[R2,#TCB_SM_OFS] ; Load stack memory base - MSR PSPLIM,R0 ; Set PSPLIM - ENDIF - -Sys_ContextRestore2 - LDR R0,[R2,#TCB_SP_OFS] ; Load SP - ADDS R0,R0,#16 ; Adjust address - LDMIA R0!,{R4-R7} ; Restore R8..R11 - MOV R8,R4 - MOV R9,R5 - MOV R10,R6 - MOV R11,R7 - MSR PSP,R0 ; Set PSP - SUBS R0,R0,#32 ; Adjust address - LDMIA R0!,{R4-R7} ; Restore R4..R7 - -Sys_ContextExit - BX LR ; Exit from handler + B SVC_Context ; Branch to context handling ALIGN ENDP diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M3/irq_cm3.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M3/irq_cm3.S index 0a5ed3458a5..0c8148f978b 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M3/irq_cm3.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M3/irq_cm3.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2013-2018 Arm Limited. All rights reserved. +; * Copyright (c) 2013-2021 Arm Limited. All rights reserved. ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -18,14 +18,30 @@ ; * ----------------------------------------------------------------------------- ; * ; * Project: CMSIS-RTOS RTX -; * Title: Cortex-M3 Exception handlers +; * Title: ARMv7-M Exception handlers ; * ; * ----------------------------------------------------------------------------- ; */ +#ifndef RTX_STACK_CHECK +RTX_STACK_CHECK EQU 0 +#endif + + IF ({FPU}="FPv4-SP") +FPU_USED EQU 1 + ELSE +FPU_USED EQU 0 + ENDIF + I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset TCB_SP_OFS EQU 56 ; TCB.SP offset +TCB_SF_OFS EQU 34 ; TCB.stack_frame offset + +FPCCR EQU 0xE000EF34 ; FPCCR Address + +osRtxErrorStackOverflow\ + EQU 1 ; Stack overflow PRESERVE8 @@ -44,9 +60,10 @@ SVC_Handler PROC EXPORT SVC_Handler IMPORT osRtxUserSVC IMPORT osRtxInfo - IF :DEF:MPU_LOAD - IMPORT osRtxMpuLoad - ENDIF + IF RTX_STACK_CHECK != 0 + IMPORT osRtxThreadStackCheck + IMPORT osRtxKernelErrorNotify + ENDIF TST LR,#0x04 ; Determine return stack from EXC_RETURN bit 2 ITE EQ @@ -55,7 +72,8 @@ SVC_Handler PROC LDR R1,[R0,#24] ; Load saved PC from stack LDRB R1,[R1,#-2] ; Load SVC number - CBNZ R1,SVC_User ; Branch if not SVC 0 + CMP R1,#0 ; Check SVC number + BNE SVC_User ; Branch if not SVC 0 PUSH {R0,LR} ; Save SP and EXC_RETURN LDM R0,{R0-R3,R12} ; Load function parameters and address from stack @@ -64,35 +82,94 @@ SVC_Handler PROC STM R12,{R0-R1} ; Store function return values SVC_Context - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run + LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.thread.run LDM R3,{R1,R2} ; Load osRtxInfo.thread.run: curr & next CMP R1,R2 ; Check if thread switch is required IT EQ BXEQ LR ; Exit when threads are the same - CBZ R1,SVC_ContextSwitch ; Branch if running thread is deleted + STR R2,[R3] ; osRtxInfo.thread.run: curr = next + + IF FPU_USED != 0 + CBNZ R1,SVC_ContextSave ; Branch if running thread is not deleted +SVC_FP_LazyState + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + BNE SVC_ContextRestore ; Branch if not extended stack frame + LDR R3,=FPCCR ; FPCCR Address + LDR R0,[R3] ; Load FPCCR + BIC R0,R0,#1 ; Clear LSPACT (Lazy state preservation) + STR R0,[R3] ; Store FPCCR + B SVC_ContextRestore ; Branch to context restore handling + ELSE + CBZ R1,SVC_ContextRestore ; Branch if running thread is deleted + ENDIF SVC_ContextSave - STMDB R12!,{R4-R11} ; Save R4..R11 + IF RTX_STACK_CHECK != 0 + SUB R12,R12,#32 ; Calculate SP: space for R4..R11 + IF FPU_USED != 0 + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + SUBEQ R12,R12,#64 ; Additional space for S16..S31 + STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information + ENDIF STR R12,[R1,#TCB_SP_OFS] ; Store SP -SVC_ContextSwitch + PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next + MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr + BL osRtxThreadStackCheck ; Check if thread stack is overrun + POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next + CBNZ R0,SVC_ContextSaveRegs ; Branch when stack check is ok + + IF FPU_USED != 0 + MOV R4,R1 ; Save osRtxInfo.thread.run.curr + ENDIF + MOV R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id + BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify + LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run + LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next STR R2,[R3] ; osRtxInfo.thread.run: curr = next - - IF :DEF:MPU_LOAD - PUSH {R2,R3} ; Save registers - MOV R0,R2 ; osRtxMpuLoad parameter - BL osRtxMpuLoad ; Load MPU for next thread - POP {R2,R3} ; Restore registers - ENDIF + IF FPU_USED != 0 + LDRB LR,[R4,#TCB_SF_OFS] ; Load stack frame information + B SVC_FP_LazyState ; Branch to FP lazy state handling + ELSE + B SVC_ContextRestore ; Branch to context restore handling + ENDIF + +SVC_ContextSaveRegs + LDR R12,[R1,#TCB_SP_OFS] ; Load SP + IF FPU_USED != 0 + LDRB LR, [R1,#TCB_SF_OFS] ; Load stack frame information + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + VSTMIAEQ R12!,{S16-S31} ; Save VFP S16..S31 + ENDIF + STM R12,{R4-R11} ; Save R4..R11 + ELSE + STMDB R12!,{R4-R11} ; Save R4..R11 + IF FPU_USED != 0 + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + VSTMDBEQ R12!,{S16-S31} ; Save VFP S16.S31 + STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information + ENDIF + STR R12,[R1,#TCB_SP_OFS] ; Store SP + ENDIF SVC_ContextRestore LDR R0,[R2,#TCB_SP_OFS] ; Load SP + IF FPU_USED != 0 + LDRB R1,[R2,#TCB_SF_OFS] ; Load stack frame information + ORN LR,R1,#0xFF ; Set EXC_RETURN + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + VLDMIAEQ R0!,{S16-S31} ; Restore VFP S16..S31 + ELSE + MVN LR,#~0xFFFFFFFD ; Set EXC_RETURN value + ENDIF LDMIA R0!,{R4-R11} ; Restore R4..R11 MSR PSP,R0 ; Set PSP - MVN LR,#~0xFFFFFFFD ; Set EXC_RETURN value - SVC_Exit BX LR ; Exit from handler @@ -122,8 +199,8 @@ PendSV_Handler PROC PUSH {R0,LR} ; Save EXC_RETURN BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler POP {R0,LR} ; Restore EXC_RETURN - MRS R12,PSP - B SVC_Context + MRS R12,PSP ; Save PSP to R12 + B SVC_Context ; Branch to context handling ALIGN ENDP @@ -136,8 +213,8 @@ SysTick_Handler PROC PUSH {R0,LR} ; Save EXC_RETURN BL osRtxTick_Handler ; Call osRtxTick_Handler POP {R0,LR} ; Restore EXC_RETURN - MRS R12,PSP - B SVC_Context + MRS R12,PSP ; Save PSP to R12 + B SVC_Context ; Branch to context handling ALIGN ENDP diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M33/irq_armv8mml.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M33/irq_armv8mml.S index 3ea3a75097c..dd967edca2e 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M33/irq_armv8mml.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_M33/irq_armv8mml.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2016-2020 Arm Limited. All rights reserved. +; * Copyright (c) 2016-2021 Arm Limited. All rights reserved. ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -18,22 +18,25 @@ ; * ----------------------------------------------------------------------------- ; * ; * Project: CMSIS-RTOS RTX -; * Title: ARMv8M Mainline Exception handlers +; * Title: ARMv8-M Mainline Exception handlers ; * ; * ----------------------------------------------------------------------------- ; */ -#ifndef DOMAIN_NS -DOMAIN_NS EQU 0 +#ifndef RTX_STACK_CHECK +RTX_STACK_CHECK EQU 0 #endif -#ifdef __ARM_FP -__FPU_USED EQU 1 -#else -__FPU_USED EQU 0 +#ifndef DOMAIN_NS +DOMAIN_NS EQU 0 #endif + IF ({FPU}="FPv5-SP") || ({FPU}="FPv5_D16") +FPU_USED EQU 1 + ELSE +FPU_USED EQU 0 + ENDIF I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset TCB_SM_OFS EQU 48 ; TCB.stack_mem offset @@ -41,6 +44,11 @@ TCB_SP_OFS EQU 56 ; TCB.SP offset TCB_SF_OFS EQU 34 ; TCB.stack_frame offset TCB_TZM_OFS EQU 64 ; TCB.tz_memory offset +FPCCR EQU 0xE000EF34 ; FPCCR Address + +osRtxErrorStackOverflow\ + EQU 1 ; Stack overflow + PRESERVE8 THUMB @@ -58,13 +66,14 @@ SVC_Handler PROC EXPORT SVC_Handler IMPORT osRtxUserSVC IMPORT osRtxInfo - IF :DEF:MPU_LOAD - IMPORT osRtxMpuLoad - ENDIF - IF DOMAIN_NS = 1 + IF RTX_STACK_CHECK != 0 + IMPORT osRtxThreadStackCheck + IMPORT osRtxKernelErrorNotify + ENDIF + IF DOMAIN_NS != 0 IMPORT TZ_LoadContext_S IMPORT TZ_StoreContext_S - ENDIF + ENDIF TST LR,#0x04 ; Determine return stack from EXC_RETURN bit 2 ITE EQ @@ -73,7 +82,7 @@ SVC_Handler PROC LDR R1,[R0,#24] ; Load saved PC from stack LDRB R1,[R1,#-2] ; Load SVC number - CMP R1,#0 + CMP R1,#0 ; Check SVC number BNE SVC_User ; Branch if not SVC 0 PUSH {R0,LR} ; Save SP and EXC_RETURN @@ -83,86 +92,130 @@ SVC_Handler PROC STM R12,{R0-R1} ; Store function return values SVC_Context - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run + LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.thread.run LDM R3,{R1,R2} ; Load osRtxInfo.thread.run: curr & next CMP R1,R2 ; Check if thread switch is required IT EQ BXEQ LR ; Exit when threads are the same - IF __FPU_USED = 1 + STR R2,[R3] ; osRtxInfo.thread.run: curr = next + + IF FPU_USED != 0 CBNZ R1,SVC_ContextSave ; Branch if running thread is not deleted - TST LR,#0x10 ; Check if extended stack frame - BNE SVC_ContextSwitch - LDR R1,=0xE000EF34 ; FPCCR Address - LDR R0,[R1] ; Load FPCCR - BIC R0,R0,#1 ; Clear LSPACT (Lazy state) - STR R0,[R1] ; Store FPCCR - B SVC_ContextSwitch - ELSE - CBZ R1,SVC_ContextSwitch ; Branch if running thread is deleted - ENDIF +SVC_FP_LazyState + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + BNE SVC_ContextRestore ; Branch if not extended stack frame + LDR R3,=FPCCR ; FPCCR Address + LDR R0,[R3] ; Load FPCCR + BIC R0,R0,#1 ; Clear LSPACT (Lazy state preservation) + STR R0,[R3] ; Store FPCCR + B SVC_ContextRestore ; Branch to context restore handling + ELSE + CBZ R1,SVC_ContextRestore ; Branch if running thread is deleted + ENDIF SVC_ContextSave - IF DOMAIN_NS = 1 + IF DOMAIN_NS != 0 LDR R0,[R1,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,SVC_ContextSave1 ; Branch if there is no secure context - PUSH {R1,R2,R3,LR} ; Save registers and EXC_RETURN + CBZ R0,SVC_ContextSave_NS ; Branch if there is no secure context + PUSH {R1,R2,R12,LR} ; Save registers and EXC_RETURN BL TZ_StoreContext_S ; Store secure context - POP {R1,R2,R3,LR} ; Restore registers and EXC_RETURN - ENDIF - -SVC_ContextSave1 - MRS R0,PSP ; Get PSP - STMDB R0!,{R4-R11} ; Save R4..R11 - IF __FPU_USED = 1 - TST LR,#0x10 ; Check if extended stack frame - IT EQ - VSTMDBEQ R0!,{S16-S31} ; Save VFP S16.S31 - ENDIF - -SVC_ContextSave2 - STR R0,[R1,#TCB_SP_OFS] ; Store SP - STRB LR,[R1,#TCB_SF_OFS] ; Store stack frame information + POP {R1,R2,R12,LR} ; Restore registers and EXC_RETURN + ENDIF -SVC_ContextSwitch +SVC_ContextSave_NS + IF DOMAIN_NS != 0 + TST LR,#0x40 ; Check domain of interrupted thread + BNE SVC_ContextSaveSP ; Branch if secure + ENDIF + + IF RTX_STACK_CHECK != 0 + SUB R12,R12,#32 ; Calculate SP: space for R4..R11 + IF FPU_USED != 0 + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + SUBEQ R12,R12,#64 ; Additional space for S16..S31 + ENDIF + +SVC_ContextSaveSP + STR R12,[R1,#TCB_SP_OFS] ; Store SP + STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information + + PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next + MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr + BL osRtxThreadStackCheck ; Check if thread stack is overrun + POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next + CBNZ R0,SVC_ContextSaveRegs ; Branch when stack check is ok + + IF FPU_USED != 0 + MOV R4,R1 ; Save osRtxInfo.thread.run.curr + ENDIF + MOV R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id + BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify + LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run + LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next STR R2,[R3] ; osRtxInfo.thread.run: curr = next - - IF :DEF:MPU_LOAD - PUSH {R2,R3} ; Save registers - MOV R0,R2 ; osRtxMpuLoad parameter - BL osRtxMpuLoad ; Load MPU for next thread - POP {R2,R3} ; Restore registers - ENDIF + IF FPU_USED != 0 + LDRB LR,[R4,#TCB_SF_OFS] ; Load stack frame information + B SVC_FP_LazyState ; Branch to FP lazy state handling + ELSE + B SVC_ContextRestore ; Branch to context restore handling + ENDIF + +SVC_ContextSaveRegs + LDRB LR,[R1,#TCB_SF_OFS] ; Load stack frame information + IF DOMAIN_NS != 0 + TST LR,#0x40 ; Check domain of interrupted thread + BNE SVC_ContextRestore ; Branch if secure + ENDIF + LDR R12,[R1,#TCB_SP_OFS] ; Load SP + IF FPU_USED != 0 + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + VSTMIAEQ R12!,{S16-S31} ; Save VFP S16..S31 + ENDIF + STM R12,{R4-R11} ; Save R4..R11 + ELSE + STMDB R12!,{R4-R11} ; Save R4..R11 + IF FPU_USED != 0 + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + VSTMDBEQ R12!,{S16-S31} ; Save VFP S16.S31 + ENDIF +SVC_ContextSaveSP + STR R12,[R1,#TCB_SP_OFS] ; Store SP + STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information + ENDIF SVC_ContextRestore - IF DOMAIN_NS = 1 + IF DOMAIN_NS != 0 LDR R0,[R2,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,SVC_ContextRestore1 ; Branch if there is no secure context + CBZ R0,SVC_ContextRestore_NS; Branch if there is no secure context PUSH {R2,R3} ; Save registers BL TZ_LoadContext_S ; Load secure context POP {R2,R3} ; Restore registers - ENDIF + ENDIF -SVC_ContextRestore1 - LDR R0,[R2,#TCB_SM_OFS] ; Load stack memory base - LDRB R1,[R2,#TCB_SF_OFS] ; Load stack frame information - MSR PSPLIM,R0 ; Set PSPLIM +SVC_ContextRestore_NS LDR R0,[R2,#TCB_SP_OFS] ; Load SP - ORR LR,R1,#0xFFFFFF00 ; Set EXC_RETURN + LDR R1,[R2,#TCB_SM_OFS] ; Load stack memory base + MSR PSPLIM,R1 ; Set PSPLIM + LDRB R1,[R2,#TCB_SF_OFS] ; Load stack frame information + ORN LR,R1,#0xFF ; Set EXC_RETURN - IF DOMAIN_NS = 1 + IF DOMAIN_NS != 0 TST LR,#0x40 ; Check domain of interrupted thread - BNE SVC_ContextRestore2 ; Branch if secure - ENDIF + BNE SVC_ContextRestoreSP ; Branch if secure + ENDIF - IF __FPU_USED = 1 - TST LR,#0x10 ; Check if extended stack frame - IT EQ + IF FPU_USED != 0 + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame VLDMIAEQ R0!,{S16-S31} ; Restore VFP S16..S31 - ENDIF + ENDIF LDMIA R0!,{R4-R11} ; Restore R4..R11 -SVC_ContextRestore2 +SVC_ContextRestoreSP MSR PSP,R0 ; Set PSP SVC_Exit @@ -194,7 +247,8 @@ PendSV_Handler PROC PUSH {R0,LR} ; Save EXC_RETURN BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler POP {R0,LR} ; Restore EXC_RETURN - B Sys_Context + MRS R12,PSP ; Save PSP to R12 + B SVC_Context ; Branch to context handling ALIGN ENDP @@ -207,100 +261,8 @@ SysTick_Handler PROC PUSH {R0,LR} ; Save EXC_RETURN BL osRtxTick_Handler ; Call osRtxTick_Handler POP {R0,LR} ; Restore EXC_RETURN - B Sys_Context - - ALIGN - ENDP - - -Sys_Context PROC - EXPORT Sys_Context - IMPORT osRtxInfo - IF :DEF:MPU_LOAD - IMPORT osRtxMpuLoad - ENDIF - IF DOMAIN_NS = 1 - IMPORT TZ_LoadContext_S - IMPORT TZ_StoreContext_S - ENDIF - - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run - LDM R3,{R1,R2} ; Load osRtxInfo.thread.run: curr & next - CMP R1,R2 ; Check if thread switch is required - IT EQ - BXEQ LR ; Exit when threads are the same - -Sys_ContextSave - IF DOMAIN_NS = 1 - LDR R0,[R1,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,Sys_ContextSave1 ; Branch if there is no secure context - PUSH {R1,R2,R3,LR} ; Save registers and EXC_RETURN - BL TZ_StoreContext_S ; Store secure context - POP {R1,R2,R3,LR} ; Restore registers and EXC_RETURN - -Sys_ContextSave1 - TST LR,#0x40 ; Check domain of interrupted thread - IT NE - MRSNE R0,PSP ; Get PSP - BNE Sys_ContextSave3 ; Branch if secure - ENDIF - -Sys_ContextSave2 - MRS R0,PSP ; Get PSP - STMDB R0!,{R4-R11} ; Save R4..R11 - IF __FPU_USED = 1 - TST LR,#0x10 ; Check if extended stack frame - IT EQ - VSTMDBEQ R0!,{S16-S31} ; Save VFP S16.S31 - ENDIF - -Sys_ContextSave3 - STR R0,[R1,#TCB_SP_OFS] ; Store SP - STRB LR,[R1,#TCB_SF_OFS] ; Store stack frame information - -Sys_ContextSwitch - STR R2,[R3] ; osRtxInfo.run: curr = next - - IF :DEF:MPU_LOAD - PUSH {R2,R3} ; Save registers - MOV R0,R2 ; osRtxMpuLoad parameter - BL osRtxMpuLoad ; Load MPU for next thread - POP {R2,R3} ; Restore registers - ENDIF - -Sys_ContextRestore - IF DOMAIN_NS = 1 - LDR R0,[R2,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,Sys_ContextRestore1 ; Branch if there is no secure context - PUSH {R2,R3} ; Save registers - BL TZ_LoadContext_S ; Load secure context - POP {R2,R3} ; Restore registers - ENDIF - -Sys_ContextRestore1 - LDR R0,[R2,#TCB_SM_OFS] ; Load stack memory base - LDRB R1,[R2,#TCB_SF_OFS] ; Load stack frame information - MSR PSPLIM,R0 ; Set PSPLIM - LDR R0,[R2,#TCB_SP_OFS] ; Load SP - ORR LR,R1,#0xFFFFFF00 ; Set EXC_RETURN - - IF DOMAIN_NS = 1 - TST LR,#0x40 ; Check domain of interrupted thread - BNE Sys_ContextRestore2 ; Branch if secure - ENDIF - - IF __FPU_USED = 1 - TST LR,#0x10 ; Check if extended stack frame - IT EQ - VLDMIAEQ R0!,{S16-S31} ; Restore VFP S16..S31 - ENDIF - LDMIA R0!,{R4-R11} ; Restore R4..R11 - -Sys_ContextRestore2 - MSR PSP,R0 ; Set PSP - -Sys_ContextExit - BX LR ; Exit from handler + MRS R12,PSP ; Save PSP to R12 + B SVC_Context ; Branch to context handling ALIGN ENDP diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_RTOS_M4_M7/irq_cm4f.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_RTOS_M4_M7/irq_cm4f.S index 803c7c378c0..4905a35b73b 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_RTOS_M4_M7/irq_cm4f.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_ARM/TARGET_RTOS_M4_M7/irq_cm4f.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2013-2018 Arm Limited. All rights reserved. +; * Copyright (c) 2013-2021 Arm Limited. All rights reserved. ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -18,16 +18,31 @@ ; * ----------------------------------------------------------------------------- ; * ; * Project: CMSIS-RTOS RTX -; * Title: Cortex-M4F Exception handlers +; * Title: ARMv7-M Exception handlers ; * ; * ----------------------------------------------------------------------------- ; */ +#ifndef RTX_STACK_CHECK +RTX_STACK_CHECK EQU 0 +#endif + + IF ({FPU}="FPv4-SP") || ({FPU}="VFPv4_SP_D16") || ({FPU}="FPv5-SP") || ({FPU}="FPv5_D16") +FPU_USED EQU 1 + ELSE +FPU_USED EQU 0 + ENDIF + I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset TCB_SP_OFS EQU 56 ; TCB.SP offset TCB_SF_OFS EQU 34 ; TCB.stack_frame offset +FPCCR EQU 0xE000EF34 ; FPCCR Address + +osRtxErrorStackOverflow\ + EQU 1 ; Stack overflow + PRESERVE8 THUMB @@ -45,9 +60,10 @@ SVC_Handler PROC EXPORT SVC_Handler IMPORT osRtxUserSVC IMPORT osRtxInfo - IF :DEF:MPU_LOAD - IMPORT osRtxMpuLoad - ENDIF + IF RTX_STACK_CHECK != 0 + IMPORT osRtxThreadStackCheck + IMPORT osRtxKernelErrorNotify + ENDIF TST LR,#0x04 ; Determine return stack from EXC_RETURN bit 2 ITE EQ @@ -56,7 +72,8 @@ SVC_Handler PROC LDR R1,[R0,#24] ; Load saved PC from stack LDRB R1,[R1,#-2] ; Load SVC number - CBNZ R1,SVC_User ; Branch if not SVC 0 + CMP R1,#0 ; Check SVC number + BNE SVC_User ; Branch if not SVC 0 PUSH {R0,LR} ; Save SP and EXC_RETURN LDM R0,{R0-R3,R12} ; Load function parameters and address from stack @@ -65,54 +82,91 @@ SVC_Handler PROC STM R12,{R0-R1} ; Store function return values SVC_Context - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run + LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.thread.run LDM R3,{R1,R2} ; Load osRtxInfo.thread.run: curr & next CMP R1,R2 ; Check if thread switch is required IT EQ BXEQ LR ; Exit when threads are the same + STR R2,[R3] ; osRtxInfo.thread.run: curr = next + + IF FPU_USED != 0 CBNZ R1,SVC_ContextSave ; Branch if running thread is not deleted - TST LR,#0x10 ; Check if extended stack frame - BNE SVC_ContextSwitch -#ifdef __FPU_PRESENT - LDR R1,=0xE000EF34 ; FPCCR Address - LDR R0,[R1] ; Load FPCCR - BIC R0,R0,#1 ; Clear LSPACT (Lazy state) - STR R0,[R1] ; Store FPCCR - B SVC_ContextSwitch -#endif +SVC_FP_LazyState + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + BNE SVC_ContextRestore ; Branch if not extended stack frame + LDR R3,=FPCCR ; FPCCR Address + LDR R0,[R3] ; Load FPCCR + BIC R0,R0,#1 ; Clear LSPACT (Lazy state preservation) + STR R0,[R3] ; Store FPCCR + B SVC_ContextRestore ; Branch to context restore handling + ELSE + CBZ R1,SVC_ContextRestore ; Branch if running thread is deleted + ENDIF SVC_ContextSave - STMDB R12!,{R4-R11} ; Save R4..R11 -#ifdef __FPU_PRESENT - TST LR,#0x10 ; Check if extended stack frame - IT EQ - VSTMDBEQ R12!,{S16-S31} ; Save VFP S16.S31 -#endif - - STR R12,[R1,#TCB_SP_OFS] ; Store SP + IF RTX_STACK_CHECK != 0 + SUB R12,R12,#32 ; Calculate SP: space for R4..R11 + IF FPU_USED != 0 + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + SUBEQ R12,R12,#64 ; Additional space for S16..S31 STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information + ENDIF + STR R12,[R1,#TCB_SP_OFS] ; Store SP -SVC_ContextSwitch + PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next + MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr + BL osRtxThreadStackCheck ; Check if thread stack is overrun + POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next + CBNZ R0,SVC_ContextSaveRegs ; Branch when stack check is ok + + IF FPU_USED != 0 + MOV R4,R1 ; Save osRtxInfo.thread.run.curr + ENDIF + MOV R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id + BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify + LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run + LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next STR R2,[R3] ; osRtxInfo.thread.run: curr = next - - IF :DEF:MPU_LOAD - PUSH {R2,R3} ; Save registers - MOV R0,R2 ; osRtxMpuLoad parameter - BL osRtxMpuLoad ; Load MPU for next thread - POP {R2,R3} ; Restore registers - ENDIF + IF FPU_USED != 0 + LDRB LR,[R4,#TCB_SF_OFS] ; Load stack frame information + B SVC_FP_LazyState ; Branch to FP lazy state handling + ELSE + B SVC_ContextRestore ; Branch to context restore handling + ENDIF + +SVC_ContextSaveRegs + LDR R12,[R1,#TCB_SP_OFS] ; Load SP + IF FPU_USED != 0 + LDRB LR, [R1,#TCB_SF_OFS] ; Load stack frame information + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + VSTMIAEQ R12!,{S16-S31} ; Save VFP S16..S31 + ENDIF + STM R12,{R4-R11} ; Save R4..R11 + ELSE + STMDB R12!,{R4-R11} ; Save R4..R11 + IF FPU_USED != 0 + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + VSTMDBEQ R12!,{S16-S31} ; Save VFP S16.S31 + STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information + ENDIF + STR R12,[R1,#TCB_SP_OFS] ; Store SP + ENDIF SVC_ContextRestore - LDRB R1,[R2,#TCB_SF_OFS] ; Load stack frame information LDR R0,[R2,#TCB_SP_OFS] ; Load SP - ORR LR,R1,#0xFFFFFF00 ; Set EXC_RETURN - -#ifdef __FPU_PRESENT - TST LR,#0x10 ; Check if extended stack frame - IT EQ + IF FPU_USED != 0 + LDRB R1,[R2,#TCB_SF_OFS] ; Load stack frame information + ORN LR,R1,#0xFF ; Set EXC_RETURN + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame VLDMIAEQ R0!,{S16-S31} ; Restore VFP S16..S31 -#endif + ELSE + MVN LR,#~0xFFFFFFFD ; Set EXC_RETURN value + ENDIF LDMIA R0!,{R4-R11} ; Restore R4..R11 MSR PSP,R0 ; Set PSP @@ -145,8 +199,8 @@ PendSV_Handler PROC PUSH {R0,LR} ; Save EXC_RETURN BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler POP {R0,LR} ; Restore EXC_RETURN - MRS R12,PSP - B SVC_Context + MRS R12,PSP ; Save PSP to R12 + B SVC_Context ; Branch to context handling ALIGN ENDP @@ -159,8 +213,8 @@ SysTick_Handler PROC PUSH {R0,LR} ; Save EXC_RETURN BL osRtxTick_Handler ; Call osRtxTick_Handler POP {R0,LR} ; Restore EXC_RETURN - MRS R12,PSP - B SVC_Context + MRS R12,PSP ; Save PSP to R12 + B SVC_Context ; Branch to context handling ALIGN ENDP diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_CORTEX_A/irq_ca.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_CORTEX_A/irq_ca.S index 0db8a995570..9d5f44af8c9 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_CORTEX_A/irq_ca.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_CORTEX_A/irq_ca.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -18,7 +18,7 @@ * ----------------------------------------------------------------------------- * * Project: CMSIS-RTOS RTX - * Title: Cortex-A Exception handlers + * Title: ARMv7-A Exception handlers * * ----------------------------------------------------------------------------- */ @@ -64,48 +64,48 @@ IRQ_PendSV: .cantunwind Undef_Handler: - SRSFD SP!, #MODE_UND - PUSH {R0-R4, R12} // Save APCS corruptible registers to UND mode stack + srsfd sp!, #MODE_UND + push {r0-r4, r12} // Save APCS corruptible registers to UND mode stack - MRS R0, SPSR - TST R0, #CPSR_BIT_T // Check mode - MOVEQ R1, #4 // R1 = 4 ARM mode - MOVNE R1, #2 // R1 = 2 Thumb mode - SUB R0, LR, R1 - LDREQ R0, [R0] // ARM mode - R0 points to offending instruction - BEQ Undef_Cont + mrs r0, spsr + tst r0, #CPSR_BIT_T // Check mode + moveq r1, #4 // R1 = 4 ARM mode + movne r1, #2 // R1 = 2 Thumb mode + sub r0, lr, r1 + ldreq r0, [r0] // ARM mode - R0 points to offending instruction + beq Undef_Cont // Thumb instruction // Determine if it is a 32-bit Thumb instruction - LDRH R0, [R0] - MOV R2, #0x1C - CMP R2, R0, LSR #11 - BHS Undef_Cont // 16-bit Thumb instruction + ldrh r0, [r0] + mov r2, #0x1C + cmp r2, r0, lsr #11 + bhs Undef_Cont // 16-bit Thumb instruction // 32-bit Thumb instruction. Unaligned - reconstruct the offending instruction - LDRH R2, [LR] - ORR R0, R2, R0, LSL #16 + ldrh r2, [lr] + orr r0, r2, r0, lsl #16 Undef_Cont: - MOV R2, LR // Set LR to third argument + mov r2, lr // Set LR to third argument - AND R12, SP, #4 // Ensure stack is 8-byte aligned - SUB SP, SP, R12 // Adjust stack - PUSH {R12, LR} // Store stack adjustment and dummy LR + and r12, sp, #4 // Ensure stack is 8-byte aligned + sub sp, sp, r12 // Adjust stack + push {r12, lr} // Store stack adjustment and dummy LR // R0 =Offending instruction, R1 =2(Thumb) or =4(ARM) - BL CUndefHandler + bl CUndefHandler - POP {R12, LR} // Get stack adjustment & discard dummy LR - ADD SP, SP, R12 // Unadjust stack + pop {r12, lr} // Get stack adjustment & discard dummy LR + add sp, sp, r12 // Unadjust stack - LDR LR, [SP, #24] // Restore stacked LR and possibly adjust for retry - SUB LR, LR, R0 - LDR R0, [SP, #28] // Restore stacked SPSR - MSR SPSR_cxsf, R0 - CLREX // Clear exclusive monitor - POP {R0-R4, R12} // Restore stacked APCS registers - ADD SP, SP, #8 // Adjust SP for already-restored banked registers - MOVS PC, LR + ldr lr, [sp, #24] // Restore stacked LR and possibly adjust for retry + sub lr, lr, r0 + ldr r0, [sp, #28] // Restore stacked SPSR + msr spsr_cxsf, r0 + clrex // Clear exclusive monitor + pop {r0-r4, r12} // Restore stacked APCS registers + add sp, sp, #8 // Adjust SP for already-restored banked registers + movs pc, lr .fnend .size Undef_Handler, .-Undef_Handler @@ -117,26 +117,26 @@ Undef_Cont: .cantunwind PAbt_Handler: - SUB LR, LR, #4 // Pre-adjust LR - SRSFD SP!, #MODE_ABT // Save LR and SPRS to ABT mode stack - PUSH {R0-R4, R12} // Save APCS corruptible registers to ABT mode stack - MRC p15, 0, R0, c5, c0, 1 // IFSR - MRC p15, 0, R1, c6, c0, 2 // IFAR + sub lr, lr, #4 // Pre-adjust LR + srsfd sp!, #MODE_ABT // Save LR and SPRS to ABT mode stack + push {r0-r4, r12} // Save APCS corruptible registers to ABT mode stack + mrc p15, 0, r0, c5, c0, 1 // IFSR + mrc p15, 0, r1, c6, c0, 2 // IFAR - MOV R2, LR // Set LR to third argument + mov r2, lr // Set LR to third argument - AND R12, SP, #4 // Ensure stack is 8-byte aligned - SUB SP, SP, R12 // Adjust stack - PUSH {R12, LR} // Store stack adjustment and dummy LR + and r12, sp, #4 // Ensure stack is 8-byte aligned + sub sp, sp, r12 // Adjust stack + push {r12, lr} // Store stack adjustment and dummy LR - BL CPAbtHandler + bl CPAbtHandler - POP {R12, LR} // Get stack adjustment & discard dummy LR - ADD SP, SP, R12 // Unadjust stack + pop {r12, lr} // Get stack adjustment & discard dummy LR + add sp, sp, r12 // Unadjust stack - CLREX // Clear exclusive monitor - POP {R0-R4, R12} // Restore stack APCS registers - RFEFD SP! // Return from exception + clrex // Clear exclusive monitor + pop {r0-r4, r12} // Restore stack APCS registers + rfefd sp! // Return from exception .fnend .size PAbt_Handler, .-PAbt_Handler @@ -147,26 +147,26 @@ PAbt_Handler: .fnstart .cantunwind DAbt_Handler: - SUB LR, LR, #8 // Pre-adjust LR - SRSFD SP!, #MODE_ABT // Save LR and SPRS to ABT mode stack - PUSH {R0-R4, R12} // Save APCS corruptible registers to ABT mode stack - MRC p15, 0, R0, c5, c0, 0 // DFSR - MRC p15, 0, R1, c6, c0, 0 // DFAR + sub lr, lr, #8 // Pre-adjust LR + srsfd sp!, #MODE_ABT // Save LR and SPRS to ABT mode stack + push {r0-r4, r12} // Save APCS corruptible registers to ABT mode stack + mrc p15, 0, r0, c5, c0, 0 // DFSR + mrc p15, 0, r1, c6, c0, 0 // DFAR - MOV R2, LR // Set LR to third argument + mov r2, lr // Set LR to third argument - AND R12, SP, #4 // Ensure stack is 8-byte aligned - SUB SP, SP, R12 // Adjust stack - PUSH {R12, LR} // Store stack adjustment and dummy LR + and r12, sp, #4 // Ensure stack is 8-byte aligned + sub sp, sp, r12 // Adjust stack + push {r12, lr} // Store stack adjustment and dummy LR - BL CDAbtHandler + bl CDAbtHandler - POP {R12, LR} // Get stack adjustment & discard dummy LR - ADD SP, SP, R12 // Unadjust stack + pop {r12, lr} // Get stack adjustment & discard dummy LR + add sp, sp, r12 // Unadjust stack - CLREX // Clear exclusive monitor - POP {R0-R4, R12} // Restore stacked APCS registers - RFEFD SP! // Return from exception + clrex // Clear exclusive monitor + pop {r0-r4, r12} // Restore stacked APCS registers + rfefd sp! // Return from exception .fnend .size DAbt_Handler, .-DAbt_Handler @@ -178,49 +178,49 @@ DAbt_Handler: .cantunwind IRQ_Handler: - SUB LR, LR, #4 // Pre-adjust LR - SRSFD SP!, #MODE_SVC // Save LR_irq and SPSR_irq on to the SVC stack - CPS #MODE_SVC // Change to SVC mode - PUSH {R0-R3, R12, LR} // Save APCS corruptible registers + sub lr, lr, #4 // Pre-adjust LR + srsfd sp!, #MODE_SVC // Save LR_irq and SPSR_irq on to the SVC stack + cps #MODE_SVC // Change to SVC mode + push {r0-r3, r12, lr} // Save APCS corruptible registers - LDR R0, =IRQ_NestLevel - LDR R1, [R0] - ADD R1, R1, #1 // Increment IRQ nesting level - STR R1, [R0] + ldr r0, =IRQ_NestLevel + ldr r1, [r0] + add r1, r1, #1 // Increment IRQ nesting level + str r1, [r0] - MOV R3, SP // Move SP into R3 - AND R3, R3, #4 // Get stack adjustment to ensure 8-byte alignment - SUB SP, SP, R3 // Adjust stack - PUSH {R3, R4} // Store stack adjustment(R3) and user data(R4) + mov r3, sp // Move SP into R3 + and r3, r3, #4 // Get stack adjustment to ensure 8-byte alignment + sub sp, sp, r3 // Adjust stack + push {r3, r4} // Store stack adjustment(R3) and user data(R4) - BLX IRQ_GetActiveIRQ // Retrieve interrupt ID into R0 - MOV R4, R0 // Move interrupt ID to R4 + blx IRQ_GetActiveIRQ // Retrieve interrupt ID into R0 + mov r4, r0 // Move interrupt ID to R4 - BLX IRQ_GetHandler // Retrieve interrupt handler address for current ID - CMP R0, #0 // Check if handler address is 0 - BEQ IRQ_End // If 0, end interrupt and return + blx IRQ_GetHandler // Retrieve interrupt handler address for current ID + cmp r0, #0 // Check if handler address is 0 + beq IRQ_End // If 0, end interrupt and return - CPSIE i // Re-enable interrupts - BLX R0 // Call IRQ handler - CPSID i // Disable interrupts + cpsie i // Re-enable interrupts + blx r0 // Call IRQ handler + cpsid i // Disable interrupts IRQ_End: - MOV R0, R4 // Move interrupt ID to R0 - BLX IRQ_EndOfInterrupt // Signal end of interrupt + mov r0, r4 // Move interrupt ID to R0 + blx IRQ_EndOfInterrupt // Signal end of interrupt - POP {R3, R4} // Restore stack adjustment(R3) and user data(R4) - ADD SP, SP, R3 // Unadjust stack + pop {r3, r4} // Restore stack adjustment(R3) and user data(R4) + add sp, sp, r3 // Unadjust stack - BL osRtxContextSwitch // Continue in context switcher + bl osRtxContextSwitch // Continue in context switcher - LDR R0, =IRQ_NestLevel - LDR R1, [R0] - SUBS R1, R1, #1 // Decrement IRQ nesting level - STR R1, [R0] + ldr r0, =IRQ_NestLevel + ldr r1, [r0] + subs r1, r1, #1 // Decrement IRQ nesting level + str r1, [r0] - CLREX // Clear exclusive monitor for interrupted code - POP {R0-R3, R12, LR} // Restore stacked APCS registers - RFEFD SP! // Return from IRQ handler + clrex // Clear exclusive monitor for interrupted code + pop {r0-r3, r12, lr} // Restore stacked APCS registers + rfefd sp! // Return from IRQ handler .fnend .size IRQ_Handler, .-IRQ_Handler @@ -232,80 +232,80 @@ IRQ_End: .cantunwind SVC_Handler: - SRSFD SP!, #MODE_SVC // Store SPSR_svc and LR_svc onto SVC stack - PUSH {R12, LR} - - MRS R12, SPSR // Load SPSR - TST R12, #CPSR_BIT_T // Thumb bit set? - LDRHNE R12, [LR,#-2] // Thumb: load halfword - BICNE R12, R12, #0xFF00 // extract SVC number - LDREQ R12, [LR,#-4] // ARM: load word - BICEQ R12, R12, #0xFF000000 // extract SVC number - CMP R12, #0 // Compare SVC number - BNE SVC_User // Branch if User SVC - - PUSH {R0-R3} - - LDR R0, =IRQ_NestLevel - LDR R1, [R0] - ADD R1, R1, #1 // Increment IRQ nesting level - STR R1, [R0] - - LDR R0, =osRtxInfo - LDR R1, [R0, #I_K_STATE_OFS] // Load RTX5 kernel state - CMP R1, #K_STATE_RUNNING // Check osKernelRunning - BLT SVC_FuncCall // Continue if kernel is not running - LDR R0, [R0, #I_TICK_IRQN_OFS] // Load OS Tick irqn - BLX IRQ_Disable // Disable OS Tick interrupt + srsfd sp!, #MODE_SVC // Store SPSR_svc and LR_svc onto SVC stack + push {r12, lr} + + mrs r12, spsr // Load SPSR + tst r12, #CPSR_BIT_T // Thumb bit set? + ldrhne r12, [lr,#-2] // Thumb: load halfword + bicne r12, r12, #0xFF00 // extract SVC number + ldreq r12, [lr,#-4] // ARM: load word + biceq r12, r12, #0xFF000000 // extract SVC number + cmp r12, #0 // Compare SVC number + bne SVC_User // Branch if User SVC + + push {r0-r3} + + ldr r0, =IRQ_NestLevel + ldr r1, [r0] + add r1, r1, #1 // Increment IRQ nesting level + str r1, [r0] + + ldr r0, =osRtxInfo + ldr r1, [r0, #I_K_STATE_OFS] // Load RTX5 kernel state + cmp r1, #K_STATE_RUNNING // Check osKernelRunning + blt SVC_FuncCall // Continue if kernel is not running + ldr r0, [r0, #I_TICK_IRQN_OFS] // Load OS Tick irqn + blx IRQ_Disable // Disable OS Tick interrupt SVC_FuncCall: - POP {R0-R3} + pop {r0-r3} - LDR R12, [SP] // Reload R12 from stack + ldr r12, [sp] // Reload R12 from stack - CPSIE i // Re-enable interrupts - BLX R12 // Branch to SVC function - CPSID i // Disable interrupts + cpsie i // Re-enable interrupts + blx r12 // Branch to SVC function + cpsid i // Disable interrupts - SUB SP, SP, #4 - STM SP, {SP}^ // Store SP_usr onto stack - POP {R12} // Pop SP_usr into R12 - SUB R12, R12, #16 // Adjust pointer to SP_usr - LDMDB R12, {R2,R3} // Load return values from SVC function - PUSH {R0-R3} // Push return values to stack + sub sp, sp, #4 + stm sp, {sp}^ // Store SP_usr onto stack + pop {r12} // Pop SP_usr into R12 + sub r12, r12, #16 // Adjust pointer to SP_usr + ldmdb r12, {r2,r3} // Load return values from SVC function + push {r0-r3} // Push return values to stack - LDR R0, =osRtxInfo - LDR R1, [R0, #I_K_STATE_OFS] // Load RTX5 kernel state - CMP R1, #K_STATE_RUNNING // Check osKernelRunning - BLT SVC_ContextCheck // Continue if kernel is not running - LDR R0, [R0, #I_TICK_IRQN_OFS] // Load OS Tick irqn - BLX IRQ_Enable // Enable OS Tick interrupt + ldr r0, =osRtxInfo + ldr r1, [r0, #I_K_STATE_OFS] // Load RTX5 kernel state + cmp r1, #K_STATE_RUNNING // Check osKernelRunning + blt SVC_ContextCheck // Continue if kernel is not running + ldr r0, [r0, #I_TICK_IRQN_OFS] // Load OS Tick irqn + blx IRQ_Enable // Enable OS Tick interrupt SVC_ContextCheck: - BL osRtxContextSwitch // Continue in context switcher + bl osRtxContextSwitch // Continue in context switcher - LDR R0, =IRQ_NestLevel - LDR R1, [R0] - SUB R1, R1, #1 // Decrement IRQ nesting level - STR R1, [R0] + ldr r0, =IRQ_NestLevel + ldr r1, [r0] + sub r1, r1, #1 // Decrement IRQ nesting level + str r1, [r0] - CLREX // Clear exclusive monitor - POP {R0-R3, R12, LR} // Restore stacked APCS registers - RFEFD SP! // Return from exception + clrex // Clear exclusive monitor + pop {r0-r3, r12, lr} // Restore stacked APCS registers + rfefd sp! // Return from exception SVC_User: - PUSH {R4, R5} - LDR R5,=osRtxUserSVC // Load address of SVC table - LDR R4,[R5] // Load SVC maximum number - CMP R12,R4 // Check SVC number range - BHI SVC_Done // Branch if out of range + push {r4, r5} + ldr r5,=osRtxUserSVC // Load address of SVC table + ldr r4,[r5] // Load SVC maximum number + cmp r12,r4 // Check SVC number range + bhi SVC_Done // Branch if out of range - LDR R12,[R5,R12,LSL #2] // Load SVC Function Address - BLX R12 // Call SVC Function + ldr r12,[r5,r12,lsl #2] // Load SVC Function Address + blx r12 // Call SVC Function SVC_Done: - CLREX // Clear exclusive monitor - POP {R4, R5, R12, LR} - RFEFD SP! // Return from exception + clrex // Clear exclusive monitor + pop {r4, r5, r12, lr} + rfefd sp! // Return from exception .fnend .size SVC_Handler, .-SVC_Handler @@ -317,146 +317,146 @@ SVC_Done: .cantunwind osRtxContextSwitch: - PUSH {LR} + push {lr} // Check interrupt nesting level - LDR R0, =IRQ_NestLevel - LDR R1, [R0] // Load IRQ nest level - CMP R1, #1 - BNE osRtxContextExit // Nesting interrupts, exit context switcher + ldr r0, =IRQ_NestLevel + ldr r1, [r0] // Load IRQ nest level + cmp r1, #1 + bne osRtxContextExit // Nesting interrupts, exit context switcher - LDR R12, =osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run - LDM R12, {R0, R1} // Load osRtxInfo.thread.run: curr & next - LDR R2, =IRQ_PendSV // Load address of IRQ_PendSV flag - LDRB R3, [R2] // Load PendSV flag + ldr r12, =osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run + ldm r12, {r0, r1} // Load osRtxInfo.thread.run: curr & next + ldr r2, =IRQ_PendSV // Load address of IRQ_PendSV flag + ldrb r3, [r2] // Load PendSV flag - CMP R0, R1 // Check if context switch is required - BNE osRtxContextCheck // Not equal, check if context save required - CMP R3, #1 // Compare IRQ_PendSV value - BNE osRtxContextExit // No post processing (and no context switch requested) + cmp r0, r1 // Check if context switch is required + bne osRtxContextCheck // Not equal, check if context save required + cmp r3, #1 // Compare IRQ_PendSV value + bne osRtxContextExit // No post processing (and no context switch requested) osRtxContextCheck: - STR R1, [R12] // Store run.next as run.curr + str r1, [r12] // Store run.next as run.curr // R0 = curr, R1 = next, R2 = &IRQ_PendSV, R3 = IRQ_PendSV, R12 = &osRtxInfo.thread.run - PUSH {R1-R3, R12} + push {r1-r3, r12} - CMP R0, #0 // Is osRtxInfo.thread.run.curr == 0 - BEQ osRtxPostProcess // Current deleted, skip context save + cmp r0, #0 // Is osRtxInfo.thread.run.curr == 0 + beq osRtxPostProcess // Current deleted, skip context save osRtxContextSave: - MOV LR, R0 // Move &osRtxInfo.thread.run.curr to LR - MOV R0, SP // Move SP_svc into R0 - ADD R0, R0, #20 // Adjust SP_svc to R0 of the basic frame - SUB SP, SP, #4 - STM SP, {SP}^ // Save SP_usr to current stack - POP {R1} // Pop SP_usr into R1 - - SUB R1, R1, #64 // Adjust SP_usr to R4 of the basic frame - STMIA R1!, {R4-R11} // Save R4-R11 to user stack - LDMIA R0!, {R4-R8} // Load stacked R0-R3,R12 into R4-R8 - STMIA R1!, {R4-R8} // Store them to user stack - STM R1, {LR}^ // Store LR_usr directly - ADD R1, R1, #4 // Adjust user sp to PC - LDMIB R0!, {R5-R6} // Load current PC, CPSR - STMIA R1!, {R5-R6} // Restore user PC and CPSR - - SUB R1, R1, #64 // Adjust SP_usr to stacked R4 + mov lr, r0 // Move &osRtxInfo.thread.run.curr to LR + mov r0, sp // Move SP_svc into R0 + add r0, r0, #20 // Adjust SP_svc to R0 of the basic frame + sub sp, sp, #4 + stm sp, {sp}^ // Save SP_usr to current stack + pop {r1} // Pop SP_usr into R1 + + sub r1, r1, #64 // Adjust SP_usr to R4 of the basic frame + stmia r1!, {r4-r11} // Save R4-R11 to user stack + ldmia r0!, {r4-r8} // Load stacked R0-R3,R12 into R4-R8 + stmia r1!, {r4-r8} // Store them to user stack + stm r1, {lr}^ // Store LR_usr directly + add r1, r1, #4 // Adjust user sp to PC + ldmib r0!, {r5-r6} // Load current PC, CPSR + stmia r1!, {r5-r6} // Restore user PC and CPSR + + sub r1, r1, #64 // Adjust SP_usr to stacked R4 // Check if VFP state need to be saved - MRC p15, 0, R2, c1, c0, 2 // VFP/NEON access enabled? (CPACR) - AND R2, R2, #0x00F00000 - CMP R2, #0x00F00000 - BNE osRtxContextSave1 // Continue, no VFP - - VMRS R2, FPSCR - STMDB R1!, {R2,R12} // Push FPSCR, maintain 8-byte alignment - - VSTMDB R1!, {D0-D15} // Save D0-D15 - #if __ARM_NEON == 1 - VSTMDB R1!, {D16-D31} // Save D16-D31 - #endif - - LDRB R2, [LR, #TCB_SP_FRAME] // Load osRtxInfo.thread.run.curr frame info - #if __ARM_NEON == 1 - ORR R2, R2, #4 // NEON state - #else - ORR R2, R2, #2 // VFP state - #endif - STRB R2, [LR, #TCB_SP_FRAME] // Store VFP/NEON state - -osRtxContextSave1: - STR R1, [LR, #TCB_SP_OFS] // Store user sp to osRtxInfo.thread.run.curr + mrc p15, 0, r2, c1, c0, 2 // VFP/NEON access enabled? (CPACR) + and r2, r2, #0x00F00000 + cmp r2, #0x00F00000 + bne osRtxContextSaveSP // Continue, no VFP + + vmrs r2, fpscr + stmdb r1!, {r2,r12} // Push FPSCR, maintain 8-byte alignment + + vstmdb r1!, {d0-d15} // Save D0-D15 + #if defined(__ARM_NEON) && (__ARM_NEON == 1) + vstmdb r1!, {d16-d31} // Save D16-D31 + #endif + + ldrb r2, [lr, #TCB_SP_FRAME] // Load osRtxInfo.thread.run.curr frame info + #if defined(__ARM_NEON) && (__ARM_NEON == 1) + orr r2, r2, #4 // NEON state + #else + orr r2, r2, #2 // VFP state + #endif + strb r2, [lr, #TCB_SP_FRAME] // Store VFP/NEON state + +osRtxContextSaveSP: + str r1, [lr, #TCB_SP_OFS] // Store user sp to osRtxInfo.thread.run.curr osRtxPostProcess: // RTX IRQ post processing check - POP {R8-R11} // Pop R8 = run.next, R9 = &IRQ_PendSV, R10 = IRQ_PendSV, R11 = &osRtxInfo.thread.run - CMP R10, #1 // Compare PendSV value - BNE osRtxContextRestore // Skip post processing if not pending + pop {r8-r11} // Pop R8 = run.next, R9 = &IRQ_PendSV, R10 = IRQ_PendSV, R11 = &osRtxInfo.thread.run + cmp r10, #1 // Compare PendSV value + bne osRtxContextRestore // Skip post processing if not pending - MOV R4, SP // Move SP_svc into R4 - AND R4, R4, #4 // Get stack adjustment to ensure 8-byte alignment - SUB SP, SP, R4 // Adjust stack + mov r4, sp // Move SP_svc into R4 + and r4, r4, #4 // Get stack adjustment to ensure 8-byte alignment + sub sp, sp, r4 // Adjust stack // Disable OS Tick - LDR R5, =osRtxInfo // Load address of osRtxInfo - LDR R5, [R5, #I_TICK_IRQN_OFS] // Load OS Tick irqn - MOV R0, R5 // Set it as function parameter - BLX IRQ_Disable // Disable OS Tick interrupt - MOV R6, #0 // Set PendSV clear value - B osRtxPendCheck + ldr r5, =osRtxInfo // Load address of osRtxInfo + ldr r5, [r5, #I_TICK_IRQN_OFS] // Load OS Tick irqn + mov r0, r5 // Set it as function parameter + blx IRQ_Disable // Disable OS Tick interrupt + mov r6, #0 // Set PendSV clear value + b osRtxPendCheck osRtxPendExec: - STRB R6, [R9] // Clear PendSV flag - CPSIE i // Re-enable interrupts - BLX osRtxPendSV_Handler // Post process pending objects - CPSID i // Disable interrupts + strb r6, [r9] // Clear PendSV flag + cpsie i // Re-enable interrupts + blx osRtxPendSV_Handler // Post process pending objects + cpsid i // Disable interrupts osRtxPendCheck: - LDR R8, [R11, #4] // Load osRtxInfo.thread.run.next - STR R8, [R11] // Store run.next as run.curr - LDRB R0, [R9] // Load PendSV flag - CMP R0, #1 // Compare PendSV value - BEQ osRtxPendExec // Branch to PendExec if PendSV is set + ldr r8, [r11, #4] // Load osRtxInfo.thread.run.next + str r8, [r11] // Store run.next as run.curr + ldrb r0, [r9] // Load PendSV flag + cmp r0, #1 // Compare PendSV value + beq osRtxPendExec // Branch to PendExec if PendSV is set // Re-enable OS Tick - MOV R0, R5 // Restore irqn as function parameter - BLX IRQ_Enable // Enable OS Tick interrupt + mov r0, r5 // Restore irqn as function parameter + blx IRQ_Enable // Enable OS Tick interrupt - ADD SP, SP, R4 // Restore stack adjustment + add sp, sp, r4 // Restore stack adjustment osRtxContextRestore: - LDR LR, [R8, #TCB_SP_OFS] // Load next osRtxThread_t.sp - LDRB R2, [R8, #TCB_SP_FRAME] // Load next osRtxThread_t.stack_frame - - ANDS R2, R2, #0x6 // Check stack frame for VFP context - MRC p15, 0, R2, c1, c0, 2 // Read CPACR - ANDEQ R2, R2, #0xFF0FFFFF // VFP/NEON state not stacked, disable VFP/NEON - ORRNE R2, R2, #0x00F00000 // VFP/NEON state is stacked, enable VFP/NEON - MCR p15, 0, R2, c1, c0, 2 // Write CPACR - BEQ osRtxContextRestore1 // No VFP - ISB // Sync if VFP was enabled - #if __ARM_NEON == 1 - VLDMIA LR!, {D16-D31} // Restore D16-D31 - #endif - VLDMIA LR!, {D0-D15} // Restore D0-D15 - LDR R2, [LR] - VMSR FPSCR, R2 // Restore FPSCR - ADD LR, LR, #8 // Adjust sp pointer to R4 - -osRtxContextRestore1: - LDMIA LR!, {R4-R11} // Restore R4-R11 - ADD R12, LR, #32 // Adjust sp and save it into R12 - PUSH {R12} // Push sp onto stack - LDM SP, {SP}^ // Restore SP_usr directly - ADD SP, SP, #4 // Adjust SP_svc - LDMIA LR!, {R0-R3, R12} // Load user registers R0-R3,R12 - STMIB SP!, {R0-R3, R12} // Store them to SP_svc - LDM LR, {LR}^ // Restore LR_usr directly - LDMIB LR!, {R0-R1} // Load user registers PC,CPSR - ADD SP, SP, #4 - STMIB SP!, {R0-R1} // Store them to SP_svc - SUB SP, SP, #32 // Adjust SP_svc to stacked LR + ldr lr, [r8, #TCB_SP_OFS] // Load next osRtxThread_t.sp + ldrb r2, [r8, #TCB_SP_FRAME] // Load next osRtxThread_t.stack_frame + + ands r2, r2, #0x6 // Check stack frame for VFP context + mrc p15, 0, r2, c1, c0, 2 // Read CPACR + andeq r2, r2, #0xFF0FFFFF // VFP/NEON state not stacked, disable VFP/NEON + orrne r2, r2, #0x00F00000 // VFP/NEON state is stacked, enable VFP/NEON + mcr p15, 0, r2, c1, c0, 2 // Write CPACR + beq osRtxContextRestoreRegs // No VFP + isb // Sync if VFP was enabled + #if defined(__ARM_NEON) && (__ARM_NEON == 1) + vldmia lr!, {d16-d31} // Restore D16-D31 + #endif + vldmia lr!, {d0-d15} // Restore D0-D15 + ldr r2, [lr] + vmsr fpscr, r2 // Restore FPSCR + add lr, lr, #8 // Adjust sp pointer to R4 + +osRtxContextRestoreRegs: + ldmia lr!, {r4-r11} // Restore R4-R11 + add r12, lr, #32 // Adjust sp and save it into R12 + push {r12} // Push sp onto stack + ldm sp, {sp}^ // Restore SP_usr directly + add sp, sp, #4 // Adjust SP_svc + ldmia lr!, {r0-r3, r12} // Load user registers R0-R3,R12 + stmib sp!, {r0-r3, r12} // Store them to SP_svc + ldm lr, {lr}^ // Restore LR_usr directly + ldmib lr!, {r0-r1} // Load user registers PC,CPSR + add sp, sp, #4 + stmib sp!, {r0-r1} // Store them to SP_svc + sub sp, sp, #32 // Adjust SP_svc to stacked LR osRtxContextExit: - POP {PC} // Return + pop {pc} // Return .fnend .size osRtxContextSwitch, .-osRtxContextSwitch diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M0/irq_cm0.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M0/irq_cm0.S index 4d1359116e6..74f7d362aaa 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M0/irq_cm0.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M0/irq_cm0.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -18,7 +18,7 @@ * ----------------------------------------------------------------------------- * * Project: CMSIS-RTOS RTX - * Title: Cortex-M0 Exception handlers + * Title: ARMv6-M Exception handlers * * ----------------------------------------------------------------------------- */ @@ -26,9 +26,16 @@ .syntax unified + // Mbed OS patch: Exclude RTE_Components.h and RTX_Config.h inclusion in .S files + #define RTX_CONFIG_H_ + #undef _RTE_ + #include "rtx_def.h" + .equ I_T_RUN_OFS, 20 // osRtxInfo.thread.run offset .equ TCB_SP_OFS, 56 // TCB.SP offset + .equ osRtxErrorStackOverflow, 1 // Stack overflow + .section ".rodata" .global irqRtxLib // Non weak library reference irqRtxLib: @@ -38,6 +45,7 @@ irqRtxLib: .thumb .section ".text" .align 2 + .eabi_attribute Tag_ABI_align_preserved, 1 .thumb_func @@ -47,89 +55,109 @@ irqRtxLib: .cantunwind SVC_Handler: - MOV R0,LR - LSRS R0,R0,#3 // Determine return stack from EXC_RETURN bit 2 - BCC SVC_MSP // Branch if return stack is MSP - MRS R0,PSP // Get PSP + mov r0,lr + lsrs r0,r0,#3 // Determine return stack from EXC_RETURN bit 2 + bcc SVC_MSP // Branch if return stack is MSP + mrs r0,psp // Get PSP SVC_Number: - LDR R1,[R0,#24] // Load saved PC from stack - SUBS R1,R1,#2 // Point to SVC instruction - LDRB R1,[R1] // Load SVC number - CMP R1,#0 - BNE SVC_User // Branch if not SVC 0 - - PUSH {R0,LR} // Save SP and EXC_RETURN - LDMIA R0,{R0-R3} // Load function parameters from stack - BLX R7 // Call service function - POP {R2,R3} // Restore SP and EXC_RETURN - STMIA R2!,{R0-R1} // Store function return values - MOV LR,R3 // Set EXC_RETURN + ldr r1,[r0,#24] // Load saved PC from stack + subs r1,r1,#2 // Point to SVC instruction + ldrb r1,[r1] // Load SVC number + cmp r1,#0 // Check SVC number + bne SVC_User // Branch if not SVC 0 + + push {r0,lr} // Save SP and EXC_RETURN + ldmia r0,{r0-r3} // Load function parameters from stack + blx r7 // Call service function + pop {r2,r3} // Restore SP and EXC_RETURN + stmia r2!,{r0-r1} // Store function return values + mov lr,r3 // Set EXC_RETURN SVC_Context: - LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run - LDMIA R3!,{R1,R2} // Load osRtxInfo.thread.run: curr & next - CMP R1,R2 // Check if thread switch is required - BEQ SVC_Exit // Branch when threads are the same + ldr r3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.thread.run + ldmia r3!,{r1,r2} // Load osRtxInfo.thread.run: curr & next + cmp r1,r2 // Check if thread switch is required + beq SVC_Exit // Branch when threads are the same - CMP R1,#0 - BEQ SVC_ContextSwitch // Branch if running thread is deleted + subs r3,r3,#8 // Adjust address + str r2,[r3] // osRtxInfo.thread.run: curr = next + cmp r1,#0 + beq SVC_ContextRestore // Branch if running thread is deleted SVC_ContextSave: - MRS R0,PSP // Get PSP - SUBS R0,R0,#32 // Calculate SP - STR R0,[R1,#TCB_SP_OFS] // Store SP - STMIA R0!,{R4-R7} // Save R4..R7 - MOV R4,R8 - MOV R5,R9 - MOV R6,R10 - MOV R7,R11 - STMIA R0!,{R4-R7} // Save R8..R11 - -SVC_ContextSwitch: - SUBS R3,R3,#8 // Adjust address - STR R2,[R3] // osRtxInfo.thread.run: curr = next + mrs r0,psp // Get PSP + subs r0,r0,#32 // Calculate SP: space for R4..R11 + str r0,[r1,#TCB_SP_OFS] // Store SP + + #ifdef RTX_STACK_CHECK + + push {r1,r2} // Save osRtxInfo.thread.run: curr & next + mov r0,r1 // Parameter: osRtxInfo.thread.run.curr + bl osRtxThreadStackCheck // Check if thread stack is overrun + pop {r1,r2} // Restore osRtxInfo.thread.run: curr & next + cmp r0,#0 + bne SVC_ContextSaveRegs // Branch when stack check is ok + + movs r0,#osRtxErrorStackOverflow // Parameter: r0=code, r1=object_id + bl osRtxKernelErrorNotify // Call osRtxKernelErrorNotify + ldr r3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.thread.run + ldr r2,[r3,#4] // Load osRtxInfo.thread.run: next + str r2,[r3] // osRtxInfo.thread.run: curr = next + b SVC_ContextRestore // Branch to context restore handling + +SVC_ContextSaveRegs: + ldr r0,[r1,#TCB_SP_OFS] // Load SP + + #endif // RTX_STACK_CHECK + + stmia r0!,{r4-r7} // Save R4..R7 + mov r4,r8 + mov r5,r9 + mov r6,r10 + mov r7,r11 + stmia r0!,{r4-r7} // Save R8..R11 SVC_ContextRestore: - LDR R0,[R2,#TCB_SP_OFS] // Load SP - ADDS R0,R0,#16 // Adjust address - LDMIA R0!,{R4-R7} // Restore R8..R11 - MOV R8,R4 - MOV R9,R5 - MOV R10,R6 - MOV R11,R7 - MSR PSP,R0 // Set PSP - SUBS R0,R0,#32 // Adjust address - LDMIA R0!,{R4-R7} // Restore R4..R7 - - MOVS R0,#2 // Binary complement of 0xFFFFFFFD - MVNS R0,R0 // Set EXC_RETURN value - BX R0 // Exit from handler + ldr r0,[r2,#TCB_SP_OFS] // Load SP + adds r0,r0,#16 // Adjust address + ldmia r0!,{r4-r7} // Restore R8..R11 + mov r8,r4 + mov r9,r5 + mov r10,r6 + mov r11,r7 + msr psp,r0 // Set PSP + subs r0,r0,#32 // Adjust address + ldmia r0!,{r4-r7} // Restore R4..R7 + + movs r0,#2 // Binary complement of 0xFFFFFFFD + mvns r0,r0 // Set EXC_RETURN value + bx r0 // Exit from handler SVC_MSP: - MRS R0,MSP // Get MSP - B SVC_Number + mrs r0,msp // Get MSP + b SVC_Number SVC_Exit: - BX LR // Exit from handler + bx lr // Exit from handler SVC_User: - LDR R2,=osRtxUserSVC // Load address of SVC table - LDR R3,[R2] // Load SVC maximum number - CMP R1,R3 // Check SVC number range - BHI SVC_Exit // Branch if out of range - - PUSH {R0,LR} // Save SP and EXC_RETURN - LSLS R1,R1,#2 - LDR R3,[R2,R1] // Load address of SVC function - MOV R12,R3 - LDMIA R0,{R0-R3} // Load function parameters from stack - BLX R12 // Call service function - POP {R2,R3} // Restore SP and EXC_RETURN - STR R0,[R2] // Store function return value - MOV LR,R3 // Set EXC_RETURN - - BX LR // Return from handler + ldr r2,=osRtxUserSVC // Load address of SVC table + ldr r3,[r2] // Load SVC maximum number + cmp r1,r3 // Check SVC number range + bhi SVC_Exit // Branch if out of range + + push {r0,lr} // Save SP and EXC_RETURN + lsls r1,r1,#2 + ldr r3,[r2,r1] // Load address of SVC function + mov r12,r3 + ldmia r0,{r0-r3} // Load function parameters from stack + blx r12 // Call service function + pop {r2,r3} // Restore SP and EXC_RETURN + str r0,[r2] // Store function return value + mov lr,r3 // Set EXC_RETURN + + bx lr // Return from handler .fnend .size SVC_Handler, .-SVC_Handler @@ -142,11 +170,11 @@ SVC_User: .cantunwind PendSV_Handler: - PUSH {R0,LR} // Save EXC_RETURN - BL osRtxPendSV_Handler // Call osRtxPendSV_Handler - POP {R0,R1} // Restore EXC_RETURN - MOV LR,R1 // Set EXC_RETURN - B SVC_Context + push {r0,lr} // Save EXC_RETURN + bl osRtxPendSV_Handler // Call osRtxPendSV_Handler + pop {r0,r1} // Restore EXC_RETURN + mov lr,r1 // Set EXC_RETURN + b SVC_Context // Branch to context handling .fnend .size PendSV_Handler, .-PendSV_Handler @@ -159,11 +187,11 @@ PendSV_Handler: .cantunwind SysTick_Handler: - PUSH {R0,LR} // Save EXC_RETURN - BL osRtxTick_Handler // Call osRtxTick_Handler - POP {R0,R1} // Restore EXC_RETURN - MOV LR,R1 // Set EXC_RETURN - B SVC_Context + push {r0,lr} // Save EXC_RETURN + bl osRtxTick_Handler // Call osRtxTick_Handler + pop {r0,r1} // Restore EXC_RETURN + mov lr,r1 // Set EXC_RETURN + b SVC_Context // Branch to context handling .fnend .size SysTick_Handler, .-SysTick_Handler diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M0P/irq_cm0.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M0P/irq_cm0.S index 4d1359116e6..74f7d362aaa 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M0P/irq_cm0.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M0P/irq_cm0.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -18,7 +18,7 @@ * ----------------------------------------------------------------------------- * * Project: CMSIS-RTOS RTX - * Title: Cortex-M0 Exception handlers + * Title: ARMv6-M Exception handlers * * ----------------------------------------------------------------------------- */ @@ -26,9 +26,16 @@ .syntax unified + // Mbed OS patch: Exclude RTE_Components.h and RTX_Config.h inclusion in .S files + #define RTX_CONFIG_H_ + #undef _RTE_ + #include "rtx_def.h" + .equ I_T_RUN_OFS, 20 // osRtxInfo.thread.run offset .equ TCB_SP_OFS, 56 // TCB.SP offset + .equ osRtxErrorStackOverflow, 1 // Stack overflow + .section ".rodata" .global irqRtxLib // Non weak library reference irqRtxLib: @@ -38,6 +45,7 @@ irqRtxLib: .thumb .section ".text" .align 2 + .eabi_attribute Tag_ABI_align_preserved, 1 .thumb_func @@ -47,89 +55,109 @@ irqRtxLib: .cantunwind SVC_Handler: - MOV R0,LR - LSRS R0,R0,#3 // Determine return stack from EXC_RETURN bit 2 - BCC SVC_MSP // Branch if return stack is MSP - MRS R0,PSP // Get PSP + mov r0,lr + lsrs r0,r0,#3 // Determine return stack from EXC_RETURN bit 2 + bcc SVC_MSP // Branch if return stack is MSP + mrs r0,psp // Get PSP SVC_Number: - LDR R1,[R0,#24] // Load saved PC from stack - SUBS R1,R1,#2 // Point to SVC instruction - LDRB R1,[R1] // Load SVC number - CMP R1,#0 - BNE SVC_User // Branch if not SVC 0 - - PUSH {R0,LR} // Save SP and EXC_RETURN - LDMIA R0,{R0-R3} // Load function parameters from stack - BLX R7 // Call service function - POP {R2,R3} // Restore SP and EXC_RETURN - STMIA R2!,{R0-R1} // Store function return values - MOV LR,R3 // Set EXC_RETURN + ldr r1,[r0,#24] // Load saved PC from stack + subs r1,r1,#2 // Point to SVC instruction + ldrb r1,[r1] // Load SVC number + cmp r1,#0 // Check SVC number + bne SVC_User // Branch if not SVC 0 + + push {r0,lr} // Save SP and EXC_RETURN + ldmia r0,{r0-r3} // Load function parameters from stack + blx r7 // Call service function + pop {r2,r3} // Restore SP and EXC_RETURN + stmia r2!,{r0-r1} // Store function return values + mov lr,r3 // Set EXC_RETURN SVC_Context: - LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run - LDMIA R3!,{R1,R2} // Load osRtxInfo.thread.run: curr & next - CMP R1,R2 // Check if thread switch is required - BEQ SVC_Exit // Branch when threads are the same + ldr r3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.thread.run + ldmia r3!,{r1,r2} // Load osRtxInfo.thread.run: curr & next + cmp r1,r2 // Check if thread switch is required + beq SVC_Exit // Branch when threads are the same - CMP R1,#0 - BEQ SVC_ContextSwitch // Branch if running thread is deleted + subs r3,r3,#8 // Adjust address + str r2,[r3] // osRtxInfo.thread.run: curr = next + cmp r1,#0 + beq SVC_ContextRestore // Branch if running thread is deleted SVC_ContextSave: - MRS R0,PSP // Get PSP - SUBS R0,R0,#32 // Calculate SP - STR R0,[R1,#TCB_SP_OFS] // Store SP - STMIA R0!,{R4-R7} // Save R4..R7 - MOV R4,R8 - MOV R5,R9 - MOV R6,R10 - MOV R7,R11 - STMIA R0!,{R4-R7} // Save R8..R11 - -SVC_ContextSwitch: - SUBS R3,R3,#8 // Adjust address - STR R2,[R3] // osRtxInfo.thread.run: curr = next + mrs r0,psp // Get PSP + subs r0,r0,#32 // Calculate SP: space for R4..R11 + str r0,[r1,#TCB_SP_OFS] // Store SP + + #ifdef RTX_STACK_CHECK + + push {r1,r2} // Save osRtxInfo.thread.run: curr & next + mov r0,r1 // Parameter: osRtxInfo.thread.run.curr + bl osRtxThreadStackCheck // Check if thread stack is overrun + pop {r1,r2} // Restore osRtxInfo.thread.run: curr & next + cmp r0,#0 + bne SVC_ContextSaveRegs // Branch when stack check is ok + + movs r0,#osRtxErrorStackOverflow // Parameter: r0=code, r1=object_id + bl osRtxKernelErrorNotify // Call osRtxKernelErrorNotify + ldr r3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.thread.run + ldr r2,[r3,#4] // Load osRtxInfo.thread.run: next + str r2,[r3] // osRtxInfo.thread.run: curr = next + b SVC_ContextRestore // Branch to context restore handling + +SVC_ContextSaveRegs: + ldr r0,[r1,#TCB_SP_OFS] // Load SP + + #endif // RTX_STACK_CHECK + + stmia r0!,{r4-r7} // Save R4..R7 + mov r4,r8 + mov r5,r9 + mov r6,r10 + mov r7,r11 + stmia r0!,{r4-r7} // Save R8..R11 SVC_ContextRestore: - LDR R0,[R2,#TCB_SP_OFS] // Load SP - ADDS R0,R0,#16 // Adjust address - LDMIA R0!,{R4-R7} // Restore R8..R11 - MOV R8,R4 - MOV R9,R5 - MOV R10,R6 - MOV R11,R7 - MSR PSP,R0 // Set PSP - SUBS R0,R0,#32 // Adjust address - LDMIA R0!,{R4-R7} // Restore R4..R7 - - MOVS R0,#2 // Binary complement of 0xFFFFFFFD - MVNS R0,R0 // Set EXC_RETURN value - BX R0 // Exit from handler + ldr r0,[r2,#TCB_SP_OFS] // Load SP + adds r0,r0,#16 // Adjust address + ldmia r0!,{r4-r7} // Restore R8..R11 + mov r8,r4 + mov r9,r5 + mov r10,r6 + mov r11,r7 + msr psp,r0 // Set PSP + subs r0,r0,#32 // Adjust address + ldmia r0!,{r4-r7} // Restore R4..R7 + + movs r0,#2 // Binary complement of 0xFFFFFFFD + mvns r0,r0 // Set EXC_RETURN value + bx r0 // Exit from handler SVC_MSP: - MRS R0,MSP // Get MSP - B SVC_Number + mrs r0,msp // Get MSP + b SVC_Number SVC_Exit: - BX LR // Exit from handler + bx lr // Exit from handler SVC_User: - LDR R2,=osRtxUserSVC // Load address of SVC table - LDR R3,[R2] // Load SVC maximum number - CMP R1,R3 // Check SVC number range - BHI SVC_Exit // Branch if out of range - - PUSH {R0,LR} // Save SP and EXC_RETURN - LSLS R1,R1,#2 - LDR R3,[R2,R1] // Load address of SVC function - MOV R12,R3 - LDMIA R0,{R0-R3} // Load function parameters from stack - BLX R12 // Call service function - POP {R2,R3} // Restore SP and EXC_RETURN - STR R0,[R2] // Store function return value - MOV LR,R3 // Set EXC_RETURN - - BX LR // Return from handler + ldr r2,=osRtxUserSVC // Load address of SVC table + ldr r3,[r2] // Load SVC maximum number + cmp r1,r3 // Check SVC number range + bhi SVC_Exit // Branch if out of range + + push {r0,lr} // Save SP and EXC_RETURN + lsls r1,r1,#2 + ldr r3,[r2,r1] // Load address of SVC function + mov r12,r3 + ldmia r0,{r0-r3} // Load function parameters from stack + blx r12 // Call service function + pop {r2,r3} // Restore SP and EXC_RETURN + str r0,[r2] // Store function return value + mov lr,r3 // Set EXC_RETURN + + bx lr // Return from handler .fnend .size SVC_Handler, .-SVC_Handler @@ -142,11 +170,11 @@ SVC_User: .cantunwind PendSV_Handler: - PUSH {R0,LR} // Save EXC_RETURN - BL osRtxPendSV_Handler // Call osRtxPendSV_Handler - POP {R0,R1} // Restore EXC_RETURN - MOV LR,R1 // Set EXC_RETURN - B SVC_Context + push {r0,lr} // Save EXC_RETURN + bl osRtxPendSV_Handler // Call osRtxPendSV_Handler + pop {r0,r1} // Restore EXC_RETURN + mov lr,r1 // Set EXC_RETURN + b SVC_Context // Branch to context handling .fnend .size PendSV_Handler, .-PendSV_Handler @@ -159,11 +187,11 @@ PendSV_Handler: .cantunwind SysTick_Handler: - PUSH {R0,LR} // Save EXC_RETURN - BL osRtxTick_Handler // Call osRtxTick_Handler - POP {R0,R1} // Restore EXC_RETURN - MOV LR,R1 // Set EXC_RETURN - B SVC_Context + push {r0,lr} // Save EXC_RETURN + bl osRtxTick_Handler // Call osRtxTick_Handler + pop {r0,r1} // Restore EXC_RETURN + mov lr,r1 // Set EXC_RETURN + b SVC_Context // Branch to context handling .fnend .size SysTick_Handler, .-SysTick_Handler diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M23/irq_armv8mbl.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M23/irq_armv8mbl.S index 90540257d44..deee5b9850c 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M23/irq_armv8mbl.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M23/irq_armv8mbl.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 Arm Limited. All rights reserved. + * Copyright (c) 2016-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -18,7 +18,7 @@ * ----------------------------------------------------------------------------- * * Project: CMSIS-RTOS RTX - * Title: ARMv8M Baseline Exception handlers + * Title: ARMv8-M Baseline Exception handlers * * ----------------------------------------------------------------------------- */ @@ -26,11 +26,10 @@ .syntax unified - #ifdef _RTE_ - #ifdef RTE_CMSIS_RTOS2_RTX5_ARMV8M_NS - #define DOMAIN_NS 1 - #endif - #endif + // Mbed OS patch: Exclude RTE_Components.h and RTX_Config.h inclusion in .S files + #define RTX_CONFIG_H_ + #undef _RTE_ + #include "rtx_def.h" #ifndef DOMAIN_NS #define DOMAIN_NS 0 @@ -42,6 +41,8 @@ .equ TCB_SF_OFS, 34 // TCB.stack_frame offset .equ TCB_TZM_OFS, 64 // TCB.tz_memory offset + .equ osRtxErrorStackOverflow, 1 // Stack overflow + .section ".rodata" .global irqRtxLib // Non weak library reference irqRtxLib: @@ -51,6 +52,7 @@ irqRtxLib: .thumb .section ".text" .align 2 + .eabi_attribute Tag_ABI_align_preserved, 1 .thumb_func @@ -60,129 +62,171 @@ irqRtxLib: .cantunwind SVC_Handler: - MOV R0,LR - LSRS R0,R0,#3 // Determine return stack from EXC_RETURN bit 2 - BCC SVC_MSP // Branch if return stack is MSP - MRS R0,PSP // Get PSP + mov r0,lr + lsrs r0,r0,#3 // Determine return stack from EXC_RETURN bit 2 + bcc SVC_MSP // Branch if return stack is MSP + mrs r0,psp // Get PSP SVC_Number: - LDR R1,[R0,#24] // Load saved PC from stack - SUBS R1,R1,#2 // Point to SVC instruction - LDRB R1,[R1] // Load SVC number - CMP R1,#0 - BNE SVC_User // Branch if not SVC 0 - - PUSH {R0,LR} // Save SP and EXC_RETURN - LDM R0,{R0-R3} // Load function parameters from stack - BLX R7 // Call service function - POP {R2,R3} // Restore SP and EXC_RETURN - STMIA R2!,{R0-R1} // Store function return values - MOV LR,R3 // Set EXC_RETURN + ldr r1,[r0,#24] // Load saved PC from stack + subs r1,r1,#2 // Point to SVC instruction + ldrb r1,[r1] // Load SVC number + cmp r1,#0 // Check SVC number + bne SVC_User // Branch if not SVC 0 + + push {r0,lr} // Save SP and EXC_RETURN + ldmia r0,{r0-r3} // Load function parameters from stack + blx r7 // Call service function + pop {r2,r3} // Restore SP and EXC_RETURN + stmia r2!,{r0-r1} // Store function return values + mov lr,r3 // Set EXC_RETURN SVC_Context: - LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run - LDMIA R3!,{R1,R2} // Load osRtxInfo.thread.run: curr & next - CMP R1,R2 // Check if thread switch is required - BEQ SVC_Exit // Branch when threads are the same + ldr r3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.thread.run + ldmia r3!,{r1,r2} // Load osRtxInfo.thread.run: curr & next + cmp r1,r2 // Check if thread switch is required + beq SVC_Exit // Branch when threads are the same - CBZ R1,SVC_ContextSwitch // Branch if running thread is deleted + subs r3,r3,#8 // Adjust address + str r2,[r3] // osRtxInfo.thread.run: curr = next + cbz r1,SVC_ContextRestore // Branch if running thread is deleted SVC_ContextSave: - #if (DOMAIN_NS == 1) - LDR R0,[R1,#TCB_TZM_OFS] // Load TrustZone memory identifier - CBZ R0,SVC_ContextSave1 // Branch if there is no secure context - PUSH {R1,R2,R3,R7} // Save registers - MOV R7,LR // Get EXC_RETURN - BL TZ_StoreContext_S // Store secure context - MOV LR,R7 // Set EXC_RETURN - POP {R1,R2,R3,R7} // Restore registers - #endif - -SVC_ContextSave1: - MRS R0,PSP // Get PSP - SUBS R0,R0,#32 // Calculate SP - STR R0,[R1,#TCB_SP_OFS] // Store SP - STMIA R0!,{R4-R7} // Save R4..R7 - MOV R4,R8 - MOV R5,R9 - MOV R6,R10 - MOV R7,R11 - STMIA R0!,{R4-R7} // Save R8..R11 - -SVC_ContextSave2: - MOV R0,LR // Get EXC_RETURN - ADDS R1,R1,#TCB_SF_OFS // Adjust address - STRB R0,[R1] // Store stack frame information - -SVC_ContextSwitch: - SUBS R3,R3,#8 // Adjust address - STR R2,[R3] // osRtxInfo.thread.run: curr = next + #if (DOMAIN_NS != 0) + ldr r0,[r1,#TCB_TZM_OFS] // Load TrustZone memory identifier + cbz r0,SVC_ContextSave_NS // Branch if there is no secure context + push {r1,r2,r3,r7} // Save registers + mov r7,lr // Get EXC_RETURN + bl TZ_StoreContext_S // Store secure context + mov lr,r7 // Set EXC_RETURN + pop {r1,r2,r3,r7} // Restore registers + #endif + +SVC_ContextSave_NS: + mrs r0,psp // Get PSP + #if (DOMAIN_NS != 0) + mov r3,lr // Get EXC_RETURN + lsls r3,r3,#25 // Check domain of interrupted thread + bmi SVC_ContextSaveSP // Branch if secure + #endif + + #ifdef RTX_STACK_CHECK + subs r0,r0,#32 // Calculate SP: space for R4..R11 + +SVC_ContextSaveSP: + str r0,[r1,#TCB_SP_OFS] // Store SP + mov r3,lr // Get EXC_RETURN + mov r0,r1 // osRtxInfo.thread.run.curr + adds r0,r0,#TCB_SF_OFS // Adjust address + strb r3,[r0] // Store stack frame information + + push {r1,r2} // Save osRtxInfo.thread.run: curr & next + mov r0,r1 // Parameter: osRtxInfo.thread.run.curr + bl osRtxThreadStackCheck // Check if thread stack is overrun + pop {r1,r2} // Restore osRtxInfo.thread.run: curr & next + cmp r0,#0 + bne SVC_ContextSaveRegs // Branch when stack check is ok + + movs r0,#osRtxErrorStackOverflow // Parameter: r0=code, r1=object_id + bl osRtxKernelErrorNotify // Call osRtxKernelErrorNotify + ldr r3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.thread.run + ldr r2,[r3,#4] // Load osRtxInfo.thread.run: next + str r2,[r3] // osRtxInfo.thread.run: curr = next + b SVC_ContextRestore // Branch to context restore handling + +SVC_ContextSaveRegs: + #if (DOMAIN_NS != 0) + mov r0,r1 // osRtxInfo.thread.run.curr + adds r0,r0,#TCB_SF_OFS // Adjust address + ldrb r3,[r0] // Load stack frame information + lsls r3,r3,#25 // Check domain of interrupted thread + bmi SVC_ContextRestore // Branch if secure + #endif + ldr r0,[r1,#TCB_SP_OFS] // Load SP + stmia r0!,{r4-r7} // Save R4..R7 + mov r4,r8 + mov r5,r9 + mov r6,r10 + mov r7,r11 + stmia r0!,{r4-r7} // Save R8..R11 + #else + subs r0,r0,#32 // Calculate SP: space for R4..R11 + stmia r0!,{r4-r7} // Save R4..R7 + mov r4,r8 + mov r5,r9 + mov r6,r10 + mov r7,r11 + stmia r0!,{r4-r7} // Save R8..R11 + subs r0,r0,#32 // Adjust address +SVC_ContextSaveSP: + str r0,[r1,#TCB_SP_OFS] // Store SP + mov r0,lr // Get EXC_RETURN + adds r1,r1,#TCB_SF_OFS // Adjust address + strb r0,[r1] // Store stack frame information + #endif // RTX_STACK_CHECK SVC_ContextRestore: - #if (DOMAIN_NS == 1) - LDR R0,[R2,#TCB_TZM_OFS] // Load TrustZone memory identifier - CBZ R0,SVC_ContextRestore1 // Branch if there is no secure context - PUSH {R2,R3} // Save registers - BL TZ_LoadContext_S // Load secure context - POP {R2,R3} // Restore registers - #endif - -SVC_ContextRestore1: - MOV R1,R2 - ADDS R1,R1,#TCB_SF_OFS // Adjust address - LDRB R0,[R1] // Load stack frame information - MOVS R1,#0xFF - MVNS R1,R1 // R1=0xFFFFFF00 - ORRS R0,R1 - MOV LR,R0 // Set EXC_RETURN - - #if (DOMAIN_NS == 1) - LSLS R0,R0,#25 // Check domain of interrupted thread - BPL SVC_ContextRestore2 // Branch if non-secure - LDR R0,[R2,#TCB_SP_OFS] // Load SP - MSR PSP,R0 // Set PSP - BX LR // Exit from handler - #else - LDR R0,[R2,#TCB_SM_OFS] // Load stack memory base - MSR PSPLIM,R0 // Set PSPLIM - #endif - -SVC_ContextRestore2: - LDR R0,[R2,#TCB_SP_OFS] // Load SP - ADDS R0,R0,#16 // Adjust address - LDMIA R0!,{R4-R7} // Restore R8..R11 - MOV R8,R4 - MOV R9,R5 - MOV R10,R6 - MOV R11,R7 - MSR PSP,R0 // Set PSP - SUBS R0,R0,#32 // Adjust address - LDMIA R0!,{R4-R7} // Restore R4..R7 + #if (DOMAIN_NS != 0) + ldr r0,[r2,#TCB_TZM_OFS] // Load TrustZone memory identifier + cbz r0,SVC_ContextRestore_NS // Branch if there is no secure context + push {r2,r3} // Save registers + bl TZ_LoadContext_S // Load secure context + pop {r2,r3} // Restore registers + #endif + +SVC_ContextRestore_NS: + ldr r0,[r2,#TCB_SM_OFS] // Load stack memory base + msr psplim,r0 // Set PSPLIM + mov r0,r2 // osRtxInfo.thread.run.next + adds r0,r0,#TCB_SF_OFS // Adjust address + ldrb r3,[r0] // Load stack frame information + movs r0,#0xFF + mvns r0,r0 // R0=0xFFFFFF00 + orrs r3,r3,r0 + mov lr,r3 // Set EXC_RETURN + ldr r0,[r2,#TCB_SP_OFS] // Load SP + #if (DOMAIN_NS != 0) + lsls r3,r3,#25 // Check domain of interrupted thread + bmi SVC_ContextRestoreSP // Branch if secure + #endif + + adds r0,r0,#16 // Adjust address + ldmia r0!,{r4-r7} // Restore R8..R11 + mov r8,r4 + mov r9,r5 + mov r10,r6 + mov r11,r7 + subs r0,r0,#32 // Adjust address + ldmia r0!,{r4-r7} // Restore R4..R7 + adds r0,r0,#16 // Adjust address + +SVC_ContextRestoreSP: + msr psp,r0 // Set PSP SVC_Exit: - BX LR // Exit from handler + bx lr // Exit from handler SVC_MSP: - MRS R0,MSP // Get MSP - B SVC_Number + mrs r0,msp // Get MSP + b SVC_Number SVC_User: - LDR R2,=osRtxUserSVC // Load address of SVC table - LDR R3,[R2] // Load SVC maximum number - CMP R1,R3 // Check SVC number range - BHI SVC_Exit // Branch if out of range - - PUSH {R0,LR} // Save SP and EXC_RETURN - LSLS R1,R1,#2 - LDR R3,[R2,R1] // Load address of SVC function - MOV R12,R3 - LDMIA R0,{R0-R3} // Load function parameters from stack - BLX R12 // Call service function - POP {R2,R3} // Restore SP and EXC_RETURN - STR R0,[R2] // Store function return value - MOV LR,R3 // Set EXC_RETURN - - BX LR // Return from handler + ldr r2,=osRtxUserSVC // Load address of SVC table + ldr r3,[r2] // Load SVC maximum number + cmp r1,r3 // Check SVC number range + bhi SVC_Exit // Branch if out of range + + push {r0,lr} // Save SP and EXC_RETURN + lsls r1,r1,#2 + ldr r3,[r2,r1] // Load address of SVC function + mov r12,r3 + ldmia r0,{r0-r3} // Load function parameters from stack + blx r12 // Call service function + pop {r2,r3} // Restore SP and EXC_RETURN + str r0,[r2] // Store function return value + mov lr,r3 // Set EXC_RETURN + + bx lr // Return from handler .fnend .size SVC_Handler, .-SVC_Handler @@ -195,11 +239,11 @@ SVC_User: .cantunwind PendSV_Handler: - PUSH {R0,LR} // Save EXC_RETURN - BL osRtxPendSV_Handler // Call osRtxPendSV_Handler - POP {R0,R1} // Restore EXC_RETURN - MOV LR,R1 // Set EXC_RETURN - B Sys_Context + push {r0,lr} // Save EXC_RETURN + bl osRtxPendSV_Handler // Call osRtxPendSV_Handler + pop {r0,r1} // Restore EXC_RETURN + mov lr,r1 // Set EXC_RETURN + b SVC_Context // Branch to context handling .fnend .size PendSV_Handler, .-PendSV_Handler @@ -212,113 +256,14 @@ PendSV_Handler: .cantunwind SysTick_Handler: - PUSH {R0,LR} // Save EXC_RETURN - BL osRtxTick_Handler // Call osRtxTick_Handler - POP {R0,R1} // Restore EXC_RETURN - MOV LR,R1 // Set EXC_RETURN - B Sys_Context - - .fnend - .size SysTick_Handler, .-SysTick_Handler - - - .thumb_func - .type Sys_Context, %function - .global Sys_Context - .fnstart - .cantunwind -Sys_Context: - - LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run - LDM R3!,{R1,R2} // Load osRtxInfo.thread.run: curr & next - CMP R1,R2 // Check if thread switch is required - BEQ Sys_ContextExit // Branch when threads are the same - -Sys_ContextSave: - #if (DOMAIN_NS == 1) - LDR R0,[R1,#TCB_TZM_OFS] // Load TrustZone memory identifier - CBZ R0,Sys_ContextSave1 // Branch if there is no secure context - PUSH {R1,R2,R3,R7} // Save registers - MOV R7,LR // Get EXC_RETURN - BL TZ_StoreContext_S // Store secure context - MOV LR,R7 // Set EXC_RETURN - POP {R1,R2,R3,R7} // Restore registers - -Sys_ContextSave1: - MOV R0,LR // Get EXC_RETURN - LSLS R0,R0,#25 // Check domain of interrupted thread - BPL Sys_ContextSave2 // Branch if non-secure - MRS R0,PSP // Get PSP - STR R0,[R1,#TCB_SP_OFS] // Store SP - B Sys_ContextSave3 - #endif - -Sys_ContextSave2: - MRS R0,PSP // Get PSP - SUBS R0,R0,#32 // Adjust address - STR R0,[R1,#TCB_SP_OFS] // Store SP - STMIA R0!,{R4-R7} // Save R4..R7 - MOV R4,R8 - MOV R5,R9 - MOV R6,R10 - MOV R7,R11 - STMIA R0!,{R4-R7} // Save R8..R11 - -Sys_ContextSave3: - MOV R0,LR // Get EXC_RETURN - ADDS R1,R1,#TCB_SF_OFS // Adjust address - STRB R0,[R1] // Store stack frame information - -Sys_ContextSwitch: - SUBS R3,R3,#8 // Adjust address - STR R2,[R3] // osRtxInfo.run: curr = next - -Sys_ContextRestore: - #if (DOMAIN_NS == 1) - LDR R0,[R2,#TCB_TZM_OFS] // Load TrustZone memory identifier - CBZ R0,Sys_ContextRestore1 // Branch if there is no secure context - PUSH {R2,R3} // Save registers - BL TZ_LoadContext_S // Load secure context - POP {R2,R3} // Restore registers - #endif - -Sys_ContextRestore1: - MOV R1,R2 - ADDS R1,R1,#TCB_SF_OFS // Adjust offset - LDRB R0,[R1] // Load stack frame information - MOVS R1,#0xFF - MVNS R1,R1 // R1=0xFFFFFF00 - ORRS R0,R1 - MOV LR,R0 // Set EXC_RETURN - - #if (DOMAIN_NS == 1) - LSLS R0,R0,#25 // Check domain of interrupted thread - BPL Sys_ContextRestore2 // Branch if non-secure - LDR R0,[R2,#TCB_SP_OFS] // Load SP - MSR PSP,R0 // Set PSP - BX LR // Exit from handler - #else - LDR R0,[R2,#TCB_SM_OFS] // Load stack memory base - MSR PSPLIM,R0 // Set PSPLIM - #endif - -Sys_ContextRestore2: - LDR R0,[R2,#TCB_SP_OFS] // Load SP - ADDS R0,R0,#16 // Adjust address - LDMIA R0!,{R4-R7} // Restore R8..R11 - MOV R8,R4 - MOV R9,R5 - MOV R10,R6 - MOV R11,R7 - MSR PSP,R0 // Set PSP - SUBS R0,R0,#32 // Adjust address - LDMIA R0!,{R4-R7} // Restore R4..R7 - -Sys_ContextExit: - BX LR // Exit from handler + push {r0,lr} // Save EXC_RETURN + bl osRtxTick_Handler // Call osRtxTick_Handler + pop {r0,r1} // Restore EXC_RETURN + mov lr,r1 // Set EXC_RETURN + b SVC_Context // Branch to context handling .fnend - .size Sys_Context, .-Sys_Context + .size SysTick_Handler, .-SysTick_Handler .end diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M3/irq_cm3.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M3/irq_cm3.S index 069bc901458..c0a47974347 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M3/irq_cm3.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M3/irq_cm3.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -18,7 +18,7 @@ * ----------------------------------------------------------------------------- * * Project: CMSIS-RTOS RTX - * Title: Cortex-M3 Exception handlers + * Title: ARMv7-M Exception handlers * * ----------------------------------------------------------------------------- */ @@ -26,8 +26,24 @@ .syntax unified + // Mbed OS patch: Exclude RTE_Components.h and RTX_Config.h inclusion in .S files + #define RTX_CONFIG_H_ + #undef _RTE_ + #include "rtx_def.h" + + #if (defined(__ARM_FP) && (__ARM_FP > 0)) + .equ FPU_USED, 1 + #else + .equ FPU_USED, 0 + #endif + .equ I_T_RUN_OFS, 20 // osRtxInfo.thread.run offset .equ TCB_SP_OFS, 56 // TCB.SP offset + .equ TCB_SF_OFS, 34 // TCB.stack_frame offset + + .equ FPCCR, 0xE000EF34 // FPCCR Address + + .equ osRtxErrorStackOverflow, 1 // Stack overflow .section ".rodata" .global irqRtxLib // Non weak library reference @@ -38,6 +54,7 @@ irqRtxLib: .thumb .section ".text" .align 2 + .eabi_attribute Tag_ABI_align_preserved, 1 .thumb_func @@ -47,60 +64,128 @@ irqRtxLib: .cantunwind SVC_Handler: - TST LR,#0x04 // Determine return stack from EXC_RETURN bit 2 - ITE EQ - MRSEQ R0,MSP // Get MSP if return stack is MSP - MRSNE R0,PSP // Get PSP if return stack is PSP + tst lr,#0x04 // Determine return stack from EXC_RETURN bit 2 + ite eq + mrseq r0,msp // Get MSP if return stack is MSP + mrsne r0,psp // Get PSP if return stack is PSP - LDR R1,[R0,#24] // Load saved PC from stack - LDRB R1,[R1,#-2] // Load SVC number - CBNZ R1,SVC_User // Branch if not SVC 0 + ldr r1,[r0,#24] // Load saved PC from stack + ldrb r1,[r1,#-2] // Load SVC number + cmp r1,#0 // Check SVC number + bne SVC_User // Branch if not SVC 0 - PUSH {R0,LR} // Save SP and EXC_RETURN - LDM R0,{R0-R3,R12} // Load function parameters and address from stack - BLX R12 // Call service function - POP {R12,LR} // Restore SP and EXC_RETURN - STM R12,{R0-R1} // Store function return values + push {r0,lr} // Save SP and EXC_RETURN + ldm r0,{r0-r3,r12} // Load function parameters and address from stack + blx r12 // Call service function + pop {r12,lr} // Restore SP and EXC_RETURN + stm r12,{r0-r1} // Store function return values SVC_Context: - LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run - LDM R3,{R1,R2} // Load osRtxInfo.thread.run: curr & next - CMP R1,R2 // Check if thread switch is required - IT EQ - BXEQ LR // Exit when threads are the same - - CBZ R1,SVC_ContextSwitch // Branch if running thread is deleted + ldr r3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.thread.run + ldm r3,{r1,r2} // Load osRtxInfo.thread.run: curr & next + cmp r1,r2 // Check if thread switch is required + it eq + bxeq lr // Exit when threads are the same + + str r2,[r3] // osRtxInfo.thread.run: curr = next + + .if (FPU_USED != 0) + cbnz r1,SVC_ContextSave // Branch if running thread is not deleted +SVC_FP_LazyState: + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + bne SVC_ContextRestore // Branch if not extended stack frame + ldr r3,=FPCCR // FPCCR Address + ldr r0,[r3] // Load FPCCR + bic r0,r0,#1 // Clear LSPACT (Lazy state preservation) + str r0,[r3] // Store FPCCR + b SVC_ContextRestore // Branch to context restore handling + .else + cbz r1,SVC_ContextRestore // Branch if running thread is deleted + .endif SVC_ContextSave: - STMDB R12!,{R4-R11} // Save R4..R11 - STR R12,[R1,#TCB_SP_OFS] // Store SP - -SVC_ContextSwitch: - STR R2,[R3] // osRtxInfo.thread.run: curr = next + #ifdef RTX_STACK_CHECK + sub r12,r12,#32 // Calculate SP: space for R4..R11 + .if (FPU_USED != 0) + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + it eq // If extended stack frame + subeq r12,r12,#64 // Additional space for S16..S31 + strb lr, [r1,#TCB_SF_OFS] // Store stack frame information + .endif + str r12,[r1,#TCB_SP_OFS] // Store SP + + push {r1,r2} // Save osRtxInfo.thread.run: curr & next + mov r0,r1 // Parameter: osRtxInfo.thread.run.curr + bl osRtxThreadStackCheck // Check if thread stack is overrun + pop {r1,r2} // Restore osRtxInfo.thread.run: curr & next + cbnz r0,SVC_ContextSaveRegs // Branch when stack check is ok + + .if (FPU_USED != 0) + mov r4,r1 // Save osRtxInfo.thread.run.curr + .endif + mov r0,#osRtxErrorStackOverflow // Parameter: r0=code, r1=object_id + bl osRtxKernelErrorNotify // Call osRtxKernelErrorNotify + ldr r3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.thread.run + ldr r2,[r3,#4] // Load osRtxInfo.thread.run: next + str r2,[r3] // osRtxInfo.thread.run: curr = next + .if (FPU_USED != 0) + ldrb lr,[r4,#TCB_SF_OFS] // Load stack frame information + b SVC_FP_LazyState // Branch to FP lazy state handling + .else + b SVC_ContextRestore // Branch to context restore handling + .endif + +SVC_ContextSaveRegs: + ldr r12,[r1,#TCB_SP_OFS] // Load SP + .if (FPU_USED != 0) + ldrb lr, [r1,#TCB_SF_OFS] // Load stack frame information + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + it eq // If extended stack frame + vstmiaeq r12!,{s16-s31} // Save VFP S16..S31 + .endif + stm r12,{r4-r11} // Save R4..R11 + #else + stmdb r12!,{r4-r11} // Save R4..R11 + .if (FPU_USED != 0) + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + it eq // If extended stack frame + vstmdbeq r12!,{s16-s31} // Save VFP S16.S31 + strb lr, [r1,#TCB_SF_OFS] // Store stack frame information + .endif + str r12,[r1,#TCB_SP_OFS] // Store SP + #endif // RTX_STACK_CHECK SVC_ContextRestore: - LDR R0,[R2,#TCB_SP_OFS] // Load SP - LDMIA R0!,{R4-R11} // Restore R4..R11 - MSR PSP,R0 // Set PSP - MVN LR,#~0xFFFFFFFD // Set EXC_RETURN value + ldr r0,[r2,#TCB_SP_OFS] // Load SP + .if (FPU_USED != 0) + ldrb r1,[r2,#TCB_SF_OFS] // Load stack frame information + orn lr,r1,#0xFF // Set EXC_RETURN + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + it eq // If extended stack frame + vldmiaeq r0!,{s16-s31} // Restore VFP S16..S31 + .else + mvn lr,#~0xFFFFFFFD // Set EXC_RETURN value + .endif + ldmia r0!,{r4-r11} // Restore R4..R11 + msr psp,r0 // Set PSP SVC_Exit: - BX LR // Exit from handler + bx lr // Exit from handler SVC_User: - LDR R2,=osRtxUserSVC // Load address of SVC table - LDR R3,[R2] // Load SVC maximum number - CMP R1,R3 // Check SVC number range - BHI SVC_Exit // Branch if out of range + ldr r2,=osRtxUserSVC // Load address of SVC table + ldr r3,[r2] // Load SVC maximum number + cmp r1,r3 // Check SVC number range + bhi SVC_Exit // Branch if out of range - PUSH {R0,LR} // Save SP and EXC_RETURN - LDR R12,[R2,R1,LSL #2] // Load address of SVC function - LDM R0,{R0-R3} // Load function parameters from stack - BLX R12 // Call service function - POP {R12,LR} // Restore SP and EXC_RETURN - STR R0,[R12] // Store function return value + push {r0,lr} // Save SP and EXC_RETURN + ldr r12,[r2,r1,lsl #2] // Load address of SVC function + ldm r0,{r0-r3} // Load function parameters from stack + blx r12 // Call service function + pop {r12,lr} // Restore SP and EXC_RETURN + str r0,[r12] // Store function return value - BX LR // Return from handler + bx lr // Return from handler .fnend .size SVC_Handler, .-SVC_Handler @@ -113,11 +198,11 @@ SVC_User: .cantunwind PendSV_Handler: - PUSH {R0,LR} // Save EXC_RETURN - BL osRtxPendSV_Handler // Call osRtxPendSV_Handler - POP {R0,LR} // Restore EXC_RETURN - MRS R12,PSP - B SVC_Context + push {r0,lr} // Save EXC_RETURN + bl osRtxPendSV_Handler // Call osRtxPendSV_Handler + pop {r0,lr} // Restore EXC_RETURN + mrs r12,psp // Save PSP to R12 + b SVC_Context // Branch to context handling .fnend .size PendSV_Handler, .-PendSV_Handler @@ -130,11 +215,11 @@ PendSV_Handler: .cantunwind SysTick_Handler: - PUSH {R0,LR} // Save EXC_RETURN - BL osRtxTick_Handler // Call osRtxTick_Handler - POP {R0,LR} // Restore EXC_RETURN - MRS R12,PSP - B SVC_Context + push {r0,lr} // Save EXC_RETURN + bl osRtxTick_Handler // Call osRtxTick_Handler + pop {r0,lr} // Restore EXC_RETURN + mrs r12,psp // Save PSP to R12 + b SVC_Context // Branch to context handling .fnend .size SysTick_Handler, .-SysTick_Handler diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M33/irq_armv8mml.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M33/irq_armv8mml.S index 8051ead98e8..fdd99238151 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M33/irq_armv8mml.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_M33/irq_armv8mml.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 Arm Limited. All rights reserved. + * Copyright (c) 2016-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -18,7 +18,7 @@ * ----------------------------------------------------------------------------- * * Project: CMSIS-RTOS RTX - * Title: ARMv8M Mainline Exception handlers + * Title: ARMv8-M Mainline Exception handlers * * ----------------------------------------------------------------------------- */ @@ -26,11 +26,10 @@ .syntax unified - #ifdef _RTE_ - #ifdef RTE_CMSIS_RTOS2_RTX5_ARMV8M_NS - #define DOMAIN_NS 1 - #endif - #endif + // Mbed OS patch: Exclude RTE_Components.h and RTX_Config.h inclusion in .S files + #define RTX_CONFIG_H_ + #undef _RTE_ + #include "rtx_def.h" #ifndef DOMAIN_NS #define DOMAIN_NS 0 @@ -54,6 +53,10 @@ .equ TCB_SF_OFS, 34 // TCB.stack_frame offset .equ TCB_TZM_OFS, 64 // TCB.tz_memory offset + .equ FPCCR, 0xE000EF34 // FPCCR Address + + .equ osRtxErrorStackOverflow, 1 // Stack overflow + .section ".rodata" .global irqRtxLib // Non weak library reference irqRtxLib: @@ -63,6 +66,7 @@ irqRtxLib: .thumb .section ".text" .align 2 + .eabi_attribute Tag_ABI_align_preserved, 1 .thumb_func @@ -72,115 +76,165 @@ irqRtxLib: .cantunwind SVC_Handler: - TST LR,#0x04 // Determine return stack from EXC_RETURN bit 2 - ITE EQ - MRSEQ R0,MSP // Get MSP if return stack is MSP - MRSNE R0,PSP // Get PSP if return stack is PSP + tst lr,#0x04 // Determine return stack from EXC_RETURN bit 2 + ite eq + mrseq r0,msp // Get MSP if return stack is MSP + mrsne r0,psp // Get PSP if return stack is PSP - LDR R1,[R0,#24] // Load saved PC from stack - LDRB R1,[R1,#-2] // Load SVC number - CMP R1,#0 - BNE SVC_User // Branch if not SVC 0 + ldr r1,[r0,#24] // Load saved PC from stack + ldrb r1,[r1,#-2] // Load SVC number + cmp r1,#0 // Check SVC number + bne SVC_User // Branch if not SVC 0 - PUSH {R0,LR} // Save SP and EXC_RETURN - LDM R0,{R0-R3,R12} // Load function parameters and address from stack - BLX R12 // Call service function - POP {R12,LR} // Restore SP and EXC_RETURN - STM R12,{R0-R1} // Store function return values + push {r0,lr} // Save SP and EXC_RETURN + ldm r0,{r0-r3,r12} // Load function parameters and address from stack + blx r12 // Call service function + pop {r12,lr} // Restore SP and EXC_RETURN + stm r12,{r0-r1} // Store function return values SVC_Context: - LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run - LDM R3,{R1,R2} // Load osRtxInfo.thread.run: curr & next - CMP R1,R2 // Check if thread switch is required - IT EQ - BXEQ LR // Exit when threads are the same - - .if (FPU_USED == 1) || (MVE_USED == 1) - CBNZ R1,SVC_ContextSave // Branch if running thread is not deleted - TST LR,#0x10 // Check if extended stack frame - BNE SVC_ContextSwitch - LDR R1,=0xE000EF34 // FPCCR Address - LDR R0,[R1] // Load FPCCR - BIC R0,R0,#1 // Clear LSPACT (Lazy state) - STR R0,[R1] // Store FPCCR - B SVC_ContextSwitch - .else - CBZ R1,SVC_ContextSwitch // Branch if running thread is deleted - .endif + ldr r3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.thread.run + ldm r3,{r1,r2} // Load osRtxInfo.thread.run: curr & next + cmp r1,r2 // Check if thread switch is required + it eq + bxeq lr // Exit when threads are the same + + str r2,[r3] // osRtxInfo.thread.run: curr = next + + .if (FPU_USED != 0) || (MVE_USED != 0) + cbnz r1,SVC_ContextSave // Branch if running thread is not deleted +SVC_FP_LazyState: + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + bne SVC_ContextRestore // Branch if not extended stack frame + ldr r3,=FPCCR // FPCCR Address + ldr r0,[r3] // Load FPCCR + bic r0,r0,#1 // Clear LSPACT (Lazy state preservation) + str r0,[r3] // Store FPCCR + b SVC_ContextRestore // Branch to context restore handling + .else + cbz r1,SVC_ContextRestore // Branch if running thread is deleted + .endif SVC_ContextSave: - #if (DOMAIN_NS == 1) - LDR R0,[R1,#TCB_TZM_OFS] // Load TrustZone memory identifier - CBZ R0,SVC_ContextSave1 // Branch if there is no secure context - PUSH {R1,R2,R3,LR} // Save registers and EXC_RETURN - BL TZ_StoreContext_S // Store secure context - POP {R1,R2,R3,LR} // Restore registers and EXC_RETURN - #endif - -SVC_ContextSave1: - MRS R0,PSP // Get PSP - STMDB R0!,{R4-R11} // Save R4..R11 - .if (FPU_USED == 1) || (MVE_USED == 1) - TST LR,#0x10 // Check if extended stack frame - IT EQ - VSTMDBEQ R0!,{S16-S31} // Save VFP S16.S31 - .endif - -SVC_ContextSave2: - STR R0,[R1,#TCB_SP_OFS] // Store SP - STRB LR,[R1,#TCB_SF_OFS] // Store stack frame information - -SVC_ContextSwitch: - STR R2,[R3] // osRtxInfo.thread.run: curr = next + #if (DOMAIN_NS != 0) + ldr r0,[r1,#TCB_TZM_OFS] // Load TrustZone memory identifier + cbz r0,SVC_ContextSave_NS // Branch if there is no secure context + push {r1,r2,r12,lr} // Save registers and EXC_RETURN + bl TZ_StoreContext_S // Store secure context + pop {r1,r2,r12,lr} // Restore registers and EXC_RETURN + #endif + +SVC_ContextSave_NS: + #if (DOMAIN_NS != 0) + tst lr,#0x40 // Check domain of interrupted thread + bne SVC_ContextSaveSP // Branch if secure + #endif + + #ifdef RTX_STACK_CHECK + sub r12,r12,#32 // Calculate SP: space for R4..R11 + .if (FPU_USED != 0) || (MVE_USED != 0) + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + it eq // If extended stack frame + subeq r12,r12,#64 // Additional space for S16..S31 + .endif + +SVC_ContextSaveSP: + str r12,[r1,#TCB_SP_OFS] // Store SP + strb lr, [r1,#TCB_SF_OFS] // Store stack frame information + + push {r1,r2} // Save osRtxInfo.thread.run: curr & next + mov r0,r1 // Parameter: osRtxInfo.thread.run.curr + bl osRtxThreadStackCheck // Check if thread stack is overrun + pop {r1,r2} // Restore osRtxInfo.thread.run: curr & next + cbnz r0,SVC_ContextSaveRegs // Branch when stack check is ok + + .if (FPU_USED != 0) || (MVE_USED != 0) + mov r4,r1 // Save osRtxInfo.thread.run.curr + .endif + mov r0,#osRtxErrorStackOverflow // Parameter: r0=code, r1=object_id + bl osRtxKernelErrorNotify // Call osRtxKernelErrorNotify + ldr r3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.thread.run + ldr r2,[r3,#4] // Load osRtxInfo.thread.run: next + str r2,[r3] // osRtxInfo.thread.run: curr = next + .if (FPU_USED != 0) || (MVE_USED != 0) + ldrb lr,[r4,#TCB_SF_OFS] // Load stack frame information + b SVC_FP_LazyState // Branch to FP lazy state handling + .else + b SVC_ContextRestore // Branch to context restore handling + .endif + +SVC_ContextSaveRegs: + ldrb lr,[r1,#TCB_SF_OFS] // Load stack frame information + #if (DOMAIN_NS != 0) + tst lr,#0x40 // Check domain of interrupted thread + bne SVC_ContextRestore // Branch if secure + #endif + ldr r12,[r1,#TCB_SP_OFS] // Load SP + .if (FPU_USED != 0) || (MVE_USED != 0) + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + it eq // If extended stack frame + vstmiaeq r12!,{s16-s31} // Save VFP S16..S31 + .endif + stm r12,{r4-r11} // Save R4..R11 + #else + stmdb r12!,{r4-r11} // Save R4..R11 + .if (FPU_USED != 0) || (MVE_USED != 0) + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + it eq // If extended stack frame + vstmdbeq r12!,{s16-s31} // Save VFP S16.S31 + .endif +SVC_ContextSaveSP: + str r12,[r1,#TCB_SP_OFS] // Store SP + strb lr, [r1,#TCB_SF_OFS] // Store stack frame information + #endif // RTX_STACK_CHECK SVC_ContextRestore: - #if (DOMAIN_NS == 1) - LDR R0,[R2,#TCB_TZM_OFS] // Load TrustZone memory identifier - CBZ R0,SVC_ContextRestore1 // Branch if there is no secure context - PUSH {R2,R3} // Save registers - BL TZ_LoadContext_S // Load secure context - POP {R2,R3} // Restore registers - #endif - -SVC_ContextRestore1: - LDR R0,[R2,#TCB_SM_OFS] // Load stack memory base - LDRB R1,[R2,#TCB_SF_OFS] // Load stack frame information - MSR PSPLIM,R0 // Set PSPLIM - LDR R0,[R2,#TCB_SP_OFS] // Load SP - ORR LR,R1,#0xFFFFFF00 // Set EXC_RETURN - - #if (DOMAIN_NS == 1) - TST LR,#0x40 // Check domain of interrupted thread - BNE SVC_ContextRestore2 // Branch if secure - #endif - - .if (FPU_USED == 1) || (MVE_USED == 1) - TST LR,#0x10 // Check if extended stack frame - IT EQ - VLDMIAEQ R0!,{S16-S31} // Restore VFP S16..S31 - .endif - LDMIA R0!,{R4-R11} // Restore R4..R11 - -SVC_ContextRestore2: - MSR PSP,R0 // Set PSP + #if (DOMAIN_NS != 0) + ldr r0,[r2,#TCB_TZM_OFS] // Load TrustZone memory identifier + cbz r0,SVC_ContextRestore_NS // Branch if there is no secure context + push {r2,r3} // Save registers + bl TZ_LoadContext_S // Load secure context + pop {r2,r3} // Restore registers + #endif + +SVC_ContextRestore_NS: + ldr r0,[r2,#TCB_SP_OFS] // Load SP + ldr r1,[r2,#TCB_SM_OFS] // Load stack memory base + msr psplim,r1 // Set PSPLIM + ldrb r1,[r2,#TCB_SF_OFS] // Load stack frame information + orn lr,r1,#0xFF // Set EXC_RETURN + #if (DOMAIN_NS != 0) + tst lr,#0x40 // Check domain of interrupted thread + bne SVC_ContextRestoreSP // Branch if secure + #endif + + .if (FPU_USED != 0) || (MVE_USED != 0) + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + it eq // If extended stack frame + vldmiaeq r0!,{s16-s31} // Restore VFP S16..S31 + .endif + ldmia r0!,{r4-r11} // Restore R4..R11 + +SVC_ContextRestoreSP: + msr psp,r0 // Set PSP SVC_Exit: - BX LR // Exit from handler + bx lr // Exit from handler SVC_User: - LDR R2,=osRtxUserSVC // Load address of SVC table - LDR R3,[R2] // Load SVC maximum number - CMP R1,R3 // Check SVC number range - BHI SVC_Exit // Branch if out of range + ldr r2,=osRtxUserSVC // Load address of SVC table + ldr r3,[r2] // Load SVC maximum number + cmp r1,r3 // Check SVC number range + bhi SVC_Exit // Branch if out of range - PUSH {R0,LR} // Save SP and EXC_RETURN - LDR R12,[R2,R1,LSL #2] // Load address of SVC function - LDM R0,{R0-R3} // Load function parameters from stack - BLX R12 // Call service function - POP {R12,LR} // Restore SP and EXC_RETURN - STR R0,[R12] // Store function return value + push {r0,lr} // Save SP and EXC_RETURN + ldr r12,[r2,r1,lsl #2] // Load address of SVC function + ldm r0,{r0-r3} // Load function parameters from stack + blx r12 // Call service function + pop {r12,lr} // Restore SP and EXC_RETURN + str r0,[r12] // Store function return value - BX LR // Return from handler + bx lr // Return from handler .fnend .size SVC_Handler, .-SVC_Handler @@ -193,10 +247,11 @@ SVC_User: .cantunwind PendSV_Handler: - PUSH {R0,LR} // Save EXC_RETURN - BL osRtxPendSV_Handler // Call osRtxPendSV_Handler - POP {R0,LR} // Restore EXC_RETURN - B Sys_Context + push {r0,lr} // Save EXC_RETURN + bl osRtxPendSV_Handler // Call osRtxPendSV_Handler + pop {r0,lr} // Restore EXC_RETURN + mrs r12,psp // Save PSP to R12 + b SVC_Context // Branch to context handling .fnend .size PendSV_Handler, .-PendSV_Handler @@ -209,95 +264,14 @@ PendSV_Handler: .cantunwind SysTick_Handler: - PUSH {R0,LR} // Save EXC_RETURN - BL osRtxTick_Handler // Call osRtxTick_Handler - POP {R0,LR} // Restore EXC_RETURN - B Sys_Context - - .fnend - .size SysTick_Handler, .-SysTick_Handler - - - .thumb_func - .type Sys_Context, %function - .global Sys_Context - .fnstart - .cantunwind -Sys_Context: - - LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run - LDM R3,{R1,R2} // Load osRtxInfo.thread.run: curr & next - CMP R1,R2 // Check if thread switch is required - IT EQ - BXEQ LR // Exit when threads are the same - -Sys_ContextSave: - #if (DOMAIN_NS == 1) - LDR R0,[R1,#TCB_TZM_OFS] // Load TrustZone memory identifier - CBZ R0,Sys_ContextSave1 // Branch if there is no secure context - PUSH {R1,R2,R3,LR} // Save registers and EXC_RETURN - BL TZ_StoreContext_S // Store secure context - POP {R1,R2,R3,LR} // Restore registers and EXC_RETURN - -Sys_ContextSave1: - TST LR,#0x40 // Check domain of interrupted thread - IT NE - MRSNE R0,PSP // Get PSP - BNE Sys_ContextSave3 // Branch if secure - #endif - -Sys_ContextSave2: - MRS R0,PSP // Get PSP - STMDB R0!,{R4-R11} // Save R4..R11 - .if (FPU_USED == 1) || (MVE_USED == 1) - TST LR,#0x10 // Check if extended stack frame - IT EQ - VSTMDBEQ R0!,{S16-S31} // Save VFP S16.S31 - .endif - -Sys_ContextSave3: - STR R0,[R1,#TCB_SP_OFS] // Store SP - STRB LR,[R1,#TCB_SF_OFS] // Store stack frame information - -Sys_ContextSwitch: - STR R2,[R3] // osRtxInfo.run: curr = next - -Sys_ContextRestore: - #if (DOMAIN_NS == 1) - LDR R0,[R2,#TCB_TZM_OFS] // Load TrustZone memory identifier - CBZ R0,Sys_ContextRestore1 // Branch if there is no secure context - PUSH {R2,R3} // Save registers - BL TZ_LoadContext_S // Load secure context - POP {R2,R3} // Restore registers - #endif - -Sys_ContextRestore1: - LDR R0,[R2,#TCB_SM_OFS] // Load stack memory base - LDRB R1,[R2,#TCB_SF_OFS] // Load stack frame information - MSR PSPLIM,R0 // Set PSPLIM - LDR R0,[R2,#TCB_SP_OFS] // Load SP - ORR LR,R1,#0xFFFFFF00 // Set EXC_RETURN - - #if (DOMAIN_NS == 1) - TST LR,#0x40 // Check domain of interrupted thread - BNE Sys_ContextRestore2 // Branch if secure - #endif - - .if (FPU_USED == 1) || (MVE_USED == 1) - TST LR,#0x10 // Check if extended stack frame - IT EQ - VLDMIAEQ R0!,{S16-S31} // Restore VFP S16..S31 - .endif - LDMIA R0!,{R4-R11} // Restore R4..R11 - -Sys_ContextRestore2: - MSR PSP,R0 // Set PSP - -Sys_ContextExit: - BX LR // Exit from handler + push {r0,lr} // Save EXC_RETURN + bl osRtxTick_Handler // Call osRtxTick_Handler + pop {r0,lr} // Restore EXC_RETURN + mrs r12,psp // Save PSP to R12 + b SVC_Context // Branch to context handling .fnend - .size Sys_Context, .-Sys_Context + .size SysTick_Handler, .-SysTick_Handler .end diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_RTOS_M4_M7/irq_cm4f.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_RTOS_M4_M7/irq_cm4f.S index b5c68ad2fe1..c0a47974347 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_RTOS_M4_M7/irq_cm4f.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_RTOS_M4_M7/irq_cm4f.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -18,7 +18,7 @@ * ----------------------------------------------------------------------------- * * Project: CMSIS-RTOS RTX - * Title: Cortex-M4F Exception handlers + * Title: ARMv7-M Exception handlers * * ----------------------------------------------------------------------------- */ @@ -26,10 +26,25 @@ .syntax unified + // Mbed OS patch: Exclude RTE_Components.h and RTX_Config.h inclusion in .S files + #define RTX_CONFIG_H_ + #undef _RTE_ + #include "rtx_def.h" + + #if (defined(__ARM_FP) && (__ARM_FP > 0)) + .equ FPU_USED, 1 + #else + .equ FPU_USED, 0 + #endif + .equ I_T_RUN_OFS, 20 // osRtxInfo.thread.run offset .equ TCB_SP_OFS, 56 // TCB.SP offset .equ TCB_SF_OFS, 34 // TCB.stack_frame offset + .equ FPCCR, 0xE000EF34 // FPCCR Address + + .equ osRtxErrorStackOverflow, 1 // Stack overflow + .section ".rodata" .global irqRtxLib // Non weak library reference irqRtxLib: @@ -39,6 +54,7 @@ irqRtxLib: .thumb .section ".text" .align 2 + .eabi_attribute Tag_ABI_align_preserved, 1 .thumb_func @@ -48,83 +64,128 @@ irqRtxLib: .cantunwind SVC_Handler: - TST LR,#0x04 // Determine return stack from EXC_RETURN bit 2 - ITE EQ - MRSEQ R0,MSP // Get MSP if return stack is MSP - MRSNE R0,PSP // Get PSP if return stack is PSP + tst lr,#0x04 // Determine return stack from EXC_RETURN bit 2 + ite eq + mrseq r0,msp // Get MSP if return stack is MSP + mrsne r0,psp // Get PSP if return stack is PSP - LDR R1,[R0,#24] // Load saved PC from stack - LDRB R1,[R1,#-2] // Load SVC number - CBNZ R1,SVC_User // Branch if not SVC 0 + ldr r1,[r0,#24] // Load saved PC from stack + ldrb r1,[r1,#-2] // Load SVC number + cmp r1,#0 // Check SVC number + bne SVC_User // Branch if not SVC 0 - PUSH {R0,LR} // Save SP and EXC_RETURN - LDM R0,{R0-R3,R12} // Load function parameters and address from stack - BLX R12 // Call service function - POP {R12,LR} // Restore SP and EXC_RETURN - STM R12,{R0-R1} // Store function return values + push {r0,lr} // Save SP and EXC_RETURN + ldm r0,{r0-r3,r12} // Load function parameters and address from stack + blx r12 // Call service function + pop {r12,lr} // Restore SP and EXC_RETURN + stm r12,{r0-r1} // Store function return values SVC_Context: - LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run - LDM R3,{R1,R2} // Load osRtxInfo.thread.run: curr & next - CMP R1,R2 // Check if thread switch is required - IT EQ - BXEQ LR // Exit when threads are the same - - CBNZ R1,SVC_ContextSave // Branch if running thread is not deleted - TST LR,#0x10 // Check if extended stack frame - BNE SVC_ContextSwitch -#ifdef __FPU_PRESENT - LDR R1,=0xE000EF34 // FPCCR Address - LDR R0,[R1] // Load FPCCR - BIC R0,R0,#1 // Clear LSPACT (Lazy state) - STR R0,[R1] // Store FPCCR - B SVC_ContextSwitch -#endif + ldr r3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.thread.run + ldm r3,{r1,r2} // Load osRtxInfo.thread.run: curr & next + cmp r1,r2 // Check if thread switch is required + it eq + bxeq lr // Exit when threads are the same + + str r2,[r3] // osRtxInfo.thread.run: curr = next + + .if (FPU_USED != 0) + cbnz r1,SVC_ContextSave // Branch if running thread is not deleted +SVC_FP_LazyState: + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + bne SVC_ContextRestore // Branch if not extended stack frame + ldr r3,=FPCCR // FPCCR Address + ldr r0,[r3] // Load FPCCR + bic r0,r0,#1 // Clear LSPACT (Lazy state preservation) + str r0,[r3] // Store FPCCR + b SVC_ContextRestore // Branch to context restore handling + .else + cbz r1,SVC_ContextRestore // Branch if running thread is deleted + .endif SVC_ContextSave: - STMDB R12!,{R4-R11} // Save R4..R11 -#ifdef __FPU_PRESENT - TST LR,#0x10 // Check if extended stack frame - IT EQ - VSTMDBEQ R12!,{S16-S31} // Save VFP S16.S31 -#endif - - STR R12,[R1,#TCB_SP_OFS] // Store SP - STRB LR, [R1,#TCB_SF_OFS] // Store stack frame information - -SVC_ContextSwitch: - STR R2,[R3] // osRtxInfo.thread.run: curr = next + #ifdef RTX_STACK_CHECK + sub r12,r12,#32 // Calculate SP: space for R4..R11 + .if (FPU_USED != 0) + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + it eq // If extended stack frame + subeq r12,r12,#64 // Additional space for S16..S31 + strb lr, [r1,#TCB_SF_OFS] // Store stack frame information + .endif + str r12,[r1,#TCB_SP_OFS] // Store SP + + push {r1,r2} // Save osRtxInfo.thread.run: curr & next + mov r0,r1 // Parameter: osRtxInfo.thread.run.curr + bl osRtxThreadStackCheck // Check if thread stack is overrun + pop {r1,r2} // Restore osRtxInfo.thread.run: curr & next + cbnz r0,SVC_ContextSaveRegs // Branch when stack check is ok + + .if (FPU_USED != 0) + mov r4,r1 // Save osRtxInfo.thread.run.curr + .endif + mov r0,#osRtxErrorStackOverflow // Parameter: r0=code, r1=object_id + bl osRtxKernelErrorNotify // Call osRtxKernelErrorNotify + ldr r3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.thread.run + ldr r2,[r3,#4] // Load osRtxInfo.thread.run: next + str r2,[r3] // osRtxInfo.thread.run: curr = next + .if (FPU_USED != 0) + ldrb lr,[r4,#TCB_SF_OFS] // Load stack frame information + b SVC_FP_LazyState // Branch to FP lazy state handling + .else + b SVC_ContextRestore // Branch to context restore handling + .endif + +SVC_ContextSaveRegs: + ldr r12,[r1,#TCB_SP_OFS] // Load SP + .if (FPU_USED != 0) + ldrb lr, [r1,#TCB_SF_OFS] // Load stack frame information + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + it eq // If extended stack frame + vstmiaeq r12!,{s16-s31} // Save VFP S16..S31 + .endif + stm r12,{r4-r11} // Save R4..R11 + #else + stmdb r12!,{r4-r11} // Save R4..R11 + .if (FPU_USED != 0) + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + it eq // If extended stack frame + vstmdbeq r12!,{s16-s31} // Save VFP S16.S31 + strb lr, [r1,#TCB_SF_OFS] // Store stack frame information + .endif + str r12,[r1,#TCB_SP_OFS] // Store SP + #endif // RTX_STACK_CHECK SVC_ContextRestore: - LDRB R1,[R2,#TCB_SF_OFS] // Load stack frame information - LDR R0,[R2,#TCB_SP_OFS] // Load SP - ORR LR,R1,#0xFFFFFF00 // Set EXC_RETURN - -#ifdef __FPU_PRESENT - TST LR,#0x10 // Check if extended stack frame - IT EQ - VLDMIAEQ R0!,{S16-S31} // Restore VFP S16..S31 -#endif - LDMIA R0!,{R4-R11} // Restore R4..R11 - MSR PSP,R0 // Set PSP + ldr r0,[r2,#TCB_SP_OFS] // Load SP + .if (FPU_USED != 0) + ldrb r1,[r2,#TCB_SF_OFS] // Load stack frame information + orn lr,r1,#0xFF // Set EXC_RETURN + tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4 + it eq // If extended stack frame + vldmiaeq r0!,{s16-s31} // Restore VFP S16..S31 + .else + mvn lr,#~0xFFFFFFFD // Set EXC_RETURN value + .endif + ldmia r0!,{r4-r11} // Restore R4..R11 + msr psp,r0 // Set PSP SVC_Exit: - BX LR // Exit from handler + bx lr // Exit from handler SVC_User: - LDR R2,=osRtxUserSVC // Load address of SVC table - LDR R3,[R2] // Load SVC maximum number - CMP R1,R3 // Check SVC number range - BHI SVC_Exit // Branch if out of range + ldr r2,=osRtxUserSVC // Load address of SVC table + ldr r3,[r2] // Load SVC maximum number + cmp r1,r3 // Check SVC number range + bhi SVC_Exit // Branch if out of range - PUSH {R0,LR} // Save SP and EXC_RETURN - LDR R12,[R2,R1,LSL #2] // Load address of SVC function - LDM R0,{R0-R3} // Load function parameters from stack - BLX R12 // Call service function - POP {R12,LR} // Restore SP and EXC_RETURN - STR R0,[R12] // Store function return value + push {r0,lr} // Save SP and EXC_RETURN + ldr r12,[r2,r1,lsl #2] // Load address of SVC function + ldm r0,{r0-r3} // Load function parameters from stack + blx r12 // Call service function + pop {r12,lr} // Restore SP and EXC_RETURN + str r0,[r12] // Store function return value - BX LR // Return from handler + bx lr // Return from handler .fnend .size SVC_Handler, .-SVC_Handler @@ -137,11 +198,11 @@ SVC_User: .cantunwind PendSV_Handler: - PUSH {R0,LR} // Save EXC_RETURN - BL osRtxPendSV_Handler // Call osRtxPendSV_Handler - POP {R0,LR} // Restore EXC_RETURN - MRS R12,PSP - B SVC_Context + push {r0,lr} // Save EXC_RETURN + bl osRtxPendSV_Handler // Call osRtxPendSV_Handler + pop {r0,lr} // Restore EXC_RETURN + mrs r12,psp // Save PSP to R12 + b SVC_Context // Branch to context handling .fnend .size PendSV_Handler, .-PendSV_Handler @@ -154,11 +215,11 @@ PendSV_Handler: .cantunwind SysTick_Handler: - PUSH {R0,LR} // Save EXC_RETURN - BL osRtxTick_Handler // Call osRtxTick_Handler - POP {R0,LR} // Restore EXC_RETURN - MRS R12,PSP - B SVC_Context + push {r0,lr} // Save EXC_RETURN + bl osRtxTick_Handler // Call osRtxTick_Handler + pop {r0,lr} // Restore EXC_RETURN + mrs r12,psp // Save PSP to R12 + b SVC_Context // Branch to context handling .fnend .size SysTick_Handler, .-SysTick_Handler diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_CORTEX_A/irq_ca.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_CORTEX_A/irq_ca.S index 975b30dcd67..9e27930a0e7 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_CORTEX_A/irq_ca.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_CORTEX_A/irq_ca.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2013-2018 Arm Limited. All rights reserved. +; * Copyright (c) 2013-2021 Arm Limited. All rights reserved. ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -18,12 +18,13 @@ ; * ----------------------------------------------------------------------------- ; * ; * Project: CMSIS-RTOS RTX -; * Title: Cortex-A Exception handlers +; * Title: ARMv7-A Exception handlers ; * ; * ----------------------------------------------------------------------------- ; */ - NAME irq_ca.s + NAME irq_armv7a.s + MODE_FIQ EQU 0x11 MODE_IRQ EQU 0x12 @@ -352,16 +353,16 @@ osRtxContextSave STMDB R1!, {R2,R12} ; Push FPSCR, maintain 8-byte alignment VSTMDB R1!, {D0-D15} ; Save D0-D15 - #ifdef __ARM_ADVANCED_SIMD__ + #ifdef __ARM_ADVANCED_SIMD__ VSTMDB R1!, {D16-D31} ; Save D16-D31 - #endif + #endif LDRB R2, [LR, #TCB_SP_FRAME] ; Load osRtxInfo.thread.run.curr frame info - #ifdef __ARM_ADVANCED_SIMD__ + #ifdef __ARM_ADVANCED_SIMD__ ORR R2, R2, #4 ; NEON state - #else + #else ORR R2, R2, #2 ; VFP state - #endif + #endif STRB R2, [LR, #TCB_SP_FRAME] ; Store VFP/NEON state osRtxContextSave1 @@ -413,9 +414,9 @@ osRtxContextRestore MCR p15, 0, R2, c1, c0, 2 ; Write CPACR BEQ osRtxContextRestore1 ; No VFP ISB ; Sync if VFP was enabled - #ifdef __ARM_ADVANCED_SIMD__ + #ifdef __ARM_ADVANCED_SIMD__ VLDMIA LR!, {D16-D31} ; Restore D16-D31 - #endif + #endif VLDMIA LR!, {D0-D15} ; Restore D0-D15 LDR R2, [LR] VMSR FPSCR, R2 ; Restore FPSCR diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M0/irq_cm0.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M0/irq_cm0.S index 3ca51f67012..0a6ae7da9bd 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M0/irq_cm0.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M0/irq_cm0.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2013-2018 Arm Limited. All rights reserved. +; * Copyright (c) 2013-2021 Arm Limited. All rights reserved. ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -18,18 +18,22 @@ ; * ----------------------------------------------------------------------------- ; * ; * Project: CMSIS-RTOS RTX -; * Title: Cortex-M0 Exception handlers +; * Title: ARMv6-M Exception handlers ; * ; * ----------------------------------------------------------------------------- ; */ - NAME irq_cm0.s + NAME irq_armv6m.s + I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset TCB_SP_OFS EQU 56 ; TCB.SP offset +osRtxErrorStackOverflow\ + EQU 1 ; Stack overflow + PRESERVE8 SECTION .rodata:DATA:NOROOT(2) @@ -47,6 +51,10 @@ SVC_Handler EXPORT SVC_Handler IMPORT osRtxUserSVC IMPORT osRtxInfo + #ifdef RTX_STACK_CHECK + IMPORT osRtxThreadStackCheck + IMPORT osRtxKernelErrorNotify + #endif MOV R0,LR LSRS R0,R0,#3 ; Determine return stack from EXC_RETURN bit 2 @@ -57,7 +65,7 @@ SVC_Number LDR R1,[R0,#24] ; Load saved PC from stack SUBS R1,R1,#2 ; Point to SVC instruction LDRB R1,[R1] ; Load SVC number - CMP R1,#0 + CMP R1,#0 ; Check SVC number BNE SVC_User ; Branch if not SVC 0 PUSH {R0,LR} ; Save SP and EXC_RETURN @@ -68,18 +76,42 @@ SVC_Number MOV LR,R3 ; Set EXC_RETURN SVC_Context - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run + LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.thread.run LDMIA R3!,{R1,R2} ; Load osRtxInfo.thread.run: curr & next CMP R1,R2 ; Check if thread switch is required BEQ SVC_Exit ; Branch when threads are the same + SUBS R3,R3,#8 ; Adjust address + STR R2,[R3] ; osRtxInfo.thread.run: curr = next CMP R1,#0 - BEQ SVC_ContextSwitch ; Branch if running thread is deleted + BEQ SVC_ContextRestore ; Branch if running thread is deleted SVC_ContextSave MRS R0,PSP ; Get PSP - SUBS R0,R0,#32 ; Calculate SP + SUBS R0,R0,#32 ; Calculate SP: space for R4..R11 STR R0,[R1,#TCB_SP_OFS] ; Store SP + + #ifdef RTX_STACK_CHECK + + PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next + MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr + BL osRtxThreadStackCheck ; Check if thread stack is overrun + POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next + CMP R0,#0 + BNE SVC_ContextSaveRegs ; Branch when stack check is ok + + MOVS R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id + BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify + LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run + LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next + STR R2,[R3] ; osRtxInfo.thread.run: curr = next + B SVC_ContextRestore ; Branch to context restore handling + +SVC_ContextSaveRegs + LDR R0,[R1,#TCB_SP_OFS] ; Load SP + + #endif + STMIA R0!,{R4-R7} ; Save R4..R7 MOV R4,R8 MOV R5,R9 @@ -87,10 +119,6 @@ SVC_ContextSave MOV R7,R11 STMIA R0!,{R4-R7} ; Save R8..R11 -SVC_ContextSwitch - SUBS R3,R3,#8 ; Adjust address - STR R2,[R3] ; osRtxInfo.thread.run: curr = next - SVC_ContextRestore LDR R0,[R2,#TCB_SP_OFS] ; Load SP ADDS R0,R0,#16 ; Adjust address @@ -103,7 +131,7 @@ SVC_ContextRestore SUBS R0,R0,#32 ; Adjust address LDMIA R0!,{R4-R7} ; Restore R4..R7 - MOVS R0,#~0xFFFFFFFD + MOVS R0,#2 ; Binary complement of 0xFFFFFFFD MVNS R0,R0 ; Set EXC_RETURN value BX R0 ; Exit from handler @@ -141,7 +169,7 @@ PendSV_Handler BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler POP {R0,R1} ; Restore EXC_RETURN MOV LR,R1 ; Set EXC_RETURN - B SVC_Context + B SVC_Context ; Branch to context handling SysTick_Handler @@ -152,7 +180,7 @@ SysTick_Handler BL osRtxTick_Handler ; Call osRtxTick_Handler POP {R0,R1} ; Restore EXC_RETURN MOV LR,R1 ; Set EXC_RETURN - B SVC_Context + B SVC_Context ; Branch to context handling END diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M0P/irq_cm0.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M0P/irq_cm0.S index 3ca51f67012..0a6ae7da9bd 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M0P/irq_cm0.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M0P/irq_cm0.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2013-2018 Arm Limited. All rights reserved. +; * Copyright (c) 2013-2021 Arm Limited. All rights reserved. ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -18,18 +18,22 @@ ; * ----------------------------------------------------------------------------- ; * ; * Project: CMSIS-RTOS RTX -; * Title: Cortex-M0 Exception handlers +; * Title: ARMv6-M Exception handlers ; * ; * ----------------------------------------------------------------------------- ; */ - NAME irq_cm0.s + NAME irq_armv6m.s + I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset TCB_SP_OFS EQU 56 ; TCB.SP offset +osRtxErrorStackOverflow\ + EQU 1 ; Stack overflow + PRESERVE8 SECTION .rodata:DATA:NOROOT(2) @@ -47,6 +51,10 @@ SVC_Handler EXPORT SVC_Handler IMPORT osRtxUserSVC IMPORT osRtxInfo + #ifdef RTX_STACK_CHECK + IMPORT osRtxThreadStackCheck + IMPORT osRtxKernelErrorNotify + #endif MOV R0,LR LSRS R0,R0,#3 ; Determine return stack from EXC_RETURN bit 2 @@ -57,7 +65,7 @@ SVC_Number LDR R1,[R0,#24] ; Load saved PC from stack SUBS R1,R1,#2 ; Point to SVC instruction LDRB R1,[R1] ; Load SVC number - CMP R1,#0 + CMP R1,#0 ; Check SVC number BNE SVC_User ; Branch if not SVC 0 PUSH {R0,LR} ; Save SP and EXC_RETURN @@ -68,18 +76,42 @@ SVC_Number MOV LR,R3 ; Set EXC_RETURN SVC_Context - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run + LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.thread.run LDMIA R3!,{R1,R2} ; Load osRtxInfo.thread.run: curr & next CMP R1,R2 ; Check if thread switch is required BEQ SVC_Exit ; Branch when threads are the same + SUBS R3,R3,#8 ; Adjust address + STR R2,[R3] ; osRtxInfo.thread.run: curr = next CMP R1,#0 - BEQ SVC_ContextSwitch ; Branch if running thread is deleted + BEQ SVC_ContextRestore ; Branch if running thread is deleted SVC_ContextSave MRS R0,PSP ; Get PSP - SUBS R0,R0,#32 ; Calculate SP + SUBS R0,R0,#32 ; Calculate SP: space for R4..R11 STR R0,[R1,#TCB_SP_OFS] ; Store SP + + #ifdef RTX_STACK_CHECK + + PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next + MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr + BL osRtxThreadStackCheck ; Check if thread stack is overrun + POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next + CMP R0,#0 + BNE SVC_ContextSaveRegs ; Branch when stack check is ok + + MOVS R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id + BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify + LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run + LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next + STR R2,[R3] ; osRtxInfo.thread.run: curr = next + B SVC_ContextRestore ; Branch to context restore handling + +SVC_ContextSaveRegs + LDR R0,[R1,#TCB_SP_OFS] ; Load SP + + #endif + STMIA R0!,{R4-R7} ; Save R4..R7 MOV R4,R8 MOV R5,R9 @@ -87,10 +119,6 @@ SVC_ContextSave MOV R7,R11 STMIA R0!,{R4-R7} ; Save R8..R11 -SVC_ContextSwitch - SUBS R3,R3,#8 ; Adjust address - STR R2,[R3] ; osRtxInfo.thread.run: curr = next - SVC_ContextRestore LDR R0,[R2,#TCB_SP_OFS] ; Load SP ADDS R0,R0,#16 ; Adjust address @@ -103,7 +131,7 @@ SVC_ContextRestore SUBS R0,R0,#32 ; Adjust address LDMIA R0!,{R4-R7} ; Restore R4..R7 - MOVS R0,#~0xFFFFFFFD + MOVS R0,#2 ; Binary complement of 0xFFFFFFFD MVNS R0,R0 ; Set EXC_RETURN value BX R0 ; Exit from handler @@ -141,7 +169,7 @@ PendSV_Handler BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler POP {R0,R1} ; Restore EXC_RETURN MOV LR,R1 ; Set EXC_RETURN - B SVC_Context + B SVC_Context ; Branch to context handling SysTick_Handler @@ -152,7 +180,7 @@ SysTick_Handler BL osRtxTick_Handler ; Call osRtxTick_Handler POP {R0,R1} ; Restore EXC_RETURN MOV LR,R1 ; Set EXC_RETURN - B SVC_Context + B SVC_Context ; Branch to context handling END diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M23/irq_armv8mbl_common.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M23/irq_armv8mbl_common.S index a0e6918fb7f..ee26d8edd74 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M23/irq_armv8mbl_common.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M23/irq_armv8mbl_common.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2016-2020 Arm Limited. All rights reserved. +; * Copyright (c) 2016-2021 Arm Limited. All rights reserved. ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -18,12 +18,16 @@ ; * ----------------------------------------------------------------------------- ; * ; * Project: CMSIS-RTOS RTX -; * Title: ARMv8M Baseline Exception handlers +; * Title: ARMv8-M Baseline Exception handlers ; * ; * ----------------------------------------------------------------------------- ; */ + NAME irq_armv8mbl.s + + + #ifndef DOMAIN_NS #define DOMAIN_NS 0 #endif @@ -34,6 +38,9 @@ TCB_SP_OFS EQU 56 ; TCB.SP offset TCB_SF_OFS EQU 34 ; TCB.stack_frame offset TCB_TZM_OFS EQU 64 ; TCB.tz_memory offset +osRtxErrorStackOverflow\ + EQU 1 ; Stack overflow + PRESERVE8 @@ -51,10 +58,14 @@ SVC_Handler EXPORT SVC_Handler IMPORT osRtxUserSVC IMPORT osRtxInfo - #if (DOMAIN_NS == 1) + #ifdef RTX_STACK_CHECK + IMPORT osRtxThreadStackCheck + IMPORT osRtxKernelErrorNotify + #endif + #if (DOMAIN_NS != 0) IMPORT TZ_LoadContext_S IMPORT TZ_StoreContext_S - #endif + #endif MOV R0,LR LSRS R0,R0,#3 ; Determine return stack from EXC_RETURN bit 2 @@ -65,95 +76,136 @@ SVC_Number LDR R1,[R0,#24] ; Load saved PC from stack SUBS R1,R1,#2 ; Point to SVC instruction LDRB R1,[R1] ; Load SVC number - CMP R1,#0 + CMP R1,#0 ; Check SVC number BNE SVC_User ; Branch if not SVC 0 PUSH {R0,LR} ; Save SP and EXC_RETURN - LDM R0,{R0-R3} ; Load function parameters from stack + LDMIA R0,{R0-R3} ; Load function parameters from stack BLX R7 ; Call service function POP {R2,R3} ; Restore SP and EXC_RETURN STMIA R2!,{R0-R1} ; Store function return values MOV LR,R3 ; Set EXC_RETURN SVC_Context - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run + LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.thread.run LDMIA R3!,{R1,R2} ; Load osRtxInfo.thread.run: curr & next CMP R1,R2 ; Check if thread switch is required BEQ SVC_Exit ; Branch when threads are the same - CBZ R1,SVC_ContextSwitch ; Branch if running thread is deleted + SUBS R3,R3,#8 ; Adjust address + STR R2,[R3] ; osRtxInfo.thread.run: curr = next + CBZ R1,SVC_ContextRestore ; Branch if running thread is deleted SVC_ContextSave - #if (DOMAIN_NS == 1) + #if (DOMAIN_NS != 0) LDR R0,[R1,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,SVC_ContextSave1 ; Branch if there is no secure context + CBZ R0,SVC_ContextSave_NS ; Branch if there is no secure context PUSH {R1,R2,R3,R7} ; Save registers MOV R7,LR ; Get EXC_RETURN BL TZ_StoreContext_S ; Store secure context MOV LR,R7 ; Set EXC_RETURN POP {R1,R2,R3,R7} ; Restore registers - #endif + #endif -SVC_ContextSave1 +SVC_ContextSave_NS MRS R0,PSP ; Get PSP - SUBS R0,R0,#32 ; Calculate SP + #if (DOMAIN_NS != 0) + MOV R3,LR ; Get EXC_RETURN + LSLS R3,R3,#25 ; Check domain of interrupted thread + BMI SVC_ContextSaveSP ; Branch if secure + #endif + + #ifdef RTX_STACK_CHECK + SUBS R0,R0,#32 ; Calculate SP: space for R4..R11 + +SVC_ContextSaveSP STR R0,[R1,#TCB_SP_OFS] ; Store SP + MOV R3,LR ; Get EXC_RETURN + MOV R0,R1 ; osRtxInfo.thread.run.curr + ADDS R0,R0,#TCB_SF_OFS ; Adjust address + STRB R3,[R0] ; Store stack frame information + + PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next + MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr + BL osRtxThreadStackCheck ; Check if thread stack is overrun + POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next + CMP R0,#0 + BNE SVC_ContextSaveRegs ; Branch when stack check is ok + + MOVS R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id + BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify + LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run + LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next + STR R2,[R3] ; osRtxInfo.thread.run: curr = next + B SVC_ContextRestore ; Branch to context restore handling + +SVC_ContextSaveRegs + #if (DOMAIN_NS != 0) + MOV R0,R1 ; osRtxInfo.thread.run.curr + ADDS R0,R0,#TCB_SF_OFS ; Adjust address + LDRB R3,[R0] ; Load stack frame information + LSLS R3,R3,#25 ; Check domain of interrupted thread + BMI SVC_ContextRestore ; Branch if secure + #endif + LDR R0,[R1,#TCB_SP_OFS] ; Load SP STMIA R0!,{R4-R7} ; Save R4..R7 MOV R4,R8 MOV R5,R9 MOV R6,R10 MOV R7,R11 STMIA R0!,{R4-R7} ; Save R8..R11 - -SVC_ContextSave2 + #else + SUBS R0,R0,#32 ; Calculate SP: space for R4..R11 + STMIA R0!,{R4-R7} ; Save R4..R7 + MOV R4,R8 + MOV R5,R9 + MOV R6,R10 + MOV R7,R11 + STMIA R0!,{R4-R7} ; Save R8..R11 + SUBS R0,R0,#32 ; Adjust address +SVC_ContextSaveSP + STR R0,[R1,#TCB_SP_OFS] ; Store SP MOV R0,LR ; Get EXC_RETURN ADDS R1,R1,#TCB_SF_OFS ; Adjust address STRB R0,[R1] ; Store stack frame information - -SVC_ContextSwitch - SUBS R3,R3,#8 ; Adjust address - STR R2,[R3] ; osRtxInfo.thread.run: curr = next + #endif SVC_ContextRestore - #if (DOMAIN_NS == 1) + #if (DOMAIN_NS != 0) LDR R0,[R2,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,SVC_ContextRestore1 ; Branch if there is no secure context + CBZ R0,SVC_ContextRestore_NS ; Branch if there is no secure context PUSH {R2,R3} ; Save registers BL TZ_LoadContext_S ; Load secure context POP {R2,R3} ; Restore registers - #endif + #endif -SVC_ContextRestore1 - MOV R1,R2 - ADDS R1,R1,#TCB_SF_OFS ; Adjust address - LDRB R0,[R1] ; Load stack frame information - MOVS R1,#0xFF - MVNS R1,R1 ; R1=0xFFFFFF00 - ORRS R0,R1 - MOV LR,R0 ; Set EXC_RETURN - - #if (DOMAIN_NS == 1) - LSLS R0,R0,#25 ; Check domain of interrupted thread - BPL SVC_ContextRestore2 ; Branch if non-secure - LDR R0,[R2,#TCB_SP_OFS] ; Load SP - MSR PSP,R0 ; Set PSP - BX LR ; Exit from handler - #else +SVC_ContextRestore_NS LDR R0,[R2,#TCB_SM_OFS] ; Load stack memory base MSR PSPLIM,R0 ; Set PSPLIM - #endif - -SVC_ContextRestore2 + MOV R0,R2 ; osRtxInfo.thread.run.next + ADDS R0,R0,#TCB_SF_OFS ; Adjust address + LDRB R3,[R0] ; Load stack frame information + MOVS R0,#0xFF + MVNS R0,R0 ; R0=0xFFFFFF00 + ORRS R3,R3,R0 + MOV LR,R3 ; Set EXC_RETURN LDR R0,[R2,#TCB_SP_OFS] ; Load SP + #if (DOMAIN_NS != 0) + LSLS R3,R3,#25 ; Check domain of interrupted thread + BMI SVC_ContextRestoreSP ; Branch if secure + #endif ADDS R0,R0,#16 ; Adjust address LDMIA R0!,{R4-R7} ; Restore R8..R11 MOV R8,R4 MOV R9,R5 MOV R10,R6 MOV R11,R7 - MSR PSP,R0 ; Set PSP SUBS R0,R0,#32 ; Adjust address LDMIA R0!,{R4-R7} ; Restore R4..R7 + ADDS R0,R0,#16 ; Adjust address + +SVC_ContextRestoreSP + MSR PSP,R0 ; Set PSP SVC_Exit BX LR ; Exit from handler @@ -189,7 +241,7 @@ PendSV_Handler BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler POP {R0,R1} ; Restore EXC_RETURN MOV LR,R1 ; Set EXC_RETURN - B Sys_Context + B SVC_Context ; Branch to context handling SysTick_Handler @@ -200,104 +252,7 @@ SysTick_Handler BL osRtxTick_Handler ; Call osRtxTick_Handler POP {R0,R1} ; Restore EXC_RETURN MOV LR,R1 ; Set EXC_RETURN - B Sys_Context - - + B SVC_Context ; Branch to context handling -Sys_Context - EXPORT Sys_Context - IMPORT osRtxInfo - #if (DOMAIN_NS == 1) - IMPORT TZ_LoadContext_S - IMPORT TZ_StoreContext_S - #endif - - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run - LDM R3!,{R1,R2} ; Load osRtxInfo.thread.run: curr & next - CMP R1,R2 ; Check if thread switch is required - BEQ Sys_ContextExit ; Branch when threads are the same - -Sys_ContextSave - #if (DOMAIN_NS == 1) - LDR R0,[R1,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,Sys_ContextSave1 ; Branch if there is no secure context - PUSH {R1,R2,R3,R7} ; Save registers - MOV R7,LR ; Get EXC_RETURN - BL TZ_StoreContext_S ; Store secure context - MOV LR,R7 ; Set EXC_RETURN - POP {R1,R2,R3,R7} ; Restore registers - -Sys_ContextSave1 - MOV R0,LR ; Get EXC_RETURN - LSLS R0,R0,#25 ; Check domain of interrupted thread - BPL Sys_ContextSave2 ; Branch if non-secure - MRS R0,PSP ; Get PSP - STR R0,[R1,#TCB_SP_OFS] ; Store SP - B Sys_ContextSave3 - #endif - -Sys_ContextSave2 - MRS R0,PSP ; Get PSP - SUBS R0,R0,#32 ; Adjust address - STR R0,[R1,#TCB_SP_OFS] ; Store SP - STMIA R0!,{R4-R7} ; Save R4..R7 - MOV R4,R8 - MOV R5,R9 - MOV R6,R10 - MOV R7,R11 - STMIA R0!,{R4-R7} ; Save R8..R11 - -Sys_ContextSave3 - MOV R0,LR ; Get EXC_RETURN - ADDS R1,R1,#TCB_SF_OFS ; Adjust address - STRB R0,[R1] ; Store stack frame information - -Sys_ContextSwitch - SUBS R3,R3,#8 ; Adjust address - STR R2,[R3] ; osRtxInfo.run: curr = next - -Sys_ContextRestore - #if (DOMAIN_NS == 1) - LDR R0,[R2,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,Sys_ContextRestore1 ; Branch if there is no secure context - PUSH {R2,R3} ; Save registers - BL TZ_LoadContext_S ; Load secure context - POP {R2,R3} ; Restore registers - #endif - -Sys_ContextRestore1 - MOV R1,R2 - ADDS R1,R1,#TCB_SF_OFS ; Adjust offset - LDRB R0,[R1] ; Load stack frame information - MOVS R1,#0xFF - MVNS R1,R1 ; R1=0xFFFFFF00 - ORRS R0,R1 - MOV LR,R0 ; Set EXC_RETURN - - #if (DOMAIN_NS == 1) - LSLS R0,R0,#25 ; Check domain of interrupted thread - BPL Sys_ContextRestore2 ; Branch if non-secure - LDR R0,[R2,#TCB_SP_OFS] ; Load SP - MSR PSP,R0 ; Set PSP - BX LR ; Exit from handler - #else - LDR R0,[R2,#TCB_SM_OFS] ; Load stack memory base - MSR PSPLIM,R0 ; Set PSPLIM - #endif - -Sys_ContextRestore2 - LDR R0,[R2,#TCB_SP_OFS] ; Load SP - ADDS R0,R0,#16 ; Adjust address - LDMIA R0!,{R4-R7} ; Restore R8..R11 - MOV R8,R4 - MOV R9,R5 - MOV R10,R6 - MOV R11,R7 - MSR PSP,R0 ; Set PSP - SUBS R0,R0,#32 ; Adjust address - LDMIA R0!,{R4-R7} ; Restore R4..R7 - -Sys_ContextExit - BX LR ; Exit from handler END diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M3/irq_cm3.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M3/irq_cm3.S index 29fe1b727e6..46a6a67a596 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M3/irq_cm3.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M3/irq_cm3.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2013-2018 Arm Limited. All rights reserved. +; * Copyright (c) 2013-2021 Arm Limited. All rights reserved. ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -18,17 +18,30 @@ ; * ----------------------------------------------------------------------------- ; * ; * Project: CMSIS-RTOS RTX -; * Title: Cortex-M3 Exception handlers +; * Title: ARMv7-M Exception handlers ; * ; * ----------------------------------------------------------------------------- ; */ - NAME irq_cm3.s + NAME irq_armv7m.s + +#ifdef __ARMVFP__ +FPU_USED EQU 1 +#else +FPU_USED EQU 0 +#endif + I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset TCB_SP_OFS EQU 56 ; TCB.SP offset +TCB_SF_OFS EQU 34 ; TCB.stack_frame offset + +FPCCR EQU 0xE000EF34 ; FPCCR Address + +osRtxErrorStackOverflow\ + EQU 1 ; Stack overflow PRESERVE8 @@ -47,6 +60,10 @@ SVC_Handler EXPORT SVC_Handler IMPORT osRtxUserSVC IMPORT osRtxInfo + #ifdef RTX_STACK_CHECK + IMPORT osRtxThreadStackCheck + IMPORT osRtxKernelErrorNotify + #endif TST LR,#0x04 ; Determine return stack from EXC_RETURN bit 2 ITE EQ @@ -55,7 +72,8 @@ SVC_Handler LDR R1,[R0,#24] ; Load saved PC from stack LDRB R1,[R1,#-2] ; Load SVC number - CBNZ R1,SVC_User ; Branch if not SVC 0 + CMP R1,#0 ; Check SVC number + BNE SVC_User ; Branch if not SVC 0 PUSH {R0,LR} ; Save SP and EXC_RETURN LDM R0,{R0-R3,R12} ; Load function parameters and address from stack @@ -64,28 +82,94 @@ SVC_Handler STM R12,{R0-R1} ; Store function return values SVC_Context - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run + LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.thread.run LDM R3,{R1,R2} ; Load osRtxInfo.thread.run: curr & next CMP R1,R2 ; Check if thread switch is required IT EQ BXEQ LR ; Exit when threads are the same - CBZ R1,SVC_ContextSwitch ; Branch if running thread is deleted + STR R2,[R3] ; osRtxInfo.thread.run: curr = next + + #if (FPU_USED != 0) + CBNZ R1,SVC_ContextSave ; Branch if running thread is not deleted +SVC_FP_LazyState + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + BNE SVC_ContextRestore ; Branch if not extended stack frame + LDR R3,=FPCCR ; FPCCR Address + LDR R0,[R3] ; Load FPCCR + BIC R0,R0,#1 ; Clear LSPACT (Lazy state preservation) + STR R0,[R3] ; Store FPCCR + B SVC_ContextRestore ; Branch to context restore handling + #else + CBZ R1,SVC_ContextRestore ; Branch if running thread is deleted + #endif SVC_ContextSave - STMDB R12!,{R4-R11} ; Save R4..R11 + #ifdef RTX_STACK_CHECK + SUB R12,R12,#32 ; Calculate SP: space for R4..R11 + #if (FPU_USED != 0) + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + SUBEQ R12,R12,#64 ; Additional space for S16..S31 + STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information + #endif STR R12,[R1,#TCB_SP_OFS] ; Store SP -SVC_ContextSwitch + PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next + MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr + BL osRtxThreadStackCheck ; Check if thread stack is overrun + POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next + CBNZ R0,SVC_ContextSaveRegs ; Branch when stack check is ok + + #if (FPU_USED != 0) + MOV R4,R1 ; Save osRtxInfo.thread.run.curr + #endif + MOV R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id + BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify + LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run + LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next STR R2,[R3] ; osRtxInfo.thread.run: curr = next + #if (FPU_USED != 0) + LDRB LR,[R4,#TCB_SF_OFS] ; Load stack frame information + B SVC_FP_LazyState ; Branch to FP lazy state handling + #else + B SVC_ContextRestore ; Branch to context restore handling + #endif + +SVC_ContextSaveRegs + LDR R12,[R1,#TCB_SP_OFS] ; Load SP + #if (FPU_USED != 0) + LDRB LR, [R1,#TCB_SF_OFS] ; Load stack frame information + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + VSTMIAEQ R12!,{S16-S31} ; Save VFP S16..S31 + #endif + STM R12,{R4-R11} ; Save R4..R11 + #else + STMDB R12!,{R4-R11} ; Save R4..R11 + #if (FPU_USED != 0) + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + VSTMDBEQ R12!,{S16-S31} ; Save VFP S16.S31 + STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information + #endif + STR R12,[R1,#TCB_SP_OFS] ; Store SP + #endif SVC_ContextRestore LDR R0,[R2,#TCB_SP_OFS] ; Load SP + #if (FPU_USED != 0) + LDRB R1,[R2,#TCB_SF_OFS] ; Load stack frame information + ORN LR,R1,#0xFF ; Set EXC_RETURN + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + VLDMIAEQ R0!,{S16-S31} ; Restore VFP S16..S31 + #else + MVN LR,#~0xFFFFFFFD ; Set EXC_RETURN value + #endif LDMIA R0!,{R4-R11} ; Restore R4..R11 MSR PSP,R0 ; Set PSP - MVN LR,#~0xFFFFFFFD ; Set EXC_RETURN value - SVC_Exit BX LR ; Exit from handler @@ -112,8 +196,8 @@ PendSV_Handler PUSH {R0,LR} ; Save EXC_RETURN BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler POP {R0,LR} ; Restore EXC_RETURN - MRS R12,PSP - B SVC_Context + MRS R12,PSP ; Save PSP to R12 + B SVC_Context ; Branch to context handling SysTick_Handler @@ -123,8 +207,8 @@ SysTick_Handler PUSH {R0,LR} ; Save EXC_RETURN BL osRtxTick_Handler ; Call osRtxTick_Handler POP {R0,LR} ; Restore EXC_RETURN - MRS R12,PSP - B SVC_Context + MRS R12,PSP ; Save PSP to R12 + B SVC_Context ; Branch to context handling END diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M33/irq_armv8mml_common.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M33/irq_armv8mml_common.S index aa1cbc218fb..c8da9547dc5 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M33/irq_armv8mml_common.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_M33/irq_armv8mml_common.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2016-2020 Arm Limited. All rights reserved. +; * Copyright (c) 2016-2021 Arm Limited. All rights reserved. ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -18,12 +18,16 @@ ; * ----------------------------------------------------------------------------- ; * ; * Project: CMSIS-RTOS RTX -; * Title: ARMv8M Mainline Exception handlers +; * Title: ARMv8-M Mainline Exception handlers ; * ; * ----------------------------------------------------------------------------- ; */ + NAME irq_armv8mml.s + + + #ifndef DOMAIN_NS #define DOMAIN_NS 0 #endif @@ -46,6 +50,11 @@ TCB_SP_OFS EQU 56 ; TCB.SP offset TCB_SF_OFS EQU 34 ; TCB.stack_frame offset TCB_TZM_OFS EQU 64 ; TCB.tz_memory offset +FPCCR EQU 0xE000EF34 ; FPCCR Address + +osRtxErrorStackOverflow\ + EQU 1 ; Stack overflow + PRESERVE8 @@ -63,10 +72,14 @@ SVC_Handler EXPORT SVC_Handler IMPORT osRtxUserSVC IMPORT osRtxInfo - #if (DOMAIN_NS == 1) + #ifdef RTX_STACK_CHECK + IMPORT osRtxThreadStackCheck + IMPORT osRtxKernelErrorNotify + #endif + #if (DOMAIN_NS != 0) IMPORT TZ_LoadContext_S IMPORT TZ_StoreContext_S - #endif + #endif TST LR,#0x04 ; Determine return stack from EXC_RETURN bit 2 ITE EQ @@ -75,7 +88,7 @@ SVC_Handler LDR R1,[R0,#24] ; Load saved PC from stack LDRB R1,[R1,#-2] ; Load SVC number - CMP R1,#0 + CMP R1,#0 ; Check SVC number BNE SVC_User ; Branch if not SVC 0 PUSH {R0,LR} ; Save SP and EXC_RETURN @@ -85,79 +98,131 @@ SVC_Handler STM R12,{R0-R1} ; Store function return values SVC_Context - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run + LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.thread.run LDM R3,{R1,R2} ; Load osRtxInfo.thread.run: curr & next CMP R1,R2 ; Check if thread switch is required IT EQ BXEQ LR ; Exit when threads are the same - #if ((FPU_USED == 1) || (MVE_USED == 1)) + STR R2,[R3] ; osRtxInfo.thread.run: curr = next + + #if ((FPU_USED != 0) || (MVE_USED != 0)) CBNZ R1,SVC_ContextSave ; Branch if running thread is not deleted - TST LR,#0x10 ; Check if extended stack frame - BNE SVC_ContextSwitch - LDR R1,=0xE000EF34 ; FPCCR Address - LDR R0,[R1] ; Load FPCCR - BIC R0,R0,#1 ; Clear LSPACT (Lazy state) - STR R0,[R1] ; Store FPCCR - B SVC_ContextSwitch - #else - CBZ R1,SVC_ContextSwitch ; Branch if running thread is deleted - #endif +SVC_FP_LazyState + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + BNE SVC_ContextRestore ; Branch if not extended stack frame + LDR R3,=FPCCR ; FPCCR Address + LDR R0,[R3] ; Load FPCCR + BIC R0,R0,#1 ; Clear LSPACT (Lazy state preservation) + STR R0,[R3] ; Store FPCCR + B SVC_ContextRestore ; Branch to context restore handling + #else + CBZ R1,SVC_ContextRestore ; Branch if running thread is deleted + #endif SVC_ContextSave - #if (DOMAIN_NS == 1) + #if (DOMAIN_NS != 0) LDR R0,[R1,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,SVC_ContextSave1 ; Branch if there is no secure context - PUSH {R1,R2,R3,LR} ; Save registers and EXC_RETURN + CBZ R0,SVC_ContextSave_NS ; Branch if there is no secure context + PUSH {R1,R2,R12,LR} ; Save registers and EXC_RETURN BL TZ_StoreContext_S ; Store secure context - POP {R1,R2,R3,LR} ; Restore registers and EXC_RETURN - #endif - -SVC_ContextSave1 - MRS R0,PSP ; Get PSP - STMDB R0!,{R4-R11} ; Save R4..R11 - #if ((FPU_USED == 1) || (MVE_USED == 1)) - TST LR,#0x10 ; Check if extended stack frame - IT EQ - VSTMDBEQ R0!,{S16-S31} ; Save VFP S16.S31 - #endif - -SVC_ContextSave2 - STR R0,[R1,#TCB_SP_OFS] ; Store SP - STRB LR,[R1,#TCB_SF_OFS] ; Store stack frame information + POP {R1,R2,R12,LR} ; Restore registers and EXC_RETURN + #endif -SVC_ContextSwitch +SVC_ContextSave_NS + #if (DOMAIN_NS != 0) + TST LR,#0x40 ; Check domain of interrupted thread + BNE SVC_ContextSaveSP ; Branch if secure + #endif + + #ifdef RTX_STACK_CHECK + SUB R12,R12,#32 ; Calculate SP: space for R4..R11 + #if ((FPU_USED != 0) || (MVE_USED != 0)) + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + SUBEQ R12,R12,#64 ; Additional space for S16..S31 + #endif + +SVC_ContextSaveSP + STR R12,[R1,#TCB_SP_OFS] ; Store SP + STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information + + PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next + MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr + BL osRtxThreadStackCheck ; Check if thread stack is overrun + POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next + CBNZ R0,SVC_ContextSaveRegs ; Branch when stack check is ok + + #if ((FPU_USED != 0) || (MVE_USED != 0)) + MOV R4,R1 ; Save osRtxInfo.thread.run.curr + #endif + MOV R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id + BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify + LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run + LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next STR R2,[R3] ; osRtxInfo.thread.run: curr = next + #if ((FPU_USED != 0) || (MVE_USED != 0)) + LDRB LR,[R4,#TCB_SF_OFS] ; Load stack frame information + B SVC_FP_LazyState ; Branch to FP lazy state handling + #else + B SVC_ContextRestore ; Branch to context restore handling + #endif + +SVC_ContextSaveRegs + LDRB LR,[R1,#TCB_SF_OFS] ; Load stack frame information + #if (DOMAIN_NS != 0) + TST LR,#0x40 ; Check domain of interrupted thread + BNE SVC_ContextRestore ; Branch if secure + #endif + LDR R12,[R1,#TCB_SP_OFS] ; Load SP + #if ((FPU_USED != 0) || (MVE_USED != 0)) + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + VSTMIAEQ R12!,{S16-S31} ; Save VFP S16..S31 + #endif + STM R12,{R4-R11} ; Save R4..R11 + #else + STMDB R12!,{R4-R11} ; Save R4..R11 + #if ((FPU_USED != 0) || (MVE_USED != 0)) + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + VSTMDBEQ R12!,{S16-S31} ; Save VFP S16.S31 + #endif + +SVC_ContextSaveSP + STR R12,[R1,#TCB_SP_OFS] ; Store SP + STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information + #endif SVC_ContextRestore - #if (DOMAIN_NS == 1) + #if (DOMAIN_NS != 0) LDR R0,[R2,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,SVC_ContextRestore1 ; Branch if there is no secure context + CBZ R0,SVC_ContextRestore_NS; Branch if there is no secure context PUSH {R2,R3} ; Save registers BL TZ_LoadContext_S ; Load secure context POP {R2,R3} ; Restore registers - #endif + #endif -SVC_ContextRestore1 - LDR R0,[R2,#TCB_SM_OFS] ; Load stack memory base - LDRB R1,[R2,#TCB_SF_OFS] ; Load stack frame information - MSR PSPLIM,R0 ; Set PSPLIM +SVC_ContextRestore_NS LDR R0,[R2,#TCB_SP_OFS] ; Load SP - ORR LR,R1,#0xFFFFFF00 ; Set EXC_RETURN + LDR R1,[R2,#TCB_SM_OFS] ; Load stack memory base + MSR PSPLIM,R1 ; Set PSPLIM + LDRB R1,[R2,#TCB_SF_OFS] ; Load stack frame information + ORN LR,R1,#0xFF ; Set EXC_RETURN - #if (DOMAIN_NS == 1) + #if (DOMAIN_NS != 0) TST LR,#0x40 ; Check domain of interrupted thread - BNE SVC_ContextRestore2 ; Branch if secure - #endif + BNE SVC_ContextRestoreSP ; Branch if secure + #endif - #if ((FPU_USED == 1) || (MVE_USED == 1)) - TST LR,#0x10 ; Check if extended stack frame - IT EQ + #if ((FPU_USED != 0) || (MVE_USED != 0)) + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame VLDMIAEQ R0!,{S16-S31} ; Restore VFP S16..S31 - #endif + #endif LDMIA R0!,{R4-R11} ; Restore R4..R11 -SVC_ContextRestore2 +SVC_ContextRestoreSP MSR PSP,R0 ; Set PSP SVC_Exit @@ -186,7 +251,8 @@ PendSV_Handler PUSH {R0,LR} ; Save EXC_RETURN BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler POP {R0,LR} ; Restore EXC_RETURN - B Sys_Context + MRS R12,PSP ; Save PSP to R12 + B SVC_Context ; Branch to context handling SysTick_Handler @@ -196,87 +262,8 @@ SysTick_Handler PUSH {R0,LR} ; Save EXC_RETURN BL osRtxTick_Handler ; Call osRtxTick_Handler POP {R0,LR} ; Restore EXC_RETURN - B Sys_Context - - - -Sys_Context - EXPORT Sys_Context - IMPORT osRtxInfo - #if (DOMAIN_NS == 1) - IMPORT TZ_LoadContext_S - IMPORT TZ_StoreContext_S - #endif - - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run - LDM R3,{R1,R2} ; Load osRtxInfo.thread.run: curr & next - CMP R1,R2 ; Check if thread switch is required - IT EQ - BXEQ LR ; Exit when threads are the same + MRS R12,PSP ; Save PSP to R12 + B SVC_Context ; Branch to context handling -Sys_ContextSave - #if (DOMAIN_NS == 1) - LDR R0,[R1,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,Sys_ContextSave1 ; Branch if there is no secure context - PUSH {R1,R2,R3,LR} ; Save registers and EXC_RETURN - BL TZ_StoreContext_S ; Store secure context - POP {R1,R2,R3,LR} ; Restore registers and EXC_RETURN - -Sys_ContextSave1 - TST LR,#0x40 ; Check domain of interrupted thread - IT NE - MRSNE R0,PSP ; Get PSP - BNE Sys_ContextSave3 ; Branch if secure - #endif - -Sys_ContextSave2 - MRS R0,PSP ; Get PSP - STMDB R0!,{R4-R11} ; Save R4..R11 - #if ((FPU_USED == 1) || (MVE_USED == 1)) - TST LR,#0x10 ; Check if extended stack frame - IT EQ - VSTMDBEQ R0!,{S16-S31} ; Save VFP S16.S31 - #endif - -Sys_ContextSave3 - STR R0,[R1,#TCB_SP_OFS] ; Store SP - STRB LR,[R1,#TCB_SF_OFS] ; Store stack frame information - -Sys_ContextSwitch - STR R2,[R3] ; osRtxInfo.run: curr = next - -Sys_ContextRestore - #if (DOMAIN_NS == 1) - LDR R0,[R2,#TCB_TZM_OFS] ; Load TrustZone memory identifier - CBZ R0,Sys_ContextRestore1 ; Branch if there is no secure context - PUSH {R2,R3} ; Save registers - BL TZ_LoadContext_S ; Load secure context - POP {R2,R3} ; Restore registers - #endif - -Sys_ContextRestore1 - LDR R0,[R2,#TCB_SM_OFS] ; Load stack memory base - LDRB R1,[R2,#TCB_SF_OFS] ; Load stack frame information - MSR PSPLIM,R0 ; Set PSPLIM - LDR R0,[R2,#TCB_SP_OFS] ; Load SP - ORR LR,R1,#0xFFFFFF00 ; Set EXC_RETURN - - #if (DOMAIN_NS == 1) - TST LR,#0x40 ; Check domain of interrupted thread - BNE Sys_ContextRestore2 ; Branch if secure - #endif - - #if ((FPU_USED == 1) || (MVE_USED == 1)) - TST LR,#0x10 ; Check if extended stack frame - IT EQ - VLDMIAEQ R0!,{S16-S31} ; Restore VFP S16..S31 - #endif - LDMIA R0!,{R4-R11} ; Restore R4..R11 - -Sys_ContextRestore2 - MSR PSP,R0 ; Set PSP - -Sys_ContextExit - BX LR ; Exit from handler END diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_RTOS_M4_M7/irq_cm4f.S b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_RTOS_M4_M7/irq_cm4f.S index 4f8f3d4c8f5..485433c46f4 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_RTOS_M4_M7/irq_cm4f.S +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_IAR/TARGET_RTOS_M4_M7/irq_cm4f.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2013-2018 Arm Limited. All rights reserved. +; * Copyright (c) 2013-2021 Arm Limited. All rights reserved. ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -18,19 +18,32 @@ ; * ----------------------------------------------------------------------------- ; * ; * Project: CMSIS-RTOS RTX -; * Title: Cortex-M4F Exception handlers +; * Title: ARMv7-M Exception handlers ; * ; * ----------------------------------------------------------------------------- ; */ - NAME irq_cm4f.s + NAME irq_armv7m.s + + +#ifdef __ARMVFP__ +FPU_USED EQU 1 +#else +FPU_USED EQU 0 +#endif + I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset TCB_SP_OFS EQU 56 ; TCB.SP offset TCB_SF_OFS EQU 34 ; TCB.stack_frame offset +FPCCR EQU 0xE000EF34 ; FPCCR Address + +osRtxErrorStackOverflow\ + EQU 1 ; Stack overflow + PRESERVE8 SECTION .rodata:DATA:NOROOT(2) @@ -48,6 +61,10 @@ SVC_Handler EXPORT SVC_Handler IMPORT osRtxUserSVC IMPORT osRtxInfo + #ifdef RTX_STACK_CHECK + IMPORT osRtxThreadStackCheck + IMPORT osRtxKernelErrorNotify + #endif TST LR,#0x04 ; Determine return stack from EXC_RETURN bit 2 ITE EQ @@ -56,7 +73,8 @@ SVC_Handler LDR R1,[R0,#24] ; Load saved PC from stack LDRB R1,[R1,#-2] ; Load SVC number - CBNZ R1,SVC_User ; Branch if not SVC 0 + CMP R1,#0 ; Check SVC number + BNE SVC_User ; Branch if not SVC 0 PUSH {R0,LR} ; Save SP and EXC_RETURN LDM R0,{R0-R3,R12} ; Load function parameters and address from stack @@ -65,47 +83,91 @@ SVC_Handler STM R12,{R0-R1} ; Store function return values SVC_Context - LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run + LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.thread.run LDM R3,{R1,R2} ; Load osRtxInfo.thread.run: curr & next CMP R1,R2 ; Check if thread switch is required IT EQ BXEQ LR ; Exit when threads are the same + STR R2,[R3] ; osRtxInfo.thread.run: curr = next + + #if (FPU_USED != 0) CBNZ R1,SVC_ContextSave ; Branch if running thread is not deleted - TST LR,#0x10 ; Check if extended stack frame - BNE SVC_ContextSwitch -#ifdef __FPU_PRESENT - LDR R1,=0xE000EF34 ; FPCCR Address - LDR R0,[R1] ; Load FPCCR - BIC R0,R0,#1 ; Clear LSPACT (Lazy state) - STR R0,[R1] ; Store FPCCR - B SVC_ContextSwitch -#endif +SVC_FP_LazyState + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + BNE SVC_ContextRestore ; Branch if not extended stack frame + LDR R3,=FPCCR ; FPCCR Address + LDR R0,[R3] ; Load FPCCR + BIC R0,R0,#1 ; Clear LSPACT (Lazy state preservation) + STR R0,[R3] ; Store FPCCR + B SVC_ContextRestore ; Branch to context restore handling + #else + CBZ R1,SVC_ContextRestore ; Branch if running thread is deleted + #endif SVC_ContextSave - STMDB R12!,{R4-R11} ; Save R4..R11 -#ifdef __FPU_PRESENT - TST LR,#0x10 ; Check if extended stack frame - IT EQ - VSTMDBEQ R12!,{S16-S31} ; Save VFP S16.S31 -#endif - - STR R12,[R1,#TCB_SP_OFS] ; Store SP + #ifdef RTX_STACK_CHECK + SUB R12,R12,#32 ; Calculate SP: space for R4..R11 + #if (FPU_USED != 0) + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + SUBEQ R12,R12,#64 ; Additional space for S16..S31 STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information + #endif + STR R12,[R1,#TCB_SP_OFS] ; Store SP -SVC_ContextSwitch + PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next + MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr + BL osRtxThreadStackCheck ; Check if thread stack is overrun + POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next + CBNZ R0,SVC_ContextSaveRegs ; Branch when stack check is ok + + #if (FPU_USED != 0) + MOV R4,R1 ; Save osRtxInfo.thread.run.curr + #endif + MOV R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id + BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify + LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run + LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next STR R2,[R3] ; osRtxInfo.thread.run: curr = next + #if (FPU_USED != 0) + LDRB LR,[R4,#TCB_SF_OFS] ; Load stack frame information + B SVC_FP_LazyState ; Branch to FP lazy state handling + #else + B SVC_ContextRestore ; Branch to context restore handling + #endif + +SVC_ContextSaveRegs + LDR R12,[R1,#TCB_SP_OFS] ; Load SP + #if (FPU_USED != 0) + LDRB LR, [R1,#TCB_SF_OFS] ; Load stack frame information + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + VSTMIAEQ R12!,{S16-S31} ; Save VFP S16..S31 + #endif + STM R12,{R4-R11} ; Save R4..R11 + #else + STMDB R12!,{R4-R11} ; Save R4..R11 + #if (FPU_USED != 0) + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame + VSTMDBEQ R12!,{S16-S31} ; Save VFP S16.S31 + STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information + #endif + STR R12,[R1,#TCB_SP_OFS] ; Store SP + #endif SVC_ContextRestore - LDRB R1,[R2,#TCB_SF_OFS] ; Load stack frame information LDR R0,[R2,#TCB_SP_OFS] ; Load SP - ORR LR,R1,#0xFFFFFF00 ; Set EXC_RETURN - -#ifdef __FPU_PRESENT - TST LR,#0x10 ; Check if extended stack frame - IT EQ + #if (FPU_USED != 0) + LDRB R1,[R2,#TCB_SF_OFS] ; Load stack frame information + ORN LR,R1,#0xFF ; Set EXC_RETURN + TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4 + IT EQ ; If extended stack frame VLDMIAEQ R0!,{S16-S31} ; Restore VFP S16..S31 -#endif + #else + MVN LR,#~0xFFFFFFFD ; Set EXC_RETURN value + #endif LDMIA R0!,{R4-R11} ; Restore R4..R11 MSR PSP,R0 ; Set PSP @@ -135,8 +197,8 @@ PendSV_Handler PUSH {R0,LR} ; Save EXC_RETURN BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler POP {R0,LR} ; Restore EXC_RETURN - MRS R12,PSP - B SVC_Context + MRS R12,PSP ; Save PSP to R12 + B SVC_Context ; Branch to context handling SysTick_Handler @@ -146,8 +208,8 @@ SysTick_Handler PUSH {R0,LR} ; Save EXC_RETURN BL osRtxTick_Handler ; Call osRtxTick_Handler POP {R0,LR} ; Restore EXC_RETURN - MRS R12,PSP - B SVC_Context + MRS R12,PSP ; Save PSP to R12 + B SVC_Context ; Branch to context handling END diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_c.h b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_c.h index 445d393c9a5..7192a1d01e3 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_c.h +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_c.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -27,7 +27,9 @@ #define RTX_CORE_C_H_ //lint -emacro((923,9078),SCB) "cast from unsigned long to pointer" [MISRA Note 9] +#ifndef RTE_COMPONENTS_H #include "RTE_Components.h" +#endif #include CMSIS_device_header #if ((!defined(__ARM_ARCH_6M__)) && \ diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_ca.h b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_ca.h index 9fd36f2c8e3..a599516f2b9 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_ca.h +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_ca.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -27,7 +27,9 @@ #define RTX_CORE_CA_H_ #ifndef RTX_CORE_C_H_ +#ifndef RTE_COMPONENTS_H #include "RTE_Components.h" +#endif #include CMSIS_device_header #endif @@ -158,9 +160,9 @@ __STATIC_INLINE bool_t IsPrivileged (void) { return (__get_mode() != CPSR_MODE_USER); } -/// Check if in IRQ Mode -/// \return true=IRQ, false=thread -__STATIC_INLINE bool_t IsIrqMode (void) { +/// Check if in Exception +/// \return true=exception, false=thread +__STATIC_INLINE bool_t IsException (void) { return ((__get_mode() != CPSR_MODE_USER) && (__get_mode() != CPSR_MODE_SYSTEM)); } diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_cm.h b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_cm.h index 94ee5ba7eca..086b1e00761 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_cm.h +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_cm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -27,7 +27,9 @@ #define RTX_CORE_CM_H_ #ifndef RTX_CORE_C_H_ +#ifndef RTE_COMPONENTS_H #include "RTE_Components.h" +#endif #include CMSIS_device_header #endif @@ -35,15 +37,11 @@ typedef bool bool_t; #ifndef FALSE -#define FALSE (0) +#define FALSE ((bool_t)0) #endif #ifndef TRUE -#define TRUE (1) -#endif - -#ifdef RTE_CMSIS_RTOS2_RTX5_ARMV8M_NS -#define DOMAIN_NS 1 +#define TRUE ((bool_t)1) #endif #ifndef DOMAIN_NS @@ -120,9 +118,9 @@ __STATIC_INLINE bool_t IsPrivileged (void) { return ((__get_CONTROL() & 1U) == 0U); } -/// Check if in IRQ Mode -/// \return true=IRQ, false=thread -__STATIC_INLINE bool_t IsIrqMode (void) { +/// Check if in Exception +/// \return true=exception, false=thread +__STATIC_INLINE bool_t IsException (void) { return (__get_IPSR() != 0U); } @@ -209,58 +207,58 @@ __STATIC_INLINE void SetPendSV (void) { (defined(__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ != 0)) || \ (defined(__ARM_ARCH_8M_MAIN__) && (__ARM_ARCH_8M_MAIN__ != 0)) || \ (defined(__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ != 0))) -#define __SVC_INDIRECT(n) __svc_indirect(n) +#define SVC_INDIRECT(n) __svc_indirect(n) #elif ((defined(__ARM_ARCH_6M__) && (__ARM_ARCH_6M__ != 0)) || \ (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))) -#define __SVC_INDIRECT(n) __svc_indirect_r7(n) +#define SVC_INDIRECT(n) __svc_indirect_r7(n) #endif #define SVC0_0N(f,t) \ -__SVC_INDIRECT(0) t svc##f (t(*)()); \ +SVC_INDIRECT(0) t svc##f (t(*)()); \ __attribute__((always_inline)) \ -__STATIC_INLINE t __svc##f (void) { \ +__STATIC_INLINE t __svc##f (void) { \ svc##f(svcRtx##f); \ } #define SVC0_0(f,t) \ -__SVC_INDIRECT(0) t svc##f (t(*)()); \ +SVC_INDIRECT(0) t svc##f (t(*)()); \ __attribute__((always_inline)) \ -__STATIC_INLINE t __svc##f (void) { \ +__STATIC_INLINE t __svc##f (void) { \ return svc##f(svcRtx##f); \ } #define SVC0_1N(f,t,t1) \ -__SVC_INDIRECT(0) t svc##f (t(*)(t1),t1); \ +SVC_INDIRECT(0) t svc##f (t(*)(t1),t1); \ __attribute__((always_inline)) \ -__STATIC_INLINE t __svc##f (t1 a1) { \ +__STATIC_INLINE t __svc##f (t1 a1) { \ svc##f(svcRtx##f,a1); \ } #define SVC0_1(f,t,t1) \ -__SVC_INDIRECT(0) t svc##f (t(*)(t1),t1); \ +SVC_INDIRECT(0) t svc##f (t(*)(t1),t1); \ __attribute__((always_inline)) \ -__STATIC_INLINE t __svc##f (t1 a1) { \ +__STATIC_INLINE t __svc##f (t1 a1) { \ return svc##f(svcRtx##f,a1); \ } #define SVC0_2(f,t,t1,t2) \ -__SVC_INDIRECT(0) t svc##f (t(*)(t1,t2),t1,t2); \ +SVC_INDIRECT(0) t svc##f (t(*)(t1,t2),t1,t2); \ __attribute__((always_inline)) \ -__STATIC_INLINE t __svc##f (t1 a1, t2 a2) { \ +__STATIC_INLINE t __svc##f (t1 a1, t2 a2) { \ return svc##f(svcRtx##f,a1,a2); \ } #define SVC0_3(f,t,t1,t2,t3) \ -__SVC_INDIRECT(0) t svc##f (t(*)(t1,t2,t3),t1,t2,t3); \ +SVC_INDIRECT(0) t svc##f (t(*)(t1,t2,t3),t1,t2,t3); \ __attribute__((always_inline)) \ -__STATIC_INLINE t __svc##f (t1 a1, t2 a2, t3 a3) { \ +__STATIC_INLINE t __svc##f (t1 a1, t2 a2, t3 a3) { \ return svc##f(svcRtx##f,a1,a2,a3); \ } #define SVC0_4(f,t,t1,t2,t3,t4) \ -__SVC_INDIRECT(0) t svc##f (t(*)(t1,t2,t3,t4),t1,t2,t3,t4); \ +SVC_INDIRECT(0) t svc##f (t(*)(t1,t2,t3,t4),t1,t2,t3,t4); \ __attribute__((always_inline)) \ -__STATIC_INLINE t __svc##f (t1 a1, t2 a2, t3 a3, t4 a4) { \ +__STATIC_INLINE t __svc##f (t1 a1, t2 a2, t3 a3, t4 a4) { \ return svc##f(svcRtx##f,a1,a2,a3,a4); \ } @@ -285,60 +283,60 @@ __STATIC_INLINE t __svc##f (t1 a1, t2 a2, t3 a3, t4 a4) { \ #endif #define STRINGIFY(a) #a -#define __SVC_INDIRECT(n) _Pragma(STRINGIFY(swi_number = n)) __swi +#define SVC_INDIRECT(n) _Pragma(STRINGIFY(swi_number = n)) __swi #define SVC0_0N(f,t) \ -__SVC_INDIRECT(0) t svc##f (); \ +SVC_INDIRECT(0) t svc##f (); \ __attribute__((always_inline)) \ -__STATIC_INLINE t __svc##f (void) { \ +__STATIC_INLINE t __svc##f (void) { \ SVC_ArgF(svcRtx##f); \ svc##f(); \ } #define SVC0_0(f,t) \ -__SVC_INDIRECT(0) t svc##f (); \ +SVC_INDIRECT(0) t svc##f (); \ __attribute__((always_inline)) \ -__STATIC_INLINE t __svc##f (void) { \ +__STATIC_INLINE t __svc##f (void) { \ SVC_ArgF(svcRtx##f); \ return svc##f(); \ } #define SVC0_1N(f,t,t1) \ -__SVC_INDIRECT(0) t svc##f (t1 a1); \ +SVC_INDIRECT(0) t svc##f (t1 a1); \ __attribute__((always_inline)) \ -__STATIC_INLINE t __svc##f (t1 a1) { \ +__STATIC_INLINE t __svc##f (t1 a1) { \ SVC_ArgF(svcRtx##f); \ svc##f(a1); \ } #define SVC0_1(f,t,t1) \ -__SVC_INDIRECT(0) t svc##f (t1 a1); \ +SVC_INDIRECT(0) t svc##f (t1 a1); \ __attribute__((always_inline)) \ -__STATIC_INLINE t __svc##f (t1 a1) { \ +__STATIC_INLINE t __svc##f (t1 a1) { \ SVC_ArgF(svcRtx##f); \ return svc##f(a1); \ } #define SVC0_2(f,t,t1,t2) \ -__SVC_INDIRECT(0) t svc##f (t1 a1, t2 a2); \ +SVC_INDIRECT(0) t svc##f (t1 a1, t2 a2); \ __attribute__((always_inline)) \ -__STATIC_INLINE t __svc##f (t1 a1, t2 a2) { \ +__STATIC_INLINE t __svc##f (t1 a1, t2 a2) { \ SVC_ArgF(svcRtx##f); \ return svc##f(a1,a2); \ } #define SVC0_3(f,t,t1,t2,t3) \ -__SVC_INDIRECT(0) t svc##f (t1 a1, t2 a2, t3 a3); \ +SVC_INDIRECT(0) t svc##f (t1 a1, t2 a2, t3 a3); \ __attribute__((always_inline)) \ -__STATIC_INLINE t __svc##f (t1 a1, t2 a2, t3 a3) { \ +__STATIC_INLINE t __svc##f (t1 a1, t2 a2, t3 a3) { \ SVC_ArgF(svcRtx##f); \ return svc##f(a1,a2,a3); \ } #define SVC0_4(f,t,t1,t2,t3,t4) \ -__SVC_INDIRECT(0) t svc##f (t1 a1, t2 a2, t3 a3, t4 a4); \ +SVC_INDIRECT(0) t svc##f (t1 a1, t2 a2, t3 a3, t4 a4); \ __attribute__((always_inline)) \ -__STATIC_INLINE t __svc##f (t1 a1, t2 a2, t3 a3, t4 a4) { \ +__STATIC_INLINE t __svc##f (t1 a1, t2 a2, t3 a3, t4 a4) { \ SVC_ArgF(svcRtx##f); \ return svc##f(a1,a2,a3,a4); \ } diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_delay.c b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_delay.c index 9d0cf414bf2..f8eacaf572c 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_delay.c +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_delay.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -31,21 +31,29 @@ /// Wait for Timeout (Time Delay). /// \note API identical to osDelay static osStatus_t svcRtxDelay (uint32_t ticks) { + osStatus_t status; - if (ticks != 0U) { - if (osRtxThreadWaitEnter(osRtxThreadWaitingDelay, ticks)) { - EvrRtxDelayStarted(ticks); - } else { - EvrRtxDelayCompleted(osRtxThreadGetRunning()); - } + if (ticks == 0U) { + EvrRtxDelayError((int32_t)osErrorParameter); + //lint -e{904} "Return statement before end of function" [MISRA Note 1] + return osErrorParameter; } - return osOK; + if (osRtxThreadWaitEnter(osRtxThreadWaitingDelay, ticks)) { + EvrRtxDelayStarted(ticks); + status = osOK; + } else { + EvrRtxDelayError((int32_t)osError); + status = osError; + } + + return status; } /// Wait until specified time. /// \note API identical to osDelayUntil static osStatus_t svcRtxDelayUntil (uint32_t ticks) { + osStatus_t status; ticks -= osRtxInfo.kernel.tick; if ((ticks == 0U) || (ticks > 0x7FFFFFFFU)) { @@ -56,11 +64,13 @@ static osStatus_t svcRtxDelayUntil (uint32_t ticks) { if (osRtxThreadWaitEnter(osRtxThreadWaitingDelay, ticks)) { EvrRtxDelayUntilStarted(ticks); + status = osOK; } else { - EvrRtxDelayCompleted(osRtxThreadGetRunning()); + EvrRtxDelayError((int32_t)osError); + status = osError; } - return osOK; + return status; } // Service Calls definitions @@ -77,7 +87,7 @@ osStatus_t osDelay (uint32_t ticks) { osStatus_t status; EvrRtxDelay(ticks); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxDelayError((int32_t)osErrorISR); status = osErrorISR; } else { @@ -91,7 +101,7 @@ osStatus_t osDelayUntil (uint32_t ticks) { osStatus_t status; EvrRtxDelayUntil(ticks); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxDelayError((int32_t)osErrorISR); status = osErrorISR; } else { diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_evflags.c b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_evflags.c index f32aec7b833..f2300e9a015 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_evflags.c +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_evflags.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -27,7 +27,7 @@ // OS Runtime Object Memory Usage -#if ((defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))) +#ifdef RTX_OBJ_MEM_USAGE osRtxObjectMemUsage_t osRtxEventFlagsMemUsage \ __attribute__((section(".data.os.evflags.obj"))) = { 0U, 0U, 0U }; @@ -200,7 +200,7 @@ static osEventFlagsId_t svcRtxEventFlagsNew (const osEventFlagsAttr_t *attr) { //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5] ef = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_event_flags_t), 1U); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE if (ef != NULL) { uint32_t used; osRtxEventFlagsMemUsage.cnt_alloc++; @@ -313,7 +313,7 @@ static uint32_t svcRtxEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags) { event_flags = EventFlagsClear(ef, flags); EvrRtxEventFlagsClearDone(ef, event_flags); - + return event_flags; } @@ -409,7 +409,7 @@ static osStatus_t svcRtxEventFlagsDelete (osEventFlagsId_t ef_id) { } else { (void)osRtxMemoryFree(osRtxInfo.mem.common, ef); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE osRtxEventFlagsMemUsage.cnt_free++; #endif } @@ -494,7 +494,7 @@ osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr) { osEventFlagsId_t ef_id; EvrRtxEventFlagsNew(attr); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxEventFlagsError(NULL, (int32_t)osErrorISR); ef_id = NULL; } else { @@ -507,7 +507,7 @@ osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr) { const char *osEventFlagsGetName (osEventFlagsId_t ef_id) { const char *name; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxEventFlagsGetName(ef_id, NULL); name = NULL; } else { @@ -521,7 +521,7 @@ uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags) { uint32_t event_flags; EvrRtxEventFlagsSet(ef_id, flags); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { event_flags = isrRtxEventFlagsSet(ef_id, flags); } else { event_flags = __svcEventFlagsSet(ef_id, flags); @@ -534,7 +534,7 @@ uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags) { uint32_t event_flags; EvrRtxEventFlagsClear(ef_id, flags); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { event_flags = svcRtxEventFlagsClear(ef_id, flags); } else { event_flags = __svcEventFlagsClear(ef_id, flags); @@ -546,7 +546,7 @@ uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags) { uint32_t osEventFlagsGet (osEventFlagsId_t ef_id) { uint32_t event_flags; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { event_flags = svcRtxEventFlagsGet(ef_id); } else { event_flags = __svcEventFlagsGet(ef_id); @@ -559,7 +559,7 @@ uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t opti uint32_t event_flags; EvrRtxEventFlagsWait(ef_id, flags, options, timeout); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { event_flags = isrRtxEventFlagsWait(ef_id, flags, options, timeout); } else { event_flags = __svcEventFlagsWait(ef_id, flags, options, timeout); @@ -572,7 +572,7 @@ osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id) { osStatus_t status; EvrRtxEventFlagsDelete(ef_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxEventFlagsError(ef_id, (int32_t)osErrorISR); status = osErrorISR; } else { diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_evr.c b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_evr.c index 042d2542700..55b55a78e93 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_evr.c +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_evr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -63,6 +63,7 @@ #define EvtRtxKernelGetTickFreq EventID(EventLevelAPI, EvtRtxKernelNo, 0x14U) #define EvtRtxKernelGetSysTimerCount EventID(EventLevelAPI, EvtRtxKernelNo, 0x15U) #define EvtRtxKernelGetSysTimerFreq EventID(EventLevelAPI, EvtRtxKernelNo, 0x16U) +#define EvtRtxKernelErrorNotify EventID(EventLevelError, EvtRtxKernelNo, 0x19U) /// Event IDs for "RTX Thread" #define EvtRtxThreadError EventID(EventLevelError, EvtRtxThreadNo, 0x00U) @@ -531,6 +532,17 @@ __WEAK void EvrRtxKernelGetSysTimerFreq (uint32_t freq) { } #endif +#if (!defined(EVR_RTX_DISABLE) && (OS_EVR_KERNEL != 0) && !defined(EVR_RTX_KERNEL_ERROR_NOTIFY_DISABLE)) +__WEAK void EvrRtxKernelErrorNotify (uint32_t code, void *object_id) { +#if defined(RTE_Compiler_EventRecorder) + (void)EventRecord2(EvtRtxKernelErrorNotify, code, (uint32_t)object_id); +#else + (void)code; + (void)object_id; +#endif +} +#endif + // ==== Thread Events ==== diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_kernel.c b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_kernel.c index 303fc5442be..68ce8283b9e 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_kernel.c +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_kernel.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -62,6 +62,31 @@ static void KernelUnblock (void) { OS_Tick_Enable(); } +// Get Kernel sleep time +static uint32_t GetKernelSleepTime (void) { + const os_thread_t *thread; + const os_timer_t *timer; + uint32_t delay; + + delay = osWaitForever; + + // Check Thread Delay list + thread = osRtxInfo.thread.delay_list; + if (thread != NULL) { + delay = thread->delay; + } + + // Check Active Timer list + timer = osRtxInfo.timer.list; + if (timer != NULL) { + if (timer->tick < delay) { + delay = timer->tick; + } + } + + return delay; +} + // ==== Service Calls ==== @@ -90,7 +115,6 @@ static osStatus_t svcRtxKernelInitialize (void) { #endif // Initialize osRtxInfo - memset(&osRtxInfo.kernel, 0, sizeof(osRtxInfo) - offsetof(osRtxInfo_t, kernel)); osRtxInfo.isr_queue.data = osRtxConfig.isr_queue.data; osRtxInfo.isr_queue.max = osRtxConfig.isr_queue.max; @@ -198,7 +222,7 @@ static osStatus_t svcRtxKernelGetInfo (osVersion_t *version, char *id_buf, uint3 } else { size = id_size; } - memcpy(id_buf, osRtxKernelId, size); + (void)memcpy(id_buf, osRtxKernelId, size); } EvrRtxKernelInfoRetrieved(version, id_buf, id_size); @@ -287,7 +311,7 @@ static int32_t svcRtxKernelLock (void) { } return lock; } - + /// Unlock the RTOS Kernel scheduler. /// \note API identical to osKernelUnlock static int32_t svcRtxKernelUnlock (void) { @@ -347,9 +371,7 @@ static int32_t svcRtxKernelRestoreLock (int32_t lock) { /// Suspend the RTOS Kernel scheduler. /// \note API identical to osKernelSuspend static uint32_t svcRtxKernelSuspend (void) { - const os_thread_t *thread; - const os_timer_t *timer; - uint32_t delay; + uint32_t delay; if (osRtxInfo.kernel.state != osRtxKernelRunning) { EvrRtxKernelError(osRtxErrorKernelNotRunning); @@ -359,24 +381,10 @@ static uint32_t svcRtxKernelSuspend (void) { KernelBlock(); - delay = osWaitForever; - - // Check Thread Delay list - thread = osRtxInfo.thread.delay_list; - if (thread != NULL) { - delay = thread->delay; - } - - // Check Active Timer list - timer = osRtxInfo.timer.list; - if (timer != NULL) { - if (timer->tick < delay) { - delay = timer->tick; - } - } - osRtxInfo.kernel.state = osRtxKernelSuspended; + delay = GetKernelSleepTime(); + EvrRtxKernelSuspended(delay); return delay; @@ -388,7 +396,7 @@ static void svcRtxKernelResume (uint32_t sleep_ticks) { os_thread_t *thread; os_timer_t *timer; uint32_t delay; - uint32_t ticks; + uint32_t ticks, kernel_tick; if (osRtxInfo.kernel.state != osRtxKernelSuspended) { EvrRtxKernelResumed(); @@ -396,40 +404,38 @@ static void svcRtxKernelResume (uint32_t sleep_ticks) { return; } - osRtxInfo.kernel.tick += sleep_ticks; + delay = GetKernelSleepTime(); + if (sleep_ticks >= delay) { + ticks = delay - 1U; + } else { + ticks = sleep_ticks; + } - // Process Thread Delay list + // Update Thread Delay sleep ticks thread = osRtxInfo.thread.delay_list; if (thread != NULL) { - delay = sleep_ticks; - do { - if (delay >= thread->delay) { - delay -= thread->delay; - thread->delay = 1U; - osRtxThreadDelayTick(); - thread = osRtxInfo.thread.delay_list; - } else { - thread->delay -= delay; - delay = 0U; - } - } while ((thread != NULL) && (delay != 0U)); + thread->delay -= ticks; } - // Process Active Timer list + // Update Timer sleep ticks timer = osRtxInfo.timer.list; if (timer != NULL) { - ticks = sleep_ticks; - do { - if (ticks >= timer->tick) { - ticks -= timer->tick; - timer->tick = 1U; - osRtxInfo.timer.tick(); - timer = osRtxInfo.timer.list; - } else { - timer->tick -= ticks; - ticks = 0U; - } - } while ((timer != NULL) && (ticks != 0U)); + timer->tick -= ticks; + } + + kernel_tick = osRtxInfo.kernel.tick + sleep_ticks; + osRtxInfo.kernel.tick += ticks; + + while (osRtxInfo.kernel.tick != kernel_tick) { + osRtxInfo.kernel.tick++; + + // Process Thread Delays + osRtxThreadDelayTick(); + + // Process Timers + if (osRtxInfo.timer.tick != NULL) { + osRtxInfo.timer.tick(); + } } osRtxInfo.kernel.state = osRtxKernelRunning; @@ -507,6 +513,13 @@ SVC0_0 (KernelGetSysTimerFreq, uint32_t) __WEAK void osRtxKernelPreInit (void) { } +/// RTOS Kernel Error Notification Handler +/// \note API identical to osRtxErrorNotify +uint32_t osRtxKernelErrorNotify (uint32_t code, void *object_id) { + EvrRtxKernelErrorNotify(code, object_id); + return osRtxErrorNotify(code, object_id); +} + // ==== Public API ==== @@ -516,7 +529,7 @@ osStatus_t osKernelInitialize (void) { osRtxKernelPreInit(); EvrRtxKernelInitialize(); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxKernelError((int32_t)osErrorISR); status = osErrorISR; } else { @@ -530,7 +543,7 @@ osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size osStatus_t status; EvrRtxKernelGetInfo(version, id_buf, id_size); - if (IsIrqMode() || IsIrqMasked() || IsPrivileged()) { + if (IsException() || IsIrqMasked() || IsPrivileged()) { status = svcRtxKernelGetInfo(version, id_buf, id_size); } else { status = __svcKernelGetInfo(version, id_buf, id_size); @@ -542,7 +555,7 @@ osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size osKernelState_t osKernelGetState (void) { osKernelState_t state; - if (IsIrqMode() || IsIrqMasked() || IsPrivileged()) { + if (IsException() || IsIrqMasked() || IsPrivileged()) { state = svcRtxKernelGetState(); } else { state = __svcKernelGetState(); @@ -555,7 +568,7 @@ osStatus_t osKernelStart (void) { osStatus_t status; EvrRtxKernelStart(); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxKernelError((int32_t)osErrorISR); status = osErrorISR; } else { @@ -569,7 +582,7 @@ int32_t osKernelLock (void) { int32_t lock; EvrRtxKernelLock(); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxKernelError((int32_t)osErrorISR); lock = (int32_t)osErrorISR; } else { @@ -577,13 +590,13 @@ int32_t osKernelLock (void) { } return lock; } - + /// Unlock the RTOS Kernel scheduler. int32_t osKernelUnlock (void) { int32_t lock; EvrRtxKernelUnlock(); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxKernelError((int32_t)osErrorISR); lock = (int32_t)osErrorISR; } else { @@ -597,7 +610,7 @@ int32_t osKernelRestoreLock (int32_t lock) { int32_t lock_new; EvrRtxKernelRestoreLock(lock); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxKernelError((int32_t)osErrorISR); lock_new = (int32_t)osErrorISR; } else { @@ -611,7 +624,7 @@ uint32_t osKernelSuspend (void) { uint32_t ticks; EvrRtxKernelSuspend(); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxKernelError((int32_t)osErrorISR); ticks = 0U; } else { @@ -624,7 +637,7 @@ uint32_t osKernelSuspend (void) { void osKernelResume (uint32_t sleep_ticks) { EvrRtxKernelResume(sleep_ticks); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxKernelError((int32_t)osErrorISR); } else { __svcKernelResume(sleep_ticks); @@ -635,7 +648,7 @@ void osKernelResume (uint32_t sleep_ticks) { uint32_t osKernelGetTickCount (void) { uint32_t count; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { count = svcRtxKernelGetTickCount(); } else { count = __svcKernelGetTickCount(); @@ -647,7 +660,7 @@ uint32_t osKernelGetTickCount (void) { uint32_t osKernelGetTickFreq (void) { uint32_t freq; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { freq = svcRtxKernelGetTickFreq(); } else { freq = __svcKernelGetTickFreq(); @@ -659,7 +672,7 @@ uint32_t osKernelGetTickFreq (void) { uint32_t osKernelGetSysTimerCount (void) { uint32_t count; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { count = svcRtxKernelGetSysTimerCount(); } else { count = __svcKernelGetSysTimerCount(); @@ -671,7 +684,7 @@ uint32_t osKernelGetSysTimerCount (void) { uint32_t osKernelGetSysTimerFreq (void) { uint32_t freq; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { freq = svcRtxKernelGetSysTimerFreq(); } else { freq = __svcKernelGetSysTimerFreq(); diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_lib.c b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_lib.c index 00cfe6426df..5b63a0a5b82 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_lib.c +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_lib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -24,7 +24,6 @@ */ #include "cmsis_compiler.h" -#include "RTX_Config.h" #include "rtx_os.h" #ifdef RTE_Compiler_EventRecorder @@ -87,7 +86,7 @@ __attribute__((section(".bss.os.thread.cb"))); // Thread Default Stack #if (OS_THREAD_DEF_STACK_NUM != 0) -static uint64_t os_thread_def_stack[OS_THREAD_DEF_STACK_NUM*(OS_STACK_SIZE/8)] \ +static uint64_t os_thread_def_stack[(OS_THREAD_DEF_STACK_NUM*OS_STACK_SIZE)/8] \ __attribute__((section(".bss.os.thread.stack"))); #endif @@ -105,32 +104,21 @@ __attribute__((section(".data.os.thread.mpi"))) = // Memory Pool for Thread Stack #if (OS_THREAD_USER_STACK_SIZE != 0) -static uint64_t os_thread_stack[2 + OS_THREAD_NUM + (OS_THREAD_USER_STACK_SIZE/8)] \ +static uint64_t os_thread_stack[(16 + (8*OS_THREAD_NUM) + OS_THREAD_USER_STACK_SIZE)/8] \ __attribute__((section(".bss.os.thread.stack"))); #endif #endif // (OS_THREAD_OBJ_MEM != 0) -// Stack overrun checking -#if (OS_STACK_CHECK == 0) -// Override library function -extern void osRtxThreadStackCheck (void); - void osRtxThreadStackCheck (void) {} -#endif - - // Idle Thread Control Block static osRtxThread_t os_idle_thread_cb \ __attribute__((section(".bss.os.thread.cb"))); // Idle Thread Stack -#if defined (__CC_ARM) -static uint64_t os_idle_thread_stack[OS_IDLE_THREAD_STACK_SIZE/8]; -#else static uint64_t os_idle_thread_stack[OS_IDLE_THREAD_STACK_SIZE/8] \ -__attribute__((section(".bss.os.thread.stack"))); -#endif +__attribute__((section(".bss.os.thread.idle.stack"))); + // Idle Thread Attributes static const osThreadAttr_t os_idle_thread_attr = { #if defined(OS_IDLE_THREAD_NAME) @@ -184,13 +172,9 @@ __attribute__((section(".data.os.timer.mpi"))) = static osRtxThread_t os_timer_thread_cb \ __attribute__((section(".bss.os.thread.cb"))); -#if defined (__CC_ARM) -static uint64_t os_timer_thread_stack[OS_TIMER_THREAD_STACK_SIZE/8]; -#else // Timer Thread Stack static uint64_t os_timer_thread_stack[OS_TIMER_THREAD_STACK_SIZE/8] \ -__attribute__((section(".bss.os.thread.stack"))); -#endif +__attribute__((section(".bss.os.thread.timer.stack"))); // Timer Thread Attributes static const osThreadAttr_t os_timer_thread_attr = { @@ -232,10 +216,8 @@ static const osMessageQueueAttr_t os_timer_mq_attr = { (uint32_t)sizeof(os_timer_mq_data) }; -#else - -extern void osRtxTimerThread (void *argument); - void osRtxTimerThread (void *argument) { (void)argument; } +extern int32_t osRtxTimerSetup (void); +extern void osRtxTimerThread (void *argument); #endif // ((OS_TIMER_THREAD_STACK_SIZE != 0) && (OS_TIMER_CB_QUEUE != 0)) @@ -326,7 +308,7 @@ __attribute__((section(".data.os.mempool.mpi"))) = #if ((OS_MEMPOOL_DATA_SIZE % 8) != 0) #error "Invalid Data Memory size for Memory Pools!" #endif -static uint64_t os_mp_data[2 + OS_MEMPOOL_NUM + (OS_MEMPOOL_DATA_SIZE/8)] \ +static uint64_t os_mp_data[(16 + (8*OS_MEMPOOL_NUM) + OS_MEMPOOL_DATA_SIZE)/8] \ __attribute__((section(".bss.os.mempool.mem"))); #endif @@ -356,7 +338,7 @@ __attribute__((section(".data.os.msgqueue.mpi"))) = #if ((OS_MSGQUEUE_DATA_SIZE % 8) != 0) #error "Invalid Data Memory size for Message Queues!" #endif -static uint64_t os_mq_data[2 + OS_MSGQUEUE_NUM + (OS_MSGQUEUE_DATA_SIZE/8)] \ +static uint64_t os_mq_data[(16 + ((8+12)*OS_MSGQUEUE_NUM) + OS_MSGQUEUE_DATA_SIZE + 7)/8] \ __attribute__((section(".bss.os.msgqueue.mem"))); #endif @@ -368,69 +350,57 @@ __attribute__((section(".bss.os.msgqueue.mem"))); #if (defined(OS_EVR_INIT) && (OS_EVR_INIT != 0)) -// Initial Thread configuration covered also Thread Flags and Generic Wait -#if defined(OS_EVR_THREAD_FILTER) -#if !defined(OS_EVR_THFLAGS_FILTER) -#define OS_EVR_THFLAGS_FILTER OS_EVR_THREAD_FILTER -#endif -#if !defined(OS_EVR_WAIT_FILTER) -#define OS_EVR_WAIT_FILTER OS_EVR_THREAD_FILTER -#endif -#endif +#ifdef RTE_Compiler_EventRecorder -// Migrate initial filter configuration -#if defined(OS_EVR_MEMORY_FILTER) -#define OS_EVR_MEMORY_LEVEL (((OS_EVR_MEMORY_FILTER & 0x80U) != 0U) ? (OS_EVR_MEMORY_FILTER & 0x0FU) : 0U) +// Event Recorder Initialize +__STATIC_INLINE void evr_initialize (void) { + + (void)EventRecorderInitialize(OS_EVR_LEVEL, (uint32_t)OS_EVR_START); + +#if ((OS_EVR_MEMORY_LEVEL & 0x80U) != 0U) + (void)EventRecorderEnable( OS_EVR_MEMORY_LEVEL & 0x0FU, EvtRtxMemoryNo, EvtRtxMemoryNo); + (void)EventRecorderDisable(~OS_EVR_MEMORY_LEVEL & 0x0FU, EvtRtxMemoryNo, EvtRtxMemoryNo); #endif -#if defined(OS_EVR_KERNEL_FILTER) -#define OS_EVR_KERNEL_LEVEL (((OS_EVR_KERNEL_FILTER & 0x80U) != 0U) ? (OS_EVR_KERNEL_FILTER & 0x0FU) : 0U) +#if ((OS_EVR_KERNEL_LEVEL & 0x80U) != 0U) + (void)EventRecorderEnable( OS_EVR_KERNEL_LEVEL & 0x0FU, EvtRtxKernelNo, EvtRtxKernelNo); + (void)EventRecorderDisable(~OS_EVR_KERNEL_LEVEL & 0x0FU, EvtRtxKernelNo, EvtRtxMemoryNo); #endif -#if defined(OS_EVR_THREAD_FILTER) -#define OS_EVR_THREAD_LEVEL (((OS_EVR_THREAD_FILTER & 0x80U) != 0U) ? (OS_EVR_THREAD_FILTER & 0x0FU) : 0U) +#if ((OS_EVR_THREAD_LEVEL & 0x80U) != 0U) + (void)EventRecorderEnable( OS_EVR_THREAD_LEVEL & 0x0FU, EvtRtxThreadNo, EvtRtxThreadNo); + (void)EventRecorderDisable(~OS_EVR_THREAD_LEVEL & 0x0FU, EvtRtxThreadNo, EvtRtxThreadNo); #endif -#if defined(OS_EVR_WAIT_FILTER) -#define OS_EVR_WAIT_LEVEL (((OS_EVR_WAIT_FILTER & 0x80U) != 0U) ? (OS_EVR_WAIT_FILTER & 0x0FU) : 0U) +#if ((OS_EVR_WAIT_LEVEL & 0x80U) != 0U) + (void)EventRecorderEnable( OS_EVR_WAIT_LEVEL & 0x0FU, EvtRtxWaitNo, EvtRtxWaitNo); + (void)EventRecorderDisable(~OS_EVR_WAIT_LEVEL & 0x0FU, EvtRtxWaitNo, EvtRtxWaitNo); #endif -#if defined(OS_EVR_THFLAGS_FILTER) -#define OS_EVR_THFLAGS_LEVEL (((OS_EVR_THFLAGS_FILTER & 0x80U) != 0U) ? (OS_EVR_THFLAGS_FILTER & 0x0FU) : 0U) +#if ((OS_EVR_THFLAGS_LEVEL & 0x80U) != 0U) + (void)EventRecorderEnable( OS_EVR_THFLAGS_LEVEL & 0x0FU, EvtRtxThreadFlagsNo, EvtRtxThreadFlagsNo); + (void)EventRecorderDisable(~OS_EVR_THFLAGS_LEVEL & 0x0FU, EvtRtxThreadFlagsNo, EvtRtxThreadFlagsNo); #endif -#if defined(OS_EVR_EVFLAGS_FILTER) -#define OS_EVR_EVFLAGS_LEVEL (((OS_EVR_EVFLAGS_FILTER & 0x80U) != 0U) ? (OS_EVR_EVFLAGS_FILTER & 0x0FU) : 0U) +#if ((OS_EVR_EVFLAGS_LEVEL & 0x80U) != 0U) + (void)EventRecorderEnable( OS_EVR_EVFLAGS_LEVEL & 0x0FU, EvtRtxEventFlagsNo, EvtRtxEventFlagsNo); + (void)EventRecorderDisable(~OS_EVR_EVFLAGS_LEVEL & 0x0FU, EvtRtxEventFlagsNo, EvtRtxEventFlagsNo); #endif -#if defined(OS_EVR_TIMER_FILTER) -#define OS_EVR_TIMER_LEVEL (((OS_EVR_TIMER_FILTER & 0x80U) != 0U) ? (OS_EVR_TIMER_FILTER & 0x0FU) : 0U) +#if ((OS_EVR_TIMER_LEVEL & 0x80U) != 0U) + (void)EventRecorderEnable( OS_EVR_TIMER_LEVEL & 0x0FU, EvtRtxTimerNo, EvtRtxTimerNo); + (void)EventRecorderDisable(~OS_EVR_TIMER_LEVEL & 0x0FU, EvtRtxTimerNo, EvtRtxTimerNo); #endif -#if defined(OS_EVR_MUTEX_FILTER) -#define OS_EVR_MUTEX_LEVEL (((OS_EVR_MUTEX_FILTER & 0x80U) != 0U) ? (OS_EVR_MUTEX_FILTER & 0x0FU) : 0U) +#if ((OS_EVR_MUTEX_LEVEL & 0x80U) != 0U) + (void)EventRecorderEnable( OS_EVR_MUTEX_LEVEL & 0x0FU, EvtRtxMutexNo, EvtRtxMutexNo); + (void)EventRecorderDisable(~OS_EVR_MUTEX_LEVEL & 0x0FU, EvtRtxMutexNo, EvtRtxMutexNo); #endif -#if defined(OS_EVR_SEMAPHORE_FILTER) -#define OS_EVR_SEMAPHORE_LEVEL (((OS_EVR_SEMAPHORE_FILTER & 0x80U) != 0U) ? (OS_EVR_SEMAPHORE_FILTER & 0x0FU) : 0U) +#if ((OS_EVR_SEMAPHORE_LEVEL & 0x80U) != 0U) + (void)EventRecorderEnable( OS_EVR_SEMAPHORE_LEVEL & 0x0FU, EvtRtxSemaphoreNo, EvtRtxSemaphoreNo); + (void)EventRecorderDisable(~OS_EVR_SEMAPHORE_LEVEL & 0x0FU, EvtRtxSemaphoreNo, EvtRtxSemaphoreNo); #endif -#if defined(OS_EVR_MEMPOOL_FILTER) -#define OS_EVR_MEMPOOL_LEVEL (((OS_EVR_MEMPOOL_FILTER & 0x80U) != 0U) ? (OS_EVR_MEMPOOL_FILTER & 0x0FU) : 0U) +#if ((OS_EVR_MEMPOOL_LEVEL & 0x80U) != 0U) + (void)EventRecorderEnable( OS_EVR_MEMPOOL_LEVEL & 0x0FU, EvtRtxMemoryPoolNo, EvtRtxMemoryPoolNo); + (void)EventRecorderDisable(~OS_EVR_MEMPOOL_LEVEL & 0x0FU, EvtRtxMemoryPoolNo, EvtRtxMemoryPoolNo); #endif -#if defined(OS_EVR_MSGQUEUE_FILTER) -#define OS_EVR_MSGQUEUE_LEVEL (((OS_EVR_MSGQUEUE_FILTER & 0x80U) != 0U) ? (OS_EVR_MSGQUEUE_FILTER & 0x0FU) : 0U) +#if ((OS_EVR_MSGQUEUE_LEVEL & 0x80U) != 0U) + (void)EventRecorderEnable( OS_EVR_MSGQUEUE_LEVEL & 0x0FU, EvtRtxMessageQueueNo, EvtRtxMessageQueueNo); + (void)EventRecorderDisable(~OS_EVR_MSGQUEUE_LEVEL & 0x0FU, EvtRtxMessageQueueNo, EvtRtxMessageQueueNo); #endif - -#if defined(RTE_Compiler_EventRecorder) - -// Event Recorder Initialize -__STATIC_INLINE void evr_initialize (void) { - - (void)EventRecorderInitialize(OS_EVR_LEVEL, (uint32_t)OS_EVR_START); - - (void)EventRecorderEnable(OS_EVR_MEMORY_LEVEL, EvtRtxMemoryNo, EvtRtxMemoryNo); - (void)EventRecorderEnable(OS_EVR_KERNEL_LEVEL, EvtRtxKernelNo, EvtRtxKernelNo); - (void)EventRecorderEnable(OS_EVR_THREAD_LEVEL, EvtRtxThreadNo, EvtRtxThreadNo); - (void)EventRecorderEnable(OS_EVR_WAIT_LEVEL, EvtRtxWaitNo, EvtRtxWaitNo); - (void)EventRecorderEnable(OS_EVR_THFLAGS_LEVEL, EvtRtxThreadFlagsNo, EvtRtxThreadFlagsNo); - (void)EventRecorderEnable(OS_EVR_EVFLAGS_LEVEL, EvtRtxEventFlagsNo, EvtRtxEventFlagsNo); - (void)EventRecorderEnable(OS_EVR_TIMER_LEVEL, EvtRtxTimerNo, EvtRtxTimerNo); - (void)EventRecorderEnable(OS_EVR_MUTEX_LEVEL, EvtRtxMutexNo, EvtRtxMutexNo); - (void)EventRecorderEnable(OS_EVR_SEMAPHORE_LEVEL, EvtRtxSemaphoreNo, EvtRtxSemaphoreNo); - (void)EventRecorderEnable(OS_EVR_MEMPOOL_LEVEL, EvtRtxMemoryPoolNo, EvtRtxMemoryPoolNo); - (void)EventRecorderEnable(OS_EVR_MSGQUEUE_LEVEL, EvtRtxMessageQueueNo, EvtRtxMessageQueueNo); } #else @@ -539,9 +509,13 @@ __attribute__((section(".rodata"))) = &os_idle_thread_attr, #if ((OS_TIMER_THREAD_STACK_SIZE != 0) && (OS_TIMER_CB_QUEUE != 0)) &os_timer_thread_attr, + osRtxTimerThread, + osRtxTimerSetup, &os_timer_mq_attr, (uint32_t)OS_TIMER_CB_QUEUE #else + NULL, + NULL, NULL, NULL, 0U @@ -553,9 +527,9 @@ __attribute__((section(".rodata"))) = //lint -esym(526,irqRtxLib) "Defined by Exception handlers" //lint -esym(714,irqRtxLibRef) "Non weak reference" //lint -esym(765,irqRtxLibRef) "Global scope" -extern uint8_t irqRtxLib; -extern const uint8_t *irqRtxLibRef; - const uint8_t *irqRtxLibRef = &irqRtxLib; +extern const uint8_t irqRtxLib; +extern const uint8_t * const irqRtxLibRef; + const uint8_t * const irqRtxLibRef = &irqRtxLib; // Default User SVC Table //lint -esym(714,osRtxUserSVC) "Referenced by Exception handlers" @@ -570,35 +544,43 @@ __WEAK void * const osRtxUserSVC[1] = { (void *)0 }; #if defined(__CC_ARM) || \ (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) -static uint32_t __os_thread_cb_start__ __attribute__((weakref(".bss.os.thread.cb$$Base"))); //lint -esym(728,__os_thread_cb_start__) -static uint32_t __os_thread_cb_end__ __attribute__((weakref(".bss.os.thread.cb$$Limit"))); //lint -esym(728,__os_thread_cb_end__) -static uint32_t __os_timer_cb_start__ __attribute__((weakref(".bss.os.timer.cb$$Base"))); //lint -esym(728,__os_timer_cb_start__) -static uint32_t __os_timer_cb_end__ __attribute__((weakref(".bss.os.timer.cb$$Limit"))); //lint -esym(728,__os_timer_cb_end__) -static uint32_t __os_evflags_cb_start__ __attribute__((weakref(".bss.os.evflags.cb$$Base"))); //lint -esym(728,__os_evflags_cb_start__) -static uint32_t __os_evflags_cb_end__ __attribute__((weakref(".bss.os.evflags.cb$$Limit"))); //lint -esym(728,__os_evflags_cb_end__) -static uint32_t __os_mutex_cb_start__ __attribute__((weakref(".bss.os.mutex.cb$$Base"))); //lint -esym(728,__os_mutex_cb_start__) -static uint32_t __os_mutex_cb_end__ __attribute__((weakref(".bss.os.mutex.cb$$Limit"))); //lint -esym(728,__os_mutex_cb_end__) -static uint32_t __os_semaphore_cb_start__ __attribute__((weakref(".bss.os.semaphore.cb$$Base"))); //lint -esym(728,__os_semaphore_cb_start__) -static uint32_t __os_semaphore_cb_end__ __attribute__((weakref(".bss.os.semaphore.cb$$Limit"))); //lint -esym(728,__os_semaphore_cb_end__) -static uint32_t __os_mempool_cb_start__ __attribute__((weakref(".bss.os.mempool.cb$$Base"))); //lint -esym(728,__os_mempool_cb_start__) -static uint32_t __os_mempool_cb_end__ __attribute__((weakref(".bss.os.mempool.cb$$Limit"))); //lint -esym(728,__os_mempool_cb_end__) -static uint32_t __os_msgqueue_cb_start__ __attribute__((weakref(".bss.os.msgqueue.cb$$Base"))); //lint -esym(728,__os_msgqueue_cb_start__) -static uint32_t __os_msgqueue_cb_end__ __attribute__((weakref(".bss.os.msgqueue.cb$$Limit"))); //lint -esym(728,__os_msgqueue_cb_end__) +// Initialized through linker +//lint -esym(728, __os_thread_cb_start__, __os_thread_cb_end__) +//lint -esym(728, __os_timer_cb_start__, __os_timer_cb_end__) +//lint -esym(728, __os_evflags_cb_start__, __os_evflags_cb_end__) +//lint -esym(728, __os_mutex_cb_start__, __os_mutex_cb_end__) +//lint -esym(728, __os_semaphore_cb_start__, __os_semaphore_cb_end__) +//lint -esym(728, __os_mempool_cb_start__, __os_mempool_cb_end__) +//lint -esym(728, __os_msgqueue_cb_start__, __os_msgqueue_cb_end__) +static const uint32_t __os_thread_cb_start__ __attribute__((weakref(".bss.os.thread.cb$$Base"))); +static const uint32_t __os_thread_cb_end__ __attribute__((weakref(".bss.os.thread.cb$$Limit"))); +static const uint32_t __os_timer_cb_start__ __attribute__((weakref(".bss.os.timer.cb$$Base"))); +static const uint32_t __os_timer_cb_end__ __attribute__((weakref(".bss.os.timer.cb$$Limit"))); +static const uint32_t __os_evflags_cb_start__ __attribute__((weakref(".bss.os.evflags.cb$$Base"))); +static const uint32_t __os_evflags_cb_end__ __attribute__((weakref(".bss.os.evflags.cb$$Limit"))); +static const uint32_t __os_mutex_cb_start__ __attribute__((weakref(".bss.os.mutex.cb$$Base"))); +static const uint32_t __os_mutex_cb_end__ __attribute__((weakref(".bss.os.mutex.cb$$Limit"))); +static const uint32_t __os_semaphore_cb_start__ __attribute__((weakref(".bss.os.semaphore.cb$$Base"))); +static const uint32_t __os_semaphore_cb_end__ __attribute__((weakref(".bss.os.semaphore.cb$$Limit"))); +static const uint32_t __os_mempool_cb_start__ __attribute__((weakref(".bss.os.mempool.cb$$Base"))); +static const uint32_t __os_mempool_cb_end__ __attribute__((weakref(".bss.os.mempool.cb$$Limit"))); +static const uint32_t __os_msgqueue_cb_start__ __attribute__((weakref(".bss.os.msgqueue.cb$$Base"))); +static const uint32_t __os_msgqueue_cb_end__ __attribute__((weakref(".bss.os.msgqueue.cb$$Limit"))); #else -extern uint32_t __os_thread_cb_start__ __attribute__((weak)); -extern uint32_t __os_thread_cb_end__ __attribute__((weak)); -extern uint32_t __os_timer_cb_start__ __attribute__((weak)); -extern uint32_t __os_timer_cb_end__ __attribute__((weak)); -extern uint32_t __os_evflags_cb_start__ __attribute__((weak)); -extern uint32_t __os_evflags_cb_end__ __attribute__((weak)); -extern uint32_t __os_mutex_cb_start__ __attribute__((weak)); -extern uint32_t __os_mutex_cb_end__ __attribute__((weak)); -extern uint32_t __os_semaphore_cb_start__ __attribute__((weak)); -extern uint32_t __os_semaphore_cb_end__ __attribute__((weak)); -extern uint32_t __os_mempool_cb_start__ __attribute__((weak)); -extern uint32_t __os_mempool_cb_end__ __attribute__((weak)); -extern uint32_t __os_msgqueue_cb_start__ __attribute__((weak)); -extern uint32_t __os_msgqueue_cb_end__ __attribute__((weak)); +extern const uint32_t __os_thread_cb_start__ __attribute__((weak)); +extern const uint32_t __os_thread_cb_end__ __attribute__((weak)); +extern const uint32_t __os_timer_cb_start__ __attribute__((weak)); +extern const uint32_t __os_timer_cb_end__ __attribute__((weak)); +extern const uint32_t __os_evflags_cb_start__ __attribute__((weak)); +extern const uint32_t __os_evflags_cb_end__ __attribute__((weak)); +extern const uint32_t __os_mutex_cb_start__ __attribute__((weak)); +extern const uint32_t __os_mutex_cb_end__ __attribute__((weak)); +extern const uint32_t __os_semaphore_cb_start__ __attribute__((weak)); +extern const uint32_t __os_semaphore_cb_end__ __attribute__((weak)); +extern const uint32_t __os_mempool_cb_start__ __attribute__((weak)); +extern const uint32_t __os_mempool_cb_end__ __attribute__((weak)); +extern const uint32_t __os_msgqueue_cb_start__ __attribute__((weak)); +extern const uint32_t __os_msgqueue_cb_end__ __attribute__((weak)); #endif //lint -e{9067} "extern array declared without size" @@ -649,6 +631,14 @@ __WEAK void software_init_hook (void) { (void)osKernelInitialize(); } +#elif defined(__ICCARM__) + +extern void $Super$$__iar_data_init3 (void); +void $Sub$$__iar_data_init3 (void) { + $Super$$__iar_data_init3(); + (void)osKernelInitialize(); +} + #endif @@ -717,7 +707,7 @@ void *__user_perthread_libspace (void) { } } if (n == (uint32_t)OS_THREAD_LIBSPACE_NUM) { - (void)osRtxErrorNotify(osRtxErrorClibSpace, id); + (void)osRtxKernelErrorNotify(osRtxErrorClibSpace, id); } } else { n = OS_THREAD_LIBSPACE_NUM; @@ -746,7 +736,7 @@ __WEAK int _mutex_initialize(mutex *m) { result = 1; } else { result = 0; - (void)osRtxErrorNotify(osRtxErrorClibMutex, m); + (void)osRtxKernelErrorNotify(osRtxErrorClibMutex, m); } return result; } diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_lib.h b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_lib.h index 2d23625e49d..242f36f9f62 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_lib.h +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_lib.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -27,6 +27,7 @@ #define RTX_LIB_H_ #include +#include "rtx_def.h" // RTX Configuration definitions #include "rtx_core_c.h" // Cortex core definitions #if ((defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0)) || \ (defined(__ARM_ARCH_8M_MAIN__) && (__ARM_ARCH_8M_MAIN__ != 0)) || \ @@ -35,7 +36,6 @@ #endif #include "os_tick.h" // CMSIS OS Tick API #include "cmsis_os2.h" // CMSIS RTOS API -#include "RTX_Config.h" // RTX Configuration #include "rtx_os.h" // RTX OS definitions #include "rtx_evr.h" // RTX Event Recorder definitions @@ -189,11 +189,14 @@ extern void osRtxThreadSwitch (os_thread_t *thread); extern void osRtxThreadDispatch (os_thread_t *thread); extern void osRtxThreadWaitExit (os_thread_t *thread, uint32_t ret_val, bool_t dispatch); extern bool_t osRtxThreadWaitEnter (uint8_t state, uint32_t timeout); -extern void osRtxThreadStackCheck (void); +#ifdef RTX_STACK_CHECK +extern bool_t osRtxThreadStackCheck (const os_thread_t *thread); +#endif extern bool_t osRtxThreadStartup (void); // Timer Library functions -extern void osRtxTimerThread (void *argument); +extern int32_t osRtxTimerSetup (void); +extern void osRtxTimerThread (void *argument); // Mutex Library functions extern void osRtxMutexOwnerRelease (os_mutex_t *mutex_list); @@ -209,6 +212,9 @@ extern uint32_t osRtxMemoryPoolInit (os_mp_info_t *mp_info, uint32_t block_co extern void *osRtxMemoryPoolAlloc (os_mp_info_t *mp_info); extern osStatus_t osRtxMemoryPoolFree (os_mp_info_t *mp_info, void *block); +// Message Queue Library functions +extern int32_t osRtxMessageQueueTimerSetup (void); + // System Library functions extern void osRtxTick_Handler (void); extern void osRtxPendSV_Handler (void); diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_mempool.c b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_mempool.c index f7a18723d27..30c924825a5 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_mempool.c +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_mempool.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -27,7 +27,7 @@ // OS Runtime Object Memory Usage -#if ((defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))) +#ifdef RTX_OBJ_MEM_USAGE osRtxObjectMemUsage_t osRtxMemoryPoolMemUsage \ __attribute__((section(".data.os.mempool.obj"))) = { 0U, 0U, 0U }; @@ -191,20 +191,16 @@ static osMemoryPoolId_t svcRtxMemoryPoolNew (uint32_t block_count, uint32_t bloc const char *name; // Check parameters - if ((block_count == 0U) || (block_size == 0U)) { + if ((block_count == 0U) || (block_size == 0U) || + ((__CLZ(block_count) + __CLZ(block_size)) < 32U)) { EvrRtxMemoryPoolError(NULL, (int32_t)osErrorParameter); //lint -e{904} "Return statement before end of function" [MISRA Note 1] return NULL; } + b_count = block_count; b_size = (block_size + 3U) & ~3UL; - if ((__CLZ(b_count) + __CLZ(b_size)) < 32U) { - EvrRtxMemoryPoolError(NULL, (int32_t)osErrorParameter); - //lint -e{904} "Return statement before end of function" [MISRA Note 1] - return NULL; - } - - size = b_count * b_size; + size = b_count * b_size; // Process attributes if (attr != NULL) { @@ -229,7 +225,7 @@ static osMemoryPoolId_t svcRtxMemoryPoolNew (uint32_t block_count, uint32_t bloc } } if (mp_mem != NULL) { - //lint -e(923) -e(9078) "cast from pointer to unsigned int" [MISRA Note 7] + //lint -e{923} "cast from pointer to unsigned int" [MISRA Note 7] if ((((uint32_t)mp_mem & 3U) != 0U) || (mp_size < size)) { EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidDataMemory); //lint -e{904} "Return statement before end of function" [MISRA Note 1] @@ -257,7 +253,7 @@ static osMemoryPoolId_t svcRtxMemoryPoolNew (uint32_t block_count, uint32_t bloc //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5] mp = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_memory_pool_t), 1U); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE if (mp != NULL) { uint32_t used; osRtxMemoryPoolMemUsage.cnt_alloc++; @@ -283,13 +279,13 @@ static osMemoryPoolId_t svcRtxMemoryPoolNew (uint32_t block_count, uint32_t bloc } else { (void)osRtxMemoryFree(osRtxInfo.mem.common, mp); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE osRtxMemoryPoolMemUsage.cnt_free++; #endif } mp = NULL; } else { - memset(mp_mem, 0, size); + (void)memset(mp_mem, 0, size); } flags |= osRtxFlagSystemMemory; } @@ -508,7 +504,7 @@ static osStatus_t svcRtxMemoryPoolDelete (osMemoryPoolId_t mp_id) { } else { (void)osRtxMemoryFree(osRtxInfo.mem.common, mp); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE osRtxMemoryPoolMemUsage.cnt_free++; #endif } @@ -594,7 +590,7 @@ osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, con osMemoryPoolId_t mp_id; EvrRtxMemoryPoolNew(block_count, block_size, attr); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxMemoryPoolError(NULL, (int32_t)osErrorISR); mp_id = NULL; } else { @@ -607,7 +603,7 @@ osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, con const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id) { const char *name; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxMemoryPoolGetName(mp_id, NULL); name = NULL; } else { @@ -621,7 +617,7 @@ void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) { void *memory; EvrRtxMemoryPoolAlloc(mp_id, timeout); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { memory = isrRtxMemoryPoolAlloc(mp_id, timeout); } else { memory = __svcMemoryPoolAlloc(mp_id, timeout); @@ -634,7 +630,7 @@ osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) { osStatus_t status; EvrRtxMemoryPoolFree(mp_id, block); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { status = isrRtxMemoryPoolFree(mp_id, block); } else { status = __svcMemoryPoolFree(mp_id, block); @@ -646,7 +642,7 @@ osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) { uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) { uint32_t capacity; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { capacity = svcRtxMemoryPoolGetCapacity(mp_id); } else { capacity = __svcMemoryPoolGetCapacity(mp_id); @@ -658,7 +654,7 @@ uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) { uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) { uint32_t block_size; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { block_size = svcRtxMemoryPoolGetBlockSize(mp_id); } else { block_size = __svcMemoryPoolGetBlockSize(mp_id); @@ -670,7 +666,7 @@ uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) { uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id) { uint32_t count; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { count = svcRtxMemoryPoolGetCount(mp_id); } else { count = __svcMemoryPoolGetCount(mp_id); @@ -682,7 +678,7 @@ uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id) { uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id) { uint32_t space; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { space = svcRtxMemoryPoolGetSpace(mp_id); } else { space = __svcMemoryPoolGetSpace(mp_id); @@ -695,7 +691,7 @@ osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id) { osStatus_t status; EvrRtxMemoryPoolDelete(mp_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxMemoryPoolError(mp_id, (int32_t)osErrorISR); status = osErrorISR; } else { diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_msgqueue.c b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_msgqueue.c index 5451998c6f7..c052811e508 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_msgqueue.c +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_msgqueue.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -27,7 +27,7 @@ // OS Runtime Object Memory Usage -#if ((defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))) +#ifdef RTX_OBJ_MEM_USAGE osRtxObjectMemUsage_t osRtxMessageQueueMemUsage \ __attribute__((section(".data.os.msgqueue.obj"))) = { 0U, 0U, 0U }; @@ -189,7 +189,7 @@ static void osRtxMessageQueuePostProcess (os_message_t *msg) { reg = osRtxThreadRegPtr(thread); //lint -e{923} "cast from unsigned int to pointer" ptr_src = (const void *)reg[2]; - memcpy(&msg0[1], ptr_src, mq->msg_size); + (void)memcpy(&msg0[1], ptr_src, mq->msg_size); // Store Message into Queue msg0->id = osRtxIdMessage; msg0->flags = 0U; @@ -214,7 +214,7 @@ static void osRtxMessageQueuePostProcess (os_message_t *msg) { reg = osRtxThreadRegPtr(thread); //lint -e{923} "cast from unsigned int to pointer" ptr_dst = (void *)reg[2]; - memcpy(ptr_dst, &msg[1], mq->msg_size); + (void)memcpy(ptr_dst, &msg[1], mq->msg_size); if (reg[3] != 0U) { //lint -e{923} -e{9078} "cast from unsigned int to pointer" *((uint8_t *)reg[3]) = msg->priority; @@ -245,19 +245,15 @@ static osMessageQueueId_t svcRtxMessageQueueNew (uint32_t msg_count, uint32_t ms const char *name; // Check parameters - if ((msg_count == 0U) || (msg_size == 0U)) { - EvrRtxMessageQueueError(NULL, (int32_t)osErrorParameter); - //lint -e{904} "Return statement before end of function" [MISRA Note 1] - return NULL; - } - block_size = ((msg_size + 3U) & ~3UL) + sizeof(os_message_t); - if ((__CLZ(msg_count) + __CLZ(block_size)) < 32U) { + if ((msg_count == 0U) || (msg_size == 0U) || + ((__CLZ(msg_count) + __CLZ(msg_size)) < 32U)) { EvrRtxMessageQueueError(NULL, (int32_t)osErrorParameter); //lint -e{904} "Return statement before end of function" [MISRA Note 1] return NULL; } - size = msg_count * block_size; + block_size = ((msg_size + 3U) & ~3UL) + sizeof(os_message_t); + size = msg_count * block_size; // Process attributes if (attr != NULL) { @@ -282,7 +278,7 @@ static osMessageQueueId_t svcRtxMessageQueueNew (uint32_t msg_count, uint32_t ms } } if (mq_mem != NULL) { - //lint -e(923) -e(9078) "cast from pointer to unsigned int" [MISRA Note 7] + //lint -e{923} "cast from pointer to unsigned int" [MISRA Note 7] if ((((uint32_t)mq_mem & 3U) != 0U) || (mq_size < size)) { EvrRtxMessageQueueError(NULL, osRtxErrorInvalidDataMemory); //lint -e{904} "Return statement before end of function" [MISRA Note 1] @@ -310,7 +306,7 @@ static osMessageQueueId_t svcRtxMessageQueueNew (uint32_t msg_count, uint32_t ms //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5] mq = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_message_queue_t), 1U); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE if (mq != NULL) { uint32_t used; osRtxMessageQueueMemUsage.cnt_alloc++; @@ -336,13 +332,13 @@ static osMessageQueueId_t svcRtxMessageQueueNew (uint32_t msg_count, uint32_t ms } else { (void)osRtxMemoryFree(osRtxInfo.mem.common, mq); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE osRtxMessageQueueMemUsage.cnt_free++; #endif } mq = NULL; } else { - memset(mq_mem, 0, size); + (void)memset(mq_mem, 0, size); } flags |= osRtxFlagSystemMemory; } @@ -414,7 +410,7 @@ static osStatus_t svcRtxMessageQueuePut (osMessageQueueId_t mq_id, const void *m reg = osRtxThreadRegPtr(thread); //lint -e{923} "cast from unsigned int to pointer" ptr = (void *)reg[2]; - memcpy(ptr, msg_ptr, mq->msg_size); + (void)memcpy(ptr, msg_ptr, mq->msg_size); if (reg[3] != 0U) { //lint -e{923} -e{9078} "cast from unsigned int to pointer" *((uint8_t *)reg[3]) = msg_prio; @@ -427,7 +423,7 @@ static osStatus_t svcRtxMessageQueuePut (osMessageQueueId_t mq_id, const void *m msg = osRtxMemoryPoolAlloc(&mq->mp_info); if (msg != NULL) { // Copy Message - memcpy(&msg[1], msg_ptr, mq->msg_size); + (void)memcpy(&msg[1], msg_ptr, mq->msg_size); // Put Message into Queue msg->id = osRtxIdMessage; msg->flags = 0U; @@ -485,7 +481,7 @@ static osStatus_t svcRtxMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr if (msg != NULL) { MessageQueueRemove(mq, msg); // Copy Message - memcpy(msg_ptr, &msg[1], mq->msg_size); + (void)memcpy(msg_ptr, &msg[1], mq->msg_size); if (msg_prio != NULL) { *msg_prio = msg->priority; } @@ -506,7 +502,7 @@ static osStatus_t svcRtxMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr reg = osRtxThreadRegPtr(thread); //lint -e{923} "cast from unsigned int to pointer" ptr = (const void *)reg[2]; - memcpy(&msg[1], ptr, mq->msg_size); + (void)memcpy(&msg[1], ptr, mq->msg_size); // Store Message into Queue msg->id = osRtxIdMessage; msg->flags = 0U; @@ -655,7 +651,7 @@ static osStatus_t svcRtxMessageQueueReset (osMessageQueueId_t mq_id) { reg = osRtxThreadRegPtr(thread); //lint -e{923} "cast from unsigned int to pointer" ptr = (const void *)reg[2]; - memcpy(&msg[1], ptr, mq->msg_size); + (void)memcpy(&msg[1], ptr, mq->msg_size); // Store Message into Queue msg->id = osRtxIdMessage; msg->flags = 0U; @@ -709,7 +705,7 @@ static osStatus_t svcRtxMessageQueueDelete (osMessageQueueId_t mq_id) { } else { (void)osRtxMemoryFree(osRtxInfo.mem.common, mq); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE osRtxMessageQueueMemUsage.cnt_free++; #endif } @@ -756,7 +752,7 @@ osStatus_t isrRtxMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, msg = osRtxMemoryPoolAlloc(&mq->mp_info); if (msg != NULL) { // Copy Message - memcpy(&msg[1], msg_ptr, mq->msg_size); + (void)memcpy(&msg[1], msg_ptr, mq->msg_size); msg->id = osRtxIdMessage; msg->flags = 0U; msg->priority = msg_prio; @@ -816,6 +812,23 @@ osStatus_t isrRtxMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8 } +// ==== Library functions ==== + +/// Create a Message Queue for the Timer Thread. +int32_t osRtxMessageQueueTimerSetup (void) { + int32_t ret = -1; + + osRtxInfo.timer.mq = osRtxMessageQueueId( + svcRtxMessageQueueNew(osRtxConfig.timer_mq_mcnt, sizeof(os_timer_finfo_t), osRtxConfig.timer_mq_attr) + ); + if (osRtxInfo.timer.mq != NULL) { + ret = 0; + } + + return ret; +} + + // ==== Public API ==== /// Create and Initialize a Message Queue object. @@ -823,7 +836,7 @@ osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, con osMessageQueueId_t mq_id; EvrRtxMessageQueueNew(msg_count, msg_size, attr); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxMessageQueueError(NULL, (int32_t)osErrorISR); mq_id = NULL; } else { @@ -836,7 +849,7 @@ osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, con const char *osMessageQueueGetName (osMessageQueueId_t mq_id) { const char *name; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxMessageQueueGetName(mq_id, NULL); name = NULL; } else { @@ -850,7 +863,7 @@ osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uin osStatus_t status; EvrRtxMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { status = isrRtxMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout); } else { status = __svcMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout); @@ -863,7 +876,7 @@ osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t * osStatus_t status; EvrRtxMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { status = isrRtxMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout); } else { status = __svcMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout); @@ -875,7 +888,7 @@ osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t * uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id) { uint32_t capacity; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { capacity = svcRtxMessageQueueGetCapacity(mq_id); } else { capacity = __svcMessageQueueGetCapacity(mq_id); @@ -887,7 +900,7 @@ uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id) { uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id) { uint32_t msg_size; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { msg_size = svcRtxMessageQueueGetMsgSize(mq_id); } else { msg_size = __svcMessageQueueGetMsgSize(mq_id); @@ -899,7 +912,7 @@ uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id) { uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id) { uint32_t count; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { count = svcRtxMessageQueueGetCount(mq_id); } else { count = __svcMessageQueueGetCount(mq_id); @@ -911,7 +924,7 @@ uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id) { uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id) { uint32_t space; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { space = svcRtxMessageQueueGetSpace(mq_id); } else { space = __svcMessageQueueGetSpace(mq_id); @@ -924,7 +937,7 @@ osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id) { osStatus_t status; EvrRtxMessageQueueReset(mq_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxMessageQueueError(mq_id, (int32_t)osErrorISR); status = osErrorISR; } else { @@ -938,7 +951,7 @@ osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id) { osStatus_t status; EvrRtxMessageQueueDelete(mq_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxMessageQueueError(mq_id, (int32_t)osErrorISR); status = osErrorISR; } else { diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_mutex.c b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_mutex.c index e97def252db..fb889b45d99 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_mutex.c +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_mutex.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -27,7 +27,7 @@ // OS Runtime Object Memory Usage -#if ((defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))) +#ifdef RTX_OBJ_MEM_USAGE osRtxObjectMemUsage_t osRtxMutexMemUsage \ __attribute__((section(".data.os.mutex.obj"))) = { 0U, 0U, 0U }; @@ -78,7 +78,7 @@ void osRtxMutexOwnerRelease (os_mutex_t *mutex_list) { void osRtxMutexOwnerRestore (const os_mutex_t *mutex, const os_thread_t *thread_wakeup) { const os_mutex_t *mutex0; os_thread_t *thread; - os_thread_t *thread0; + const os_thread_t *thread0; int8_t priority; // Restore owner Thread priority @@ -88,15 +88,17 @@ void osRtxMutexOwnerRestore (const os_mutex_t *mutex, const os_thread_t *thread_ mutex0 = thread->mutex_list; // Check Mutexes owned by Thread do { - // Check Threads waiting for Mutex - thread0 = mutex0->thread_list; - if (thread0 == thread_wakeup) { - // Skip thread that is waken-up - thread0 = thread0->thread_next; - } - if ((thread0 != NULL) && (thread0->priority > priority)) { - // Higher priority Thread is waiting for Mutex - priority = thread0->priority; + if ((mutex0->attr & osMutexPrioInherit) != 0U) { + // Check Threads waiting for Mutex + thread0 = mutex0->thread_list; + if (thread0 == thread_wakeup) { + // Skip thread that is waken-up + thread0 = thread0->thread_next; + } + if ((thread0 != NULL) && (thread0->priority > priority)) { + // Higher priority Thread is waiting for Mutex + priority = thread0->priority; + } } mutex0 = mutex0->owner_next; } while (mutex0 != NULL); @@ -153,7 +155,7 @@ static osMutexId_t svcRtxMutexNew (const osMutexAttr_t *attr) { //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5] mutex = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_mutex_t), 1U); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE if (mutex != NULL) { uint32_t used; osRtxMutexMemUsage.cnt_alloc++; @@ -336,19 +338,19 @@ static osStatus_t svcRtxMutexRelease (osMutexId_t mutex_id) { } // Restore running Thread priority - if ((mutex->attr & osMutexPrioInherit) != 0U) { - priority = thread->priority_base; - mutex0 = thread->mutex_list; - // Check mutexes owned by running Thread - while (mutex0 != NULL) { + priority = thread->priority_base; + mutex0 = thread->mutex_list; + // Check mutexes owned by running Thread + while (mutex0 != NULL) { + if ((mutex0->attr & osMutexPrioInherit) != 0U) { if ((mutex0->thread_list != NULL) && (mutex0->thread_list->priority > priority)) { // Higher priority Thread is waiting for Mutex priority = mutex0->thread_list->priority; } - mutex0 = mutex0->owner_next; } - thread->priority = priority; + mutex0 = mutex0->owner_next; } + thread->priority = priority; // Check if Thread is waiting for a Mutex if (mutex->thread_list != NULL) { @@ -428,21 +430,21 @@ static osStatus_t svcRtxMutexDelete (osMutexId_t mutex_id) { } // Restore owner Thread priority - if ((mutex->attr & osMutexPrioInherit) != 0U) { - priority = thread->priority_base; - mutex0 = thread->mutex_list; - // Check Mutexes owned by Thread - while (mutex0 != NULL) { + priority = thread->priority_base; + mutex0 = thread->mutex_list; + // Check Mutexes owned by Thread + while (mutex0 != NULL) { + if ((mutex0->attr & osMutexPrioInherit) != 0U) { if ((mutex0->thread_list != NULL) && (mutex0->thread_list->priority > priority)) { // Higher priority Thread is waiting for Mutex priority = mutex0->thread_list->priority; } - mutex0 = mutex0->owner_next; - } - if (thread->priority != priority) { - thread->priority = priority; - osRtxThreadListSort(thread); } + mutex0 = mutex0->owner_next; + } + if (thread->priority != priority) { + thread->priority = priority; + osRtxThreadListSort(thread); } // Unblock waiting threads @@ -464,7 +466,7 @@ static osStatus_t svcRtxMutexDelete (osMutexId_t mutex_id) { } else { (void)osRtxMemoryFree(osRtxInfo.mem.common, mutex); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE osRtxMutexMemUsage.cnt_free++; #endif } @@ -492,7 +494,7 @@ osMutexId_t osMutexNew (const osMutexAttr_t *attr) { osMutexId_t mutex_id; EvrRtxMutexNew(attr); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxMutexError(NULL, (int32_t)osErrorISR); mutex_id = NULL; } else { @@ -505,7 +507,7 @@ osMutexId_t osMutexNew (const osMutexAttr_t *attr) { const char *osMutexGetName (osMutexId_t mutex_id) { const char *name; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxMutexGetName(mutex_id, NULL); name = NULL; } else { @@ -519,7 +521,7 @@ osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) { osStatus_t status; EvrRtxMutexAcquire(mutex_id, timeout); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxMutexError(mutex_id, (int32_t)osErrorISR); status = osErrorISR; } else { @@ -533,7 +535,7 @@ osStatus_t osMutexRelease (osMutexId_t mutex_id) { osStatus_t status; EvrRtxMutexRelease(mutex_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxMutexError(mutex_id, (int32_t)osErrorISR); status = osErrorISR; } else { @@ -546,7 +548,7 @@ osStatus_t osMutexRelease (osMutexId_t mutex_id) { osThreadId_t osMutexGetOwner (osMutexId_t mutex_id) { osThreadId_t thread; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxMutexGetOwner(mutex_id, NULL); thread = NULL; } else { @@ -560,7 +562,7 @@ osStatus_t osMutexDelete (osMutexId_t mutex_id) { osStatus_t status; EvrRtxMutexDelete(mutex_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxMutexError(mutex_id, (int32_t)osErrorISR); status = osErrorISR; } else { diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_semaphore.c b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_semaphore.c index ebca85543c0..b96939aca3a 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_semaphore.c +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_semaphore.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -27,7 +27,7 @@ // OS Runtime Object Memory Usage -#if ((defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))) +#ifdef RTX_OBJ_MEM_USAGE osRtxObjectMemUsage_t osRtxSemaphoreMemUsage \ __attribute__((section(".data.os.semaphore.obj"))) = { 0U, 0U, 0U }; @@ -172,7 +172,7 @@ static osSemaphoreId_t svcRtxSemaphoreNew (uint32_t max_count, uint32_t initial_ //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5] semaphore = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_semaphore_t), 1U); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE if (semaphore != NULL) { uint32_t used; osRtxSemaphoreMemUsage.cnt_alloc++; @@ -346,7 +346,7 @@ static osStatus_t svcRtxSemaphoreDelete (osSemaphoreId_t semaphore_id) { } else { (void)osRtxMemoryFree(osRtxInfo.mem.common, semaphore); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE osRtxSemaphoreMemUsage.cnt_free++; #endif } @@ -432,7 +432,7 @@ osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, cons osSemaphoreId_t semaphore_id; EvrRtxSemaphoreNew(max_count, initial_count, attr); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxSemaphoreError(NULL, (int32_t)osErrorISR); semaphore_id = NULL; } else { @@ -445,7 +445,7 @@ osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, cons const char *osSemaphoreGetName (osSemaphoreId_t semaphore_id) { const char *name; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxSemaphoreGetName(semaphore_id, NULL); name = NULL; } else { @@ -459,7 +459,7 @@ osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout) { osStatus_t status; EvrRtxSemaphoreAcquire(semaphore_id, timeout); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { status = isrRtxSemaphoreAcquire(semaphore_id, timeout); } else { status = __svcSemaphoreAcquire(semaphore_id, timeout); @@ -472,7 +472,7 @@ osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id) { osStatus_t status; EvrRtxSemaphoreRelease(semaphore_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { status = isrRtxSemaphoreRelease(semaphore_id); } else { status = __svcSemaphoreRelease(semaphore_id); @@ -484,7 +484,7 @@ osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id) { uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id) { uint32_t count; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { count = svcRtxSemaphoreGetCount(semaphore_id); } else { count = __svcSemaphoreGetCount(semaphore_id); @@ -497,7 +497,7 @@ osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id) { osStatus_t status; EvrRtxSemaphoreDelete(semaphore_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxSemaphoreError(semaphore_id, (int32_t)osErrorISR); status = osErrorISR; } else { diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_system.c b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_system.c index a0583495cbf..bc969c80943 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_system.c +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_system.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -122,38 +122,40 @@ void osRtxTick_Handler (void) { OS_Tick_AcknowledgeIRQ(); osRtxInfo.kernel.tick++; - // Process Timers - if (osRtxInfo.timer.tick != NULL) { - osRtxInfo.timer.tick(); - } - // Process Thread Delays osRtxThreadDelayTick(); osRtxThreadDispatch(NULL); + // Process Timers + if (osRtxInfo.timer.tick != NULL) { + osRtxInfo.timer.tick(); + } + // Check Round Robin timeout if (osRtxInfo.thread.robin.timeout != 0U) { - if (osRtxInfo.thread.robin.thread != osRtxInfo.thread.run.next) { - // Reset Round Robin - osRtxInfo.thread.robin.thread = osRtxInfo.thread.run.next; - osRtxInfo.thread.robin.tick = osRtxInfo.thread.robin.timeout; - } else { - if (osRtxInfo.thread.robin.tick != 0U) { - osRtxInfo.thread.robin.tick--; + thread = osRtxInfo.thread.run.next; + if (thread != osRtxInfo.thread.robin.thread) { + osRtxInfo.thread.robin.thread = thread; + if (thread->delay == 0U) { + // Reset Round Robin + thread->delay = osRtxInfo.thread.robin.timeout; } - if (osRtxInfo.thread.robin.tick == 0U) { - // Round Robin Timeout - if (osRtxKernelGetState() == osRtxKernelRunning) { - thread = osRtxInfo.thread.ready.thread_list; - if ((thread != NULL) && (thread->priority == osRtxInfo.thread.robin.thread->priority)) { - osRtxThreadListRemove(thread); - osRtxThreadReadyPut(osRtxInfo.thread.robin.thread); - EvrRtxThreadPreempted(osRtxInfo.thread.robin.thread); - osRtxThreadSwitch(thread); - osRtxInfo.thread.robin.thread = thread; - osRtxInfo.thread.robin.tick = osRtxInfo.thread.robin.timeout; - } + } + if (thread->delay != 0U) { + thread->delay--; + } + if (thread->delay == 0U) { + // Round Robin Timeout + if (osRtxKernelGetState() == osRtxKernelRunning) { + thread = osRtxInfo.thread.ready.thread_list; + if ((thread != NULL) && (thread->priority == osRtxInfo.thread.robin.thread->priority)) { + osRtxThreadListRemove(thread); + osRtxThreadReadyPut(osRtxInfo.thread.robin.thread); + EvrRtxThreadPreempted(osRtxInfo.thread.robin.thread); + osRtxThreadSwitch(thread); + osRtxInfo.thread.robin.thread = thread; + thread->delay = osRtxInfo.thread.robin.timeout; } } } @@ -208,6 +210,6 @@ void osRtxPostProcess (os_object_t *object) { osRtxInfo.kernel.pendSV = 1U; } } else { - (void)osRtxErrorNotify(osRtxErrorISRQueueOverflow, object); + (void)osRtxKernelErrorNotify(osRtxErrorISRQueueOverflow, object); } } diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_thread.c b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_thread.c index 96a1e3196f0..6b572c60626 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_thread.c +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_thread.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -27,7 +27,7 @@ // OS Runtime Object Memory Usage -#if ((defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))) +#ifdef RTX_OBJ_MEM_USAGE osRtxObjectMemUsage_t osRtxThreadMemUsage \ __attribute__((section(".data.os.thread.obj"))) = { 0U, 0U, 0U }; @@ -313,6 +313,7 @@ static void osRtxThreadDelayRemove (os_thread_t *thread) { osRtxInfo.thread.delay_list = thread->delay_next; } } + thread->delay = 0U; } /// Process Thread Delay Tick (executed each System Tick). @@ -420,7 +421,6 @@ void osRtxThreadSwitch (os_thread_t *thread) { thread->state = osRtxThreadRunning; osRtxInfo.thread.run.next = thread; - osRtxThreadStackCheck(); EvrRtxThreadSwitched(thread); } @@ -509,22 +509,25 @@ bool_t osRtxThreadWaitEnter (uint8_t state, uint32_t timeout) { return TRUE; } +#ifdef RTX_STACK_CHECK /// Check current running Thread Stack. +/// \param[in] thread running thread. +/// \return true - success, false - failure. +//lint -esym(714,osRtxThreadStackCheck) "Referenced by Exception handlers" //lint -esym(759,osRtxThreadStackCheck) "Prototype in header" -//lint -esym(765,osRtxThreadStackCheck) "Global scope (can be overridden)" -__WEAK void osRtxThreadStackCheck (void) { - os_thread_t *thread; +//lint -esym(765,osRtxThreadStackCheck) "Global scope" +bool_t osRtxThreadStackCheck (const os_thread_t *thread) { - thread = osRtxThreadGetRunning(); - if (thread != NULL) { - //lint -e{923} "cast from pointer to unsigned int" - //lint -e{9079} -e{9087} "cast between pointers to different object types" - if ((thread->sp <= (uint32_t)thread->stack_mem) || - (*((uint32_t *)thread->stack_mem) != osRtxStackMagicWord)) { - (void)osRtxErrorNotify(osRtxErrorStackUnderflow, thread); - } + //lint -e{923} "cast from pointer to unsigned int" + //lint -e{9079} -e{9087} "cast between pointers to different object types" + if ((thread->sp <= (uint32_t)thread->stack_mem) || + (*((uint32_t *)thread->stack_mem) != osRtxStackMagicWord)) { + //lint -e{904} "Return statement before end of function" [MISRA Note 1] + return FALSE; } + return TRUE; } +#endif #ifdef RTX_TF_M_EXTENSION /// Get TrustZone Module Identifier of running Thread. @@ -617,7 +620,7 @@ static osThreadId_t svcRtxThreadNew (osThreadFunc_t func, void *argument, const } } if (stack_mem != NULL) { - //lint -e(923) -e(9078) "cast from pointer to unsigned int" [MISRA Note 7] + //lint -e{923} "cast from pointer to unsigned int" [MISRA Note 7] if ((((uint32_t)stack_mem & 7U) != 0U) || (stack_size == 0U)) { EvrRtxThreadError(NULL, osRtxErrorInvalidThreadStack); //lint -e{904} "Return statement before end of function" [MISRA Note 1] @@ -646,10 +649,12 @@ static osThreadId_t svcRtxThreadNew (osThreadFunc_t func, void *argument, const } // Check stack size - if ((stack_size != 0U) && (((stack_size & 7U) != 0U) || (stack_size < (64U + 8U)))) { - EvrRtxThreadError(NULL, osRtxErrorInvalidThreadStack); - //lint -e{904} "Return statement before end of function" [MISRA Note 1] - return NULL; + if (stack_size != 0U) { + if (((stack_size & 7U) != 0U) || (stack_size < (64U + 8U)) || (stack_size > 0x7FFFFFFFU)) { + EvrRtxThreadError(NULL, osRtxErrorInvalidThreadStack); + //lint -e{904} "Return statement before end of function" [MISRA Note 1] + return NULL; + } } // Allocate object memory if not provided @@ -661,7 +666,7 @@ static osThreadId_t svcRtxThreadNew (osThreadFunc_t func, void *argument, const //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5] thread = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_thread_t), 1U); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE if (thread != NULL) { uint32_t used; osRtxThreadMemUsage.cnt_alloc++; @@ -701,7 +706,7 @@ static osThreadId_t svcRtxThreadNew (osThreadFunc_t func, void *argument, const } else { (void)osRtxMemoryFree(osRtxInfo.mem.common, thread); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE osRtxThreadMemUsage.cnt_free++; #endif } @@ -729,7 +734,7 @@ static osThreadId_t svcRtxThreadNew (osThreadFunc_t func, void *argument, const } else { (void)osRtxMemoryFree(osRtxInfo.mem.common, thread); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE osRtxThreadMemUsage.cnt_free++; #endif } @@ -803,7 +808,7 @@ static osThreadId_t svcRtxThreadNew (osThreadFunc_t func, void *argument, const } else { EvrRtxThreadError(NULL, (int32_t)osErrorNoMemory); } - + if (thread != NULL) { osRtxThreadDispatch(thread); } @@ -1042,8 +1047,6 @@ static osStatus_t svcRtxThreadSuspend (osThreadId_t thread_id) { // Update Thread State and put it into Delay list thread->state = osRtxThreadBlocked; - thread->thread_prev = NULL; - thread->thread_next = NULL; osRtxThreadDelayInsert(thread, osWaitForever); } @@ -1079,6 +1082,19 @@ static osStatus_t svcRtxThreadResume (osThreadId_t thread_id) { return osOK; } +/// Wakeup a thread waiting to join. +/// \param[in] thread thread object. +static void osRtxThreadJoinWakeup (os_thread_t *thread) { + + if (thread->thread_join != NULL) { + osRtxThreadWaitExit(thread->thread_join, (uint32_t)osOK, FALSE); + EvrRtxThreadJoined(thread->thread_join); + } + if (thread->state == osRtxThreadWaitingJoin) { + thread->thread_next->thread_join = NULL; + } +} + /// Free Thread resources. /// \param[in] thread thread object. static void osRtxThreadFree (os_thread_t *thread) { @@ -1110,12 +1126,31 @@ static void osRtxThreadFree (os_thread_t *thread) { } else { (void)osRtxMemoryFree(osRtxInfo.mem.common, thread); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE osRtxThreadMemUsage.cnt_free++; #endif } } +/// Destroy a Thread. +/// \param[in] thread thread object. +static void osRtxThreadDestroy (os_thread_t *thread) { + + if ((thread->attr & osThreadJoinable) == 0U) { + osRtxThreadFree(thread); + } else { + // Update Thread State and put it into Terminate Thread list + thread->state = osRtxThreadTerminated; + thread->thread_prev = NULL; + thread->thread_next = osRtxInfo.thread.terminate_list; + if (osRtxInfo.thread.terminate_list != NULL) { + osRtxInfo.thread.terminate_list->thread_prev = thread; + } + osRtxInfo.thread.terminate_list = thread; + } + EvrRtxThreadDestroyed(thread); +} + /// Detach a thread (thread storage can be reclaimed when thread terminates). /// \note API identical to osThreadDetach static osStatus_t svcRtxThreadDetach (osThreadId_t thread_id) { @@ -1151,6 +1186,7 @@ static osStatus_t svcRtxThreadDetach (osThreadId_t thread_id) { /// \note API identical to osThreadJoin static osStatus_t svcRtxThreadJoin (osThreadId_t thread_id) { os_thread_t *thread = osRtxThreadId(thread_id); + os_thread_t *thread_running; osStatus_t status; // Check parameters @@ -1182,7 +1218,9 @@ static osStatus_t svcRtxThreadJoin (osThreadId_t thread_id) { } else { // Suspend current Thread if (osRtxThreadWaitEnter(osRtxThreadWaitingJoin, osWaitForever)) { - thread->thread_join = osRtxThreadGetRunning(); + thread_running = osRtxThreadGetRunning(); + thread_running->thread_next = thread; + thread->thread_join = thread_running; thread->attr &= ~osThreadJoinable; EvrRtxThreadJoinPending(thread); } else { @@ -1213,30 +1251,26 @@ static void svcRtxThreadExit (void) { osRtxMutexOwnerRelease(thread->mutex_list); // Wakeup Thread waiting to Join - if (thread->thread_join != NULL) { - osRtxThreadWaitExit(thread->thread_join, (uint32_t)osOK, FALSE); - EvrRtxThreadJoined(thread->thread_join); - } + osRtxThreadJoinWakeup(thread); // Switch to next Ready Thread - thread->sp = __get_PSP(); osRtxThreadSwitch(osRtxThreadListGet(&osRtxInfo.thread.ready)); - osRtxThreadSetRunning(NULL); - if ((thread->attr & osThreadJoinable) == 0U) { - osRtxThreadFree(thread); - } else { - // Update Thread State and put it into Terminate Thread list - thread->state = osRtxThreadTerminated; - thread->thread_prev = NULL; - thread->thread_next = osRtxInfo.thread.terminate_list; - if (osRtxInfo.thread.terminate_list != NULL) { - osRtxInfo.thread.terminate_list->thread_prev = thread; - } - osRtxInfo.thread.terminate_list = thread; + // Update Stack Pointer + thread->sp = __get_PSP(); +#ifdef RTX_STACK_CHECK + // Check Stack usage + if (!osRtxThreadStackCheck(thread)) { + osRtxThreadSetRunning(osRtxInfo.thread.run.next); + (void)osRtxKernelErrorNotify(osRtxErrorStackOverflow, thread); } +#endif - EvrRtxThreadDestroyed(thread); + // Mark running thread as deleted + osRtxThreadSetRunning(NULL); + + // Destroy Thread + osRtxThreadDestroy(thread); } /// Terminate execution of a thread. @@ -1285,34 +1319,28 @@ static osStatus_t svcRtxThreadTerminate (osThreadId_t thread_id) { osRtxMutexOwnerRelease(thread->mutex_list); // Wakeup Thread waiting to Join - if (thread->thread_join != NULL) { - osRtxThreadWaitExit(thread->thread_join, (uint32_t)osOK, FALSE); - EvrRtxThreadJoined(thread->thread_join); - } + osRtxThreadJoinWakeup(thread); // Switch to next Ready Thread when terminating running Thread if (thread->state == osRtxThreadRunning) { - thread->sp = __get_PSP(); osRtxThreadSwitch(osRtxThreadListGet(&osRtxInfo.thread.ready)); + // Update Stack Pointer + thread->sp = __get_PSP(); +#ifdef RTX_STACK_CHECK + // Check Stack usage + if (!osRtxThreadStackCheck(thread)) { + osRtxThreadSetRunning(osRtxInfo.thread.run.next); + (void)osRtxKernelErrorNotify(osRtxErrorStackOverflow, thread); + } +#endif + // Mark running thread as deleted osRtxThreadSetRunning(NULL); } else { osRtxThreadDispatch(NULL); } - if ((thread->attr & osThreadJoinable) == 0U) { - osRtxThreadFree(thread); - } else { - // Update Thread State and put it into Terminate Thread list - thread->state = osRtxThreadTerminated; - thread->thread_prev = NULL; - thread->thread_next = osRtxInfo.thread.terminate_list; - if (osRtxInfo.thread.terminate_list != NULL) { - osRtxInfo.thread.terminate_list->thread_prev = thread; - } - osRtxInfo.thread.terminate_list = thread; - } - - EvrRtxThreadDestroyed(thread); + // Destroy Thread + osRtxThreadDestroy(thread); } return status; @@ -1539,8 +1567,8 @@ SVC0_3 (ThreadNew, osThreadId_t, osThreadFunc_t, void *, const osTh SVC0_1 (ThreadGetName, const char *, osThreadId_t) SVC0_0 (ThreadGetId, osThreadId_t) SVC0_1 (ThreadGetState, osThreadState_t, osThreadId_t) -SVC0_1 (ThreadGetStackSize, uint32_t, osThreadId_t) -SVC0_1 (ThreadGetStackSpace, uint32_t, osThreadId_t) +SVC0_1 (ThreadGetStackSize, uint32_t, osThreadId_t) +SVC0_1 (ThreadGetStackSpace, uint32_t, osThreadId_t) SVC0_2 (ThreadSetPriority, osStatus_t, osThreadId_t, osPriority_t) SVC0_1 (ThreadGetPriority, osPriority_t, osThreadId_t) SVC0_0 (ThreadYield, osStatus_t) @@ -1600,7 +1628,7 @@ uint32_t isrRtxThreadFlagsSet (osThreadId_t thread_id, uint32_t flags) { /// Thread startup (Idle and Timer Thread). /// \return true - success, false - failure. bool_t osRtxThreadStartup (void) { - bool_t ret = TRUE; + bool_t ret = FALSE; // Create Idle Thread osRtxInfo.thread.idle = osRtxThreadId( @@ -1608,13 +1636,17 @@ bool_t osRtxThreadStartup (void) { ); // Create Timer Thread - if (osRtxConfig.timer_mq_mcnt != 0U) { - osRtxInfo.timer.thread = osRtxThreadId( - svcRtxThreadNew(osRtxTimerThread, NULL, osRtxConfig.timer_thread_attr) - ); - if (osRtxInfo.timer.thread == NULL) { - ret = FALSE; + if (osRtxConfig.timer_setup != NULL) { + if (osRtxConfig.timer_setup() == 0) { + osRtxInfo.timer.thread = osRtxThreadId( + svcRtxThreadNew(osRtxConfig.timer_thread, osRtxInfo.timer.mq, osRtxConfig.timer_thread_attr) + ); + if (osRtxInfo.timer.thread != NULL) { + ret = TRUE; + } } + } else { + ret = TRUE; } return ret; @@ -1628,7 +1660,7 @@ osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAtt osThreadId_t thread_id; EvrRtxThreadNew(func, argument, attr); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadError(NULL, (int32_t)osErrorISR); thread_id = NULL; } else { @@ -1641,7 +1673,7 @@ osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAtt const char *osThreadGetName (osThreadId_t thread_id) { const char *name; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadGetName(thread_id, NULL); name = NULL; } else { @@ -1654,7 +1686,7 @@ const char *osThreadGetName (osThreadId_t thread_id) { osThreadId_t osThreadGetId (void) { osThreadId_t thread_id; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { thread_id = svcRtxThreadGetId(); } else { thread_id = __svcThreadGetId(); @@ -1666,7 +1698,7 @@ osThreadId_t osThreadGetId (void) { osThreadState_t osThreadGetState (osThreadId_t thread_id) { osThreadState_t state; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadGetState(thread_id, osThreadError); state = osThreadError; } else { @@ -1679,7 +1711,7 @@ osThreadState_t osThreadGetState (osThreadId_t thread_id) { uint32_t osThreadGetStackSize (osThreadId_t thread_id) { uint32_t stack_size; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadGetStackSize(thread_id, 0U); stack_size = 0U; } else { @@ -1692,7 +1724,7 @@ uint32_t osThreadGetStackSize (osThreadId_t thread_id) { uint32_t osThreadGetStackSpace (osThreadId_t thread_id) { uint32_t stack_space; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadGetStackSpace(thread_id, 0U); stack_space = 0U; } else { @@ -1706,7 +1738,7 @@ osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority) { osStatus_t status; EvrRtxThreadSetPriority(thread_id, priority); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadError(thread_id, (int32_t)osErrorISR); status = osErrorISR; } else { @@ -1719,7 +1751,7 @@ osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority) { osPriority_t osThreadGetPriority (osThreadId_t thread_id) { osPriority_t priority; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadGetPriority(thread_id, osPriorityError); priority = osPriorityError; } else { @@ -1733,7 +1765,7 @@ osStatus_t osThreadYield (void) { osStatus_t status; EvrRtxThreadYield(); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadError(NULL, (int32_t)osErrorISR); status = osErrorISR; } else { @@ -1747,7 +1779,7 @@ osStatus_t osThreadSuspend (osThreadId_t thread_id) { osStatus_t status; EvrRtxThreadSuspend(thread_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadError(thread_id, (int32_t)osErrorISR); status = osErrorISR; } else { @@ -1761,7 +1793,7 @@ osStatus_t osThreadResume (osThreadId_t thread_id) { osStatus_t status; EvrRtxThreadResume(thread_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadError(thread_id, (int32_t)osErrorISR); status = osErrorISR; } else { @@ -1775,7 +1807,7 @@ osStatus_t osThreadDetach (osThreadId_t thread_id) { osStatus_t status; EvrRtxThreadDetach(thread_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadError(thread_id, (int32_t)osErrorISR); status = osErrorISR; } else { @@ -1789,7 +1821,7 @@ osStatus_t osThreadJoin (osThreadId_t thread_id) { osStatus_t status; EvrRtxThreadJoin(thread_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadError(thread_id, (int32_t)osErrorISR); status = osErrorISR; } else { @@ -1811,7 +1843,7 @@ osStatus_t osThreadTerminate (osThreadId_t thread_id) { osStatus_t status; EvrRtxThreadTerminate(thread_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadError(thread_id, (int32_t)osErrorISR); status = osErrorISR; } else { @@ -1824,7 +1856,7 @@ osStatus_t osThreadTerminate (osThreadId_t thread_id) { uint32_t osThreadGetCount (void) { uint32_t count; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadGetCount(0U); count = 0U; } else { @@ -1837,7 +1869,7 @@ uint32_t osThreadGetCount (void) { uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items) { uint32_t count; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadEnumerate(thread_array, array_items, 0U); count = 0U; } else { @@ -1851,7 +1883,7 @@ uint32_t osThreadFlagsSet (osThreadId_t thread_id, uint32_t flags) { uint32_t thread_flags; EvrRtxThreadFlagsSet(thread_id, flags); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { thread_flags = isrRtxThreadFlagsSet(thread_id, flags); } else { thread_flags = __svcThreadFlagsSet(thread_id, flags); @@ -1864,7 +1896,7 @@ uint32_t osThreadFlagsClear (uint32_t flags) { uint32_t thread_flags; EvrRtxThreadFlagsClear(flags); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadFlagsError(NULL, (int32_t)osErrorISR); thread_flags = (uint32_t)osErrorISR; } else { @@ -1877,7 +1909,7 @@ uint32_t osThreadFlagsClear (uint32_t flags) { uint32_t osThreadFlagsGet (void) { uint32_t thread_flags; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadFlagsGet(0U); thread_flags = 0U; } else { @@ -1891,7 +1923,7 @@ uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout) uint32_t thread_flags; EvrRtxThreadFlagsWait(flags, options, timeout); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxThreadFlagsError(NULL, (int32_t)osErrorISR); thread_flags = (uint32_t)osErrorISR; } else { diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_timer.c b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_timer.c index de3c98712ed..8cdca2944c3 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_timer.c +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_timer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * Copyright (c) 2013-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -27,7 +27,7 @@ // OS Runtime Object Memory Usage -#if ((defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))) +#ifdef RTX_OBJ_MEM_USAGE osRtxObjectMemUsage_t osRtxTimerMemUsage \ __attribute__((section(".data.os.timer.obj"))) = { 0U, 0U, 0U }; @@ -93,8 +93,9 @@ static void TimerUnlink (const os_timer_t *timer) { /// Timer Tick (called each SysTick). static void osRtxTimerTick (void) { - os_timer_t *timer; - osStatus_t status; + os_thread_t *thread_running; + os_timer_t *timer; + osStatus_t status; timer = osRtxInfo.timer.list; if (timer == NULL) { @@ -102,12 +103,21 @@ static void osRtxTimerTick (void) { return; } + thread_running = osRtxThreadGetRunning(); + timer->tick--; while ((timer != NULL) && (timer->tick == 0U)) { TimerUnlink(timer); status = osMessageQueuePut(osRtxInfo.timer.mq, &timer->finfo, 0U, 0U); if (status != osOK) { - (void)osRtxErrorNotify(osRtxErrorTimerQueueOverflow, timer); + const os_thread_t *thread = osRtxThreadGetRunning(); + osRtxThreadSetRunning(osRtxInfo.thread.run.next); + (void)osRtxKernelErrorNotify(osRtxErrorTimerQueueOverflow, timer); + if (osRtxThreadGetRunning() == NULL) { + if (thread_running == thread) { + thread_running = NULL; + } + } } if (timer->type == osRtxTimerPeriodic) { TimerInsert(timer, timer->load); @@ -116,22 +126,37 @@ static void osRtxTimerTick (void) { } timer = osRtxInfo.timer.list; } + + osRtxThreadSetRunning(thread_running); } -/// Timer Thread -__WEAK __NO_RETURN void osRtxTimerThread (void *argument) { - os_timer_finfo_t finfo; - osStatus_t status; - (void) argument; +/// Setup Timer Thread objects. +//lint -esym(714,osRtxTimerSetup) "Referenced from library configuration" +//lint -esym(759,osRtxTimerSetup) "Prototype in header" +//lint -esym(765,osRtxTimerSetup) "Global scope" +int32_t osRtxTimerSetup (void) { + int32_t ret = -1; - osRtxInfo.timer.mq = osRtxMessageQueueId( - osMessageQueueNew(osRtxConfig.timer_mq_mcnt, sizeof(os_timer_finfo_t), osRtxConfig.timer_mq_attr) - ); - osRtxInfo.timer.tick = osRtxTimerTick; + if (osRtxMessageQueueTimerSetup() == 0) { + osRtxInfo.timer.tick = osRtxTimerTick; + ret = 0; + } + + return ret; +} + +/// Timer Thread +//lint -esym(714,osRtxTimerThread) "Referenced from library configuration" +//lint -esym(759,osRtxTimerThread) "Prototype in header" +//lint -esym(765,osRtxTimerThread) "Global scope" +__NO_RETURN void osRtxTimerThread (void *argument) { + os_timer_finfo_t finfo; + osStatus_t status; + osMessageQueueId_t mq = (osMessageQueueId_t)argument; for (;;) { //lint -e{934} "Taking address of near auto variable" - status = osMessageQueueGet(osRtxInfo.timer.mq, &finfo, NULL, osWaitForever); + status = osMessageQueueGet(mq, &finfo, NULL, osWaitForever); if (status == osOK) { EvrRtxTimerCallback(finfo.func, finfo.arg); (finfo.func)(finfo.arg); @@ -188,7 +213,7 @@ static osTimerId_t svcRtxTimerNew (osTimerFunc_t func, osTimerType_t type, void //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5] timer = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_timer_t), 1U); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE if (timer != NULL) { uint32_t used; osRtxTimerMemUsage.cnt_alloc++; @@ -353,7 +378,7 @@ static osStatus_t svcRtxTimerDelete (osTimerId_t timer_id) { } else { (void)osRtxMemoryFree(osRtxInfo.mem.common, timer); } -#if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)) +#ifdef RTX_OBJ_MEM_USAGE osRtxTimerMemUsage.cnt_free++; #endif } @@ -381,7 +406,7 @@ osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, osTimerId_t timer_id; EvrRtxTimerNew(func, type, argument, attr); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxTimerError(NULL, (int32_t)osErrorISR); timer_id = NULL; } else { @@ -394,7 +419,7 @@ osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const char *osTimerGetName (osTimerId_t timer_id) { const char *name; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxTimerGetName(timer_id, NULL); name = NULL; } else { @@ -408,7 +433,7 @@ osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks) { osStatus_t status; EvrRtxTimerStart(timer_id, ticks); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxTimerError(timer_id, (int32_t)osErrorISR); status = osErrorISR; } else { @@ -422,7 +447,7 @@ osStatus_t osTimerStop (osTimerId_t timer_id) { osStatus_t status; EvrRtxTimerStop(timer_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxTimerError(timer_id, (int32_t)osErrorISR); status = osErrorISR; } else { @@ -435,7 +460,7 @@ osStatus_t osTimerStop (osTimerId_t timer_id) { uint32_t osTimerIsRunning (osTimerId_t timer_id) { uint32_t is_running; - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxTimerIsRunning(timer_id, 0U); is_running = 0U; } else { @@ -449,7 +474,7 @@ osStatus_t osTimerDelete (osTimerId_t timer_id) { osStatus_t status; EvrRtxTimerDelete(timer_id); - if (IsIrqMode() || IsIrqMasked()) { + if (IsException() || IsIrqMasked()) { EvrRtxTimerError(timer_id, (int32_t)osErrorISR); status = osErrorISR; } else { diff --git a/cmsis/CMSIS_5/CMSIS/RTOS2/Source/os_systick.c b/cmsis/CMSIS_5/CMSIS/RTOS2/Source/os_systick.c index b7c3e3e0b9a..3cce53c521c 100644 --- a/cmsis/CMSIS_5/CMSIS/RTOS2/Source/os_systick.c +++ b/cmsis/CMSIS_5/CMSIS/RTOS2/Source/os_systick.c @@ -1,11 +1,11 @@ /**************************************************************************//** * @file os_systick.c * @brief CMSIS OS Tick SysTick implementation - * @version V1.0.2 - * @date 6. March 2020 + * @version V1.0.3 + * @date 19. March 2021 ******************************************************************************/ /* - * Copyright (c) 2017-2020 ARM Limited. All rights reserved. + * Copyright (c) 2017-2021 ARM Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -34,7 +34,7 @@ #define SYSTICK_IRQ_PRIORITY 0xFFU #endif -static uint8_t PendST; +static uint8_t PendST __attribute__((section(".bss.os"))); // Setup OS Tick. __WEAK int32_t OS_Tick_Setup (uint32_t freq, IRQHandler_t handler) { @@ -127,7 +127,7 @@ __WEAK uint32_t OS_Tick_GetCount (void) { // Get OS Tick overflow status. __WEAK uint32_t OS_Tick_GetOverflow (void) { - return ((SysTick->CTRL >> 16) & 1U); + return ((SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) >> SCB_ICSR_PENDSTSET_Pos); } #endif // SysTick diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Include/cmsis_armcc.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Include/cmsis_armcc.h index cc11ada3539..0d9c37428cf 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Include/cmsis_armcc.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Include/cmsis_armcc.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file cmsis_armcc.h * @brief CMSIS compiler specific macros, functions, instructions - * @version V1.0.4 - * @date 30. July 2019 + * @version V1.0.5 + * @date 05. May 2021 ******************************************************************************/ /* - * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -296,6 +296,34 @@ __attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(in /* ########################### Core Function Access ########################### */ +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +/* intrinsic void __enable_irq(); */ + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +/* intrinsic void __disable_irq(void); */ + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + /** \brief Get FPSCR (Floating Point Status/Control) \return Floating Point Status/Control register value diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Include/cmsis_armclang.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Include/cmsis_armclang.h index 65a3b913467..1b0adb3b5be 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Include/cmsis_armclang.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Include/cmsis_armclang.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file cmsis_armclang.h * @brief CMSIS compiler specific macros, functions, instructions - * @version V1.2.0 - * @date 05. August 2019 + * @version V1.2.1 + * @date 05. May 2021 ******************************************************************************/ /* - * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -27,10 +27,6 @@ #pragma clang system_header /* treat file as system include file */ -#ifndef __ARM_COMPAT_H -#include /* Compatibility header for Arm Compiler 5 intrinsics */ -#endif - /* CMSIS compiler specific defines */ #ifndef __ASM #define __ASM __asm @@ -372,6 +368,50 @@ __STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) /* ########################### Core Function Access ########################### */ +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} +#endif + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} +#endif + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + /** \brief Get FPSCR \details Returns the current value of the Floating Point Status/Control register. @@ -401,7 +441,7 @@ __STATIC_FORCEINLINE uint32_t __get_CPSR(void) */ __STATIC_FORCEINLINE void __set_CPSR(uint32_t cpsr) { -__ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "cc", "memory"); + __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "cc", "memory"); } /** \brief Get Mode @@ -409,7 +449,7 @@ __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "cc", "memory"); */ __STATIC_FORCEINLINE uint32_t __get_mode(void) { - return (__get_CPSR() & 0x1FU); + return (__get_CPSR() & 0x1FU); } /** \brief Set Mode @@ -423,7 +463,7 @@ __STATIC_FORCEINLINE void __set_mode(uint32_t mode) /** \brief Get Stack Pointer \return Stack Pointer value */ -__STATIC_FORCEINLINE uint32_t __get_SP() +__STATIC_FORCEINLINE uint32_t __get_SP(void) { uint32_t result; __ASM volatile("MOV %0, sp" : "=r" (result) : : "memory"); @@ -441,7 +481,7 @@ __STATIC_FORCEINLINE void __set_SP(uint32_t stack) /** \brief Get USR/SYS Stack Pointer \return USR/SYS Stack Pointer value */ -__STATIC_FORCEINLINE uint32_t __get_SP_usr() +__STATIC_FORCEINLINE uint32_t __get_SP_usr(void) { uint32_t cpsr; uint32_t result; @@ -546,7 +586,7 @@ __STATIC_INLINE void __FPU_Enable(void) " VMOV D14,R2,R2 \n" " VMOV D15,R2,R2 \n" -#if __ARM_NEON == 1 +#if (defined(__ARM_NEON) && (__ARM_NEON == 1)) //Initialise D32 registers to 0 " VMOV D16,R2,R2 \n" " VMOV D17,R2,R2 \n" diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Include/cmsis_gcc.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Include/cmsis_gcc.h index 23d61205ddf..5f9a6aa29aa 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Include/cmsis_gcc.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Include/cmsis_gcc.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file cmsis_gcc.h * @brief CMSIS compiler specific macros, functions, instructions - * @version V1.3.0 - * @date 17. December 2019 + * @version V1.3.1 + * @date 05. May 2021 ******************************************************************************/ /* - * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -37,7 +37,6 @@ #endif /* CMSIS compiler specific defines */ - #ifndef __ASM #define __ASM __asm #endif @@ -57,7 +56,7 @@ #define __NO_RETURN __attribute__((__noreturn__)) #endif #ifndef CMSIS_DEPRECATED - #define CMSIS_DEPRECATED __attribute__((deprecated)) + #define CMSIS_DEPRECATED __attribute__((deprecated)) #endif #ifndef __USED #define __USED __attribute__((used)) @@ -433,10 +432,11 @@ __STATIC_FORCEINLINE int16_t __REVSH(int16_t value) \param [in] op2 Number of Bits to rotate \return Rotated value */ -__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) { op2 %= 32U; - if (op2 == 0U) { + if (op2 == 0U) + { return op1; } return (op1 >> op2) | (op1 << (32U - op2)); @@ -448,7 +448,7 @@ __STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) \param [in] value is ignored by the processor. If required, a debugger can use it to store additional information about the breakpoint. */ -#define __BKPT(value) __ASM volatile ("bkpt "#value) +#define __BKPT(value) __ASM volatile ("bkpt "#value) /** \brief Reverse bit order of value @@ -669,16 +669,36 @@ __STATIC_FORCEINLINE void __enable_irq(void) \details Disables IRQ interrupts by setting the I-bit in the CPSR. Can only be executed in Privileged modes. */ -__STATIC_FORCEINLINE void __disable_irq(void) +__STATIC_FORCEINLINE void __disable_irq(void) { __ASM volatile ("cpsid i" : : : "memory"); } +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + /** \brief Get FPSCR \details Returns the current value of the Floating Point Status/Control register. - \return Floating Point Status/Control register value -*/ + \return Floating Point Status/Control register value + */ __STATIC_FORCEINLINE uint32_t __get_FPSCR(void) { #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ @@ -702,8 +722,8 @@ __STATIC_FORCEINLINE uint32_t __get_FPSCR(void) /** \brief Set FPSCR \details Assigns the given value to the Floating Point Status/Control register. - \param [in] fpscr Floating Point Status/Control value to set -*/ + \param [in] fpscr Floating Point Status/Control value to set + */ __STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) { #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ @@ -736,7 +756,7 @@ __STATIC_FORCEINLINE uint32_t __get_CPSR(void) */ __STATIC_FORCEINLINE void __set_CPSR(uint32_t cpsr) { -__ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "cc", "memory"); + __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "cc", "memory"); } /** \brief Get Mode @@ -744,7 +764,7 @@ __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "cc", "memory"); */ __STATIC_FORCEINLINE uint32_t __get_mode(void) { - return (__get_CPSR() & 0x1FU); + return (__get_CPSR() & 0x1FU); } /** \brief Set Mode @@ -810,7 +830,7 @@ __STATIC_FORCEINLINE uint32_t __get_FPEXC(void) { #if (__FPU_PRESENT == 1) uint32_t result; - __ASM volatile("VMRS %0, fpexc" : "=r" (result) ); + __ASM volatile("VMRS %0, fpexc" : "=r" (result) : : "memory"); return(result); #else return(0); @@ -833,8 +853,8 @@ __STATIC_FORCEINLINE void __set_FPEXC(uint32_t fpexc) #define __get_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MRC p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : "=r" (Rt) : : "memory" ) #define __set_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" ) -#define __get_CP64(cp, op1, Rt, CRm) __ASM volatile("MRRC p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : "=r" (Rt) : : "memory" ) -#define __set_CP64(cp, op1, Rt, CRm) __ASM volatile("MCRR p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : : "r" (Rt) : "memory" ) +#define __get_CP64(cp, op1, Rt, CRm) __ASM volatile("MRRC p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : "=r" (Rt) : : "memory" ) +#define __set_CP64(cp, op1, Rt, CRm) __ASM volatile("MCRR p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : : "r" (Rt) : "memory" ) #include "cmsis_cp15.h" diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Source/irq_ctrl_gic.c b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Source/irq_ctrl_gic.c index e60467099e2..15588bffab9 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Source/irq_ctrl_gic.c +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_A/Source/irq_ctrl_gic.c @@ -1,11 +1,11 @@ /**************************************************************************//** * @file irq_ctrl_gic.c * @brief Interrupt controller handling implementation for GIC - * @version V1.1.0 - * @date 03. March 2020 + * @version V1.1.1 + * @date 29. March 2021 ******************************************************************************/ /* - * Copyright (c) 2017-2020 ARM Limited. All rights reserved. + * Copyright (c) 2017-2021 ARM Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -184,7 +184,7 @@ __WEAK int32_t IRQ_SetMode (IRQn_ID_t irqn, uint32_t mode) { if (val == IRQ_MODE_CPU_ALL) { cpu = 0xFFU; } else { - cpu = val >> IRQ_MODE_CPU_Pos; + cpu = (uint8_t)(val >> IRQ_MODE_CPU_Pos); } // Apply configuration if no mode error diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cachel1_armv7.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cachel1_armv7.h index d2c3e2291fd..abebc95f946 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cachel1_armv7.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cachel1_armv7.h @@ -1,11 +1,11 @@ /****************************************************************************** * @file cachel1_armv7.h * @brief CMSIS Level 1 Cache API for Armv7-M and later - * @version V1.0.0 - * @date 03. March 2020 + * @version V1.0.1 + * @date 19. April 2021 ******************************************************************************/ /* - * Copyright (c) 2020 Arm Limited. All rights reserved. + * Copyright (c) 2020-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -48,7 +48,7 @@ #ifndef __SCB_ICACHE_LINE_SIZE #define __SCB_ICACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */ -#endif +#endif /** \brief Enable I-Cache @@ -112,7 +112,7 @@ __STATIC_FORCEINLINE void SCB_InvalidateICache (void) \param[in] addr address \param[in] isize size of memory block (in number of bytes) */ -__STATIC_FORCEINLINE void SCB_InvalidateICache_by_Addr (void *addr, int32_t isize) +__STATIC_FORCEINLINE void SCB_InvalidateICache_by_Addr (volatile void *addr, int32_t isize) { #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) if ( isize > 0 ) { @@ -325,13 +325,13 @@ __STATIC_FORCEINLINE void SCB_CleanInvalidateDCache (void) \param[in] addr address \param[in] dsize size of memory block (in number of bytes) */ -__STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr (void *addr, int32_t dsize) +__STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr (volatile void *addr, int32_t dsize) { #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) - if ( dsize > 0 ) { + if ( dsize > 0 ) { int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; - + __DSB(); do { @@ -355,13 +355,13 @@ __STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr (void *addr, int32_t dsiz \param[in] addr address \param[in] dsize size of memory block (in number of bytes) */ -__STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize) +__STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr (volatile void *addr, int32_t dsize) { #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) - if ( dsize > 0 ) { + if ( dsize > 0 ) { int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; - + __DSB(); do { @@ -385,13 +385,13 @@ __STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize \param[in] addr address (aligned to 32-byte boundary) \param[in] dsize size of memory block (in number of bytes) */ -__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) +__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache_by_Addr (volatile void *addr, int32_t dsize) { #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) - if ( dsize > 0 ) { + if ( dsize > 0 ) { int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; - + __DSB(); do { diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armcc.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armcc.h index 237ff6ec3ea..a955d471391 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armcc.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armcc.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file cmsis_armcc.h * @brief CMSIS compiler ARMCC (Arm Compiler 5) header file - * @version V5.2.1 - * @date 26. March 2020 + * @version V5.3.2 + * @date 27. May 2021 ******************************************************************************/ /* - * Copyright (c) 2009-2020 Arm Limited. All rights reserved. + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -63,9 +63,9 @@ #ifndef __STATIC_INLINE #define __STATIC_INLINE static __inline #endif -#ifndef __STATIC_FORCEINLINE +#ifndef __STATIC_FORCEINLINE #define __STATIC_FORCEINLINE static __forceinline -#endif +#endif #ifndef __NO_RETURN #define __NO_RETURN __declspec(noreturn) #endif @@ -129,280 +129,7 @@ #ifndef __VECTOR_TABLE_ATTRIBUTE #define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET"))) -#endif - -/* ########################### Core Function Access ########################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions - @{ - */ - -/** - \brief Enable IRQ Interrupts - \details Enables IRQ interrupts by clearing the I-bit in the CPSR. - Can only be executed in Privileged modes. - */ -/* intrinsic void __enable_irq(); */ - - -/** - \brief Disable IRQ Interrupts - \details Disables IRQ interrupts by setting the I-bit in the CPSR. - Can only be executed in Privileged modes. - */ -/* intrinsic void __disable_irq(); */ - -/** - \brief Get Control Register - \details Returns the content of the Control Register. - \return Control Register value - */ -__STATIC_INLINE uint32_t __get_CONTROL(void) -{ - register uint32_t __regControl __ASM("control"); - return(__regControl); -} - - -/** - \brief Set Control Register - \details Writes the given value to the Control Register. - \param [in] control Control Register value to set - */ -__STATIC_INLINE void __set_CONTROL(uint32_t control) -{ - register uint32_t __regControl __ASM("control"); - __regControl = control; -} - - -/** - \brief Get IPSR Register - \details Returns the content of the IPSR Register. - \return IPSR Register value - */ -__STATIC_INLINE uint32_t __get_IPSR(void) -{ - register uint32_t __regIPSR __ASM("ipsr"); - return(__regIPSR); -} - - -/** - \brief Get APSR Register - \details Returns the content of the APSR Register. - \return APSR Register value - */ -__STATIC_INLINE uint32_t __get_APSR(void) -{ - register uint32_t __regAPSR __ASM("apsr"); - return(__regAPSR); -} - - -/** - \brief Get xPSR Register - \details Returns the content of the xPSR Register. - \return xPSR Register value - */ -__STATIC_INLINE uint32_t __get_xPSR(void) -{ - register uint32_t __regXPSR __ASM("xpsr"); - return(__regXPSR); -} - - -/** - \brief Get Process Stack Pointer - \details Returns the current value of the Process Stack Pointer (PSP). - \return PSP Register value - */ -__STATIC_INLINE uint32_t __get_PSP(void) -{ - register uint32_t __regProcessStackPointer __ASM("psp"); - return(__regProcessStackPointer); -} - - -/** - \brief Set Process Stack Pointer - \details Assigns the given value to the Process Stack Pointer (PSP). - \param [in] topOfProcStack Process Stack Pointer value to set - */ -__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) -{ - register uint32_t __regProcessStackPointer __ASM("psp"); - __regProcessStackPointer = topOfProcStack; -} - - -/** - \brief Get Main Stack Pointer - \details Returns the current value of the Main Stack Pointer (MSP). - \return MSP Register value - */ -__STATIC_INLINE uint32_t __get_MSP(void) -{ - register uint32_t __regMainStackPointer __ASM("msp"); - return(__regMainStackPointer); -} - - -/** - \brief Set Main Stack Pointer - \details Assigns the given value to the Main Stack Pointer (MSP). - \param [in] topOfMainStack Main Stack Pointer value to set - */ -__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) -{ - register uint32_t __regMainStackPointer __ASM("msp"); - __regMainStackPointer = topOfMainStack; -} - - -/** - \brief Get Priority Mask - \details Returns the current state of the priority mask bit from the Priority Mask Register. - \return Priority Mask value - */ -__STATIC_INLINE uint32_t __get_PRIMASK(void) -{ - register uint32_t __regPriMask __ASM("primask"); - return(__regPriMask); -} - - -/** - \brief Set Priority Mask - \details Assigns the given value to the Priority Mask Register. - \param [in] priMask Priority Mask - */ -__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) -{ - register uint32_t __regPriMask __ASM("primask"); - __regPriMask = (priMask); -} - - -#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) - -/** - \brief Enable FIQ - \details Enables FIQ interrupts by clearing the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -#define __enable_fault_irq __enable_fiq - - -/** - \brief Disable FIQ - \details Disables FIQ interrupts by setting the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -#define __disable_fault_irq __disable_fiq - - -/** - \brief Get Base Priority - \details Returns the current value of the Base Priority register. - \return Base Priority register value - */ -__STATIC_INLINE uint32_t __get_BASEPRI(void) -{ - register uint32_t __regBasePri __ASM("basepri"); - return(__regBasePri); -} - - -/** - \brief Set Base Priority - \details Assigns the given value to the Base Priority register. - \param [in] basePri Base Priority value to set - */ -__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) -{ - register uint32_t __regBasePri __ASM("basepri"); - __regBasePri = (basePri & 0xFFU); -} - - -/** - \brief Set Base Priority with condition - \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, - or the new value increases the BASEPRI priority level. - \param [in] basePri Base Priority value to set - */ -__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) -{ - register uint32_t __regBasePriMax __ASM("basepri_max"); - __regBasePriMax = (basePri & 0xFFU); -} - - -/** - \brief Get Fault Mask - \details Returns the current value of the Fault Mask register. - \return Fault Mask register value - */ -__STATIC_INLINE uint32_t __get_FAULTMASK(void) -{ - register uint32_t __regFaultMask __ASM("faultmask"); - return(__regFaultMask); -} - - -/** - \brief Set Fault Mask - \details Assigns the given value to the Fault Mask register. - \param [in] faultMask Fault Mask value to set - */ -__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) -{ - register uint32_t __regFaultMask __ASM("faultmask"); - __regFaultMask = (faultMask & (uint32_t)1U); -} - -#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ - - -/** - \brief Get FPSCR - \details Returns the current value of the Floating Point Status/Control register. - \return Floating Point Status/Control register value - */ -__STATIC_INLINE uint32_t __get_FPSCR(void) -{ -#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ - (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) - register uint32_t __regfpscr __ASM("fpscr"); - return(__regfpscr); -#else - return(0U); -#endif -} - - -/** - \brief Set FPSCR - \details Assigns the given value to the Floating Point Status/Control register. - \param [in] fpscr Floating Point Status/Control value to set - */ -__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) -{ -#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ - (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) - register uint32_t __regfpscr __ASM("fpscr"); - __regfpscr = (fpscr); -#else - (void)fpscr; -#endif -} - - -/*@} end of CMSIS_Core_RegAccFunctions */ - +#endif /* ########################## Core Instruction Access ######################### */ /** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface @@ -461,7 +188,7 @@ __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) */ #define __DMB() __dmb(0xF) - + /** \brief Reverse byte order (32 bit) \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. @@ -616,187 +343,461 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) /** - \brief STR Exclusive (16 bit) - \details Executes a exclusive STR instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXH(value, ptr) __strex(value, ptr) +#else + #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXW(value, ptr) __strex(value, ptr) +#else + #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) +{ + rrx r0, r0 + bx lr +} +#endif + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRBT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRHT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRT(value, ptr) __strt(value, ptr) + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +/* intrinsic void __enable_irq(); */ + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +/* intrinsic void __disable_irq(); */ + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; + __ISB(); +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __STREXH(value, ptr) __strex(value, ptr) -#else - #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") -#endif +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} /** - \brief STR Exclusive (32 bit) - \details Executes a exclusive STR instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __STREXW(value, ptr) __strex(value, ptr) -#else - #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") -#endif +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} /** - \brief Remove the exclusive lock - \details Removes the exclusive lock which is created by LDREX. + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value */ -#define __CLREX __clrex +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} /** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set */ -#define __SSAT __ssat +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} /** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value */ -#define __USAT __usat +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} /** - \brief Rotate Right with Extend (32 bit) - \details Moves each bit of a bitstring right by one bit. - The carry input is shifted in at the left end of the bitstring. - \param [in] value Value to rotate - \return Rotated value + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask */ -#ifndef __NO_EMBEDDED_ASM -__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) { - rrx r0, r0 - bx lr + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); } -#endif +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + /** - \brief LDRT Unprivileged (8 bit) - \details Executes a Unprivileged LDRT instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. */ -#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) +#define __enable_fault_irq __enable_fiq /** - \brief LDRT Unprivileged (16 bit) - \details Executes a Unprivileged LDRT instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. */ -#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) +#define __disable_fault_irq __disable_fiq /** - \brief LDRT Unprivileged (32 bit) - \details Executes a Unprivileged LDRT instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value */ -#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} /** - \brief STRT Unprivileged (8 bit) - \details Executes a Unprivileged STRT instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set */ -#define __STRBT(value, ptr) __strt(value, ptr) +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xFFU); +} /** - \brief STRT Unprivileged (16 bit) - \details Executes a Unprivileged STRT instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set */ -#define __STRHT(value, ptr) __strt(value, ptr) +__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + register uint32_t __regBasePriMax __ASM("basepri_max"); + __regBasePriMax = (basePri & 0xFFU); +} /** - \brief STRT Unprivileged (32 bit) - \details Executes a Unprivileged STRT instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value */ -#define __STRT(value, ptr) __strt(value, ptr) +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} -#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1U); +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + /** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value */ -__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) +__STATIC_INLINE uint32_t __get_FPSCR(void) { - if ((sat >= 1U) && (sat <= 32U)) - { - const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); - const int32_t min = -1 - max ; - if (val > max) - { - return max; - } - else if (val < min) - { - return min; - } - } - return val; +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0U); +#endif } + /** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) { - if (sat <= 31U) - { - const uint32_t max = ((1U << sat) - 1U); - if (val > (int32_t)max) - { - return max; - } - else if (val < 0) - { - return 0U; - } - } - return (uint32_t)val; +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#else + (void)fpscr; +#endif } -#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ -/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ +/*@} end of CMSIS_Core_RegAccFunctions */ /* ################### Compiler specific Intrinsics ########################### */ @@ -878,6 +879,8 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint #define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + #endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ /*@} end of group CMSIS_SIMD_intrinsics */ diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armclang.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armclang.h index 90de9dbf8f8..69114177477 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armclang.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armclang.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file cmsis_armclang.h * @brief CMSIS compiler armclang (Arm Compiler 6) header file - * @version V5.3.1 - * @date 26. March 2020 + * @version V5.4.3 + * @date 27. May 2021 ******************************************************************************/ /* - * Copyright (c) 2009-2020 Arm Limited. All rights reserved. + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -29,10 +29,6 @@ #pragma clang system_header /* treat file as system include file */ -#ifndef __ARM_COMPAT_H -#include /* Compatibility header for Arm Compiler 5 intrinsics */ -#endif - /* CMSIS compiler specific defines */ #ifndef __ASM #define __ASM __asm @@ -136,451 +132,438 @@ #define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET"))) #endif -/* ########################### Core Function Access ########################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL Image$$STACKSEAL$$ZI$$Base +#endif + +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif + + +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; +} +#endif + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions @{ - */ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif /** - \brief Enable IRQ Interrupts - \details Enables IRQ interrupts by clearing the I-bit in the CPSR. - Can only be executed in Privileged modes. + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. */ -/* intrinsic void __enable_irq(); see arm_compat.h */ - +#define __NOP __builtin_arm_nop /** - \brief Disable IRQ Interrupts - \details Disables IRQ interrupts by setting the I-bit in the CPSR. - Can only be executed in Privileged modes. + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. */ -/* intrinsic void __disable_irq(); see arm_compat.h */ +#define __WFI __builtin_arm_wfi /** - \brief Get Control Register - \details Returns the content of the Control Register. - \return Control Register value + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. */ -__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, control" : "=r" (result) ); - return(result); -} +#define __WFE __builtin_arm_wfe -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Control Register (non-secure) - \details Returns the content of the non-secure Control Register when in secure mode. - \return non-secure Control Register value + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. */ -__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) -{ - uint32_t result; +#define __SEV __builtin_arm_sev - __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); - return(result); -} -#endif +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF) /** - \brief Set Control Register - \details Writes the given value to the Control Register. - \param [in] control Control Register value to set + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. */ -__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) -{ - __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); -} +#define __DSB() __builtin_arm_dsb(0xF) -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Control Register (non-secure) - \details Writes the given value to the non-secure Control Register when in secure state. - \param [in] control Control Register value to set + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. */ -__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) -{ - __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); -} -#endif +#define __DMB() __builtin_arm_dmb(0xF) /** - \brief Get IPSR Register - \details Returns the content of the IPSR Register. - \return IPSR Register value + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value */ -__STATIC_FORCEINLINE uint32_t __get_IPSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); - return(result); -} +#define __REV(value) __builtin_bswap32(value) /** - \brief Get APSR Register - \details Returns the content of the APSR Register. - \return APSR Register value + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value */ -__STATIC_FORCEINLINE uint32_t __get_APSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, apsr" : "=r" (result) ); - return(result); -} +#define __REV16(value) __ROR(__REV(value), 16) /** - \brief Get xPSR Register - \details Returns the content of the xPSR Register. - \return xPSR Register value + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value */ -__STATIC_FORCEINLINE uint32_t __get_xPSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); - return(result); -} +#define __REVSH(value) (int16_t)__builtin_bswap16(value) /** - \brief Get Process Stack Pointer - \details Returns the current value of the Process Stack Pointer (PSP). - \return PSP Register value + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value */ -__STATIC_FORCEINLINE uint32_t __get_PSP(void) +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) { - uint32_t result; - - __ASM volatile ("MRS %0, psp" : "=r" (result) ); - return(result); + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Process Stack Pointer (non-secure) - \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. - \return PSP Register value + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. */ -__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) -{ - uint32_t result; +#define __BKPT(value) __ASM volatile ("bkpt "#value) - __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); - return(result); -} -#endif +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __builtin_arm_rbit /** - \brief Set Process Stack Pointer - \details Assigns the given value to the Process Stack Pointer (PSP). - \param [in] topOfProcStack Process Stack Pointer value to set + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value */ -__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) { - __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + /** - \brief Set Process Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. - \param [in] topOfProcStack Process Stack Pointer value to set + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) */ -__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) -{ - __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); -} -#endif +#define __LDREXB (uint8_t)__builtin_arm_ldrex /** - \brief Get Main Stack Pointer - \details Returns the current value of the Main Stack Pointer (MSP). - \return MSP Register value + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __get_MSP(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, msp" : "=r" (result) ); - return(result); -} +#define __LDREXH (uint16_t)__builtin_arm_ldrex -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Main Stack Pointer (non-secure) - \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. - \return MSP Register value + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) -{ - uint32_t result; +#define __LDREXW (uint32_t)__builtin_arm_ldrex - __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); - return(result); -} -#endif + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex /** - \brief Set Main Stack Pointer - \details Assigns the given value to the Main Stack Pointer (MSP). - \param [in] topOfMainStack Main Stack Pointer value to set + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) -{ - __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); -} +#define __STREXH (uint32_t)__builtin_arm_strex -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Main Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. - \param [in] topOfMainStack Main Stack Pointer value to set + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) -{ - __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); -} -#endif +#define __STREXW (uint32_t)__builtin_arm_strex -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Stack Pointer (non-secure) - \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. - \return SP Register value + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. */ -__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) -{ - uint32_t result; +#define __CLREX __builtin_arm_clrex + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ - __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); - return(result); -} +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) /** - \brief Set Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. - \param [in] topOfStack Stack Pointer value to set + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value */ -__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) -{ - __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); -} -#endif +#define __SSAT __builtin_arm_ssat /** - \brief Get Priority Mask - \details Returns the current state of the priority mask bit from the Priority Mask Register. - \return Priority Mask value + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value */ -__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, primask" : "=r" (result) ); - return(result); -} +#define __USAT __builtin_arm_usat -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Priority Mask (non-secure) - \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. - \return Priority Mask value + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value */ -__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) { uint32_t result; - __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); return(result); } -#endif /** - \brief Set Priority Mask - \details Assigns the given value to the Priority Mask Register. - \param [in] priMask Priority Mask + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) */ -__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) { - __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); -} - + uint32_t result; -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Set Priority Mask (non-secure) - \details Assigns the given value to the non-secure Priority Mask Register when in secure state. - \param [in] priMask Priority Mask - */ -__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) -{ - __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ } -#endif - - -#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) -/** - \brief Enable FIQ - \details Enables FIQ interrupts by clearing the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -#define __enable_fault_irq __enable_fiq /* see arm_compat.h */ - - -/** - \brief Disable FIQ - \details Disables FIQ interrupts by setting the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -#define __disable_fault_irq __disable_fiq /* see arm_compat.h */ /** - \brief Get Base Priority - \details Returns the current value of the Base Priority register. - \return Base Priority register value + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) { uint32_t result; - __ASM volatile ("MRS %0, basepri" : "=r" (result) ); - return(result); + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Base Priority (non-secure) - \details Returns the current value of the non-secure Base Priority register when in secure state. - \return Base Priority register value + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) { uint32_t result; - __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); return(result); } -#endif /** - \brief Set Base Priority - \details Assigns the given value to the Base Priority register. - \param [in] basePri Base Priority value to set + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) { - __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Base Priority (non-secure) - \details Assigns the given value to the non-secure Base Priority register when in secure state. - \param [in] basePri Base Priority value to set + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) { - __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } -#endif /** - \brief Set Base Priority with condition - \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, - or the new value increases the BASEPRI priority level. - \param [in] basePri Base Priority value to set + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) { - __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); } +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ /** - \brief Get Fault Mask - \details Returns the current value of the Fault Mask register. - \return Fault Mask register value + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value */ -__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) { - uint32_t result; - - __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); - return(result); + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; } - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Get Fault Mask (non-secure) - \details Returns the current value of the non-secure Fault Mask register when in secure state. - \return Fault Mask register value - */ -__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Fault Mask - \details Assigns the given value to the Fault Mask register. - \param [in] faultMask Fault Mask value to set - */ -__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) -{ - __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Fault Mask (non-secure) - \details Assigns the given value to the non-secure Fault Mask register when in secure state. - \param [in] faultMask Fault Mask value to set + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value */ -__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) { - __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; } -#endif #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ @@ -593,631 +576,615 @@ __STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) /** - \brief Get Process Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always in non-secure - mode. - - \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). - \return PSPLIM Register value + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) { -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure PSPLIM is RAZ/WI - return 0U; -#else uint32_t result; - __ASM volatile ("MRS %0, psplim" : "=r" (result) ); - return result; -#endif + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint8_t) result); } -#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Get Process Stack Pointer Limit (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always in non-secure - mode. - \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. - \return PSPLIM Register value +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) { -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) - // without main extensions, the non-secure PSPLIM is RAZ/WI - return 0U; -#else uint32_t result; - __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); - return result; -#endif + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint16_t) result); } -#endif /** - \brief Set Process Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored in non-secure - mode. - - \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). - \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) */ -__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) { -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure PSPLIM is RAZ/WI - (void)ProcStackPtrLimit; -#else - __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); -#endif + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return(result); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Process Stack Pointer (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored in non-secure - mode. - - \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. - \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) { -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) - // without main extensions, the non-secure PSPLIM is RAZ/WI - (void)ProcStackPtrLimit; -#else - __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); -#endif + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); } -#endif /** - \brief Get Main Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always. - - \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). - \return MSPLIM Register value + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) { -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure MSPLIM is RAZ/WI - return 0U; -#else - uint32_t result; - __ASM volatile ("MRS %0, msplim" : "=r" (result) ); - return result; -#endif + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Main Stack Pointer Limit (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always. - - \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. - \return MSPLIM Register value + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) { -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) - // without main extensions, the non-secure MSPLIM is RAZ/WI - return 0U; -#else - uint32_t result; - __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); - return result; -#endif + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); } -#endif /** - \brief Set Main Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored. + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex - \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). - \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) */ -__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) -{ -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure MSPLIM is RAZ/WI - (void)MainStackPtrLimit; -#else - __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); -#endif -} +#define __LDAEXH (uint16_t)__builtin_arm_ldaex -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Main Stack Pointer Limit (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored. + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex - \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. - \param [in] MainStackPtrLimit Main Stack Pointer value to set + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) -{ -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) - // without main extensions, the non-secure MSPLIM is RAZ/WI - (void)MainStackPtrLimit; -#else - __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); -#endif -} -#endif +#define __STLEXB (uint32_t)__builtin_arm_stlex -#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ /** - \brief Get FPSCR - \details Returns the current value of the Floating Point Status/Control register. - \return Floating Point Status/Control register value + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ - (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) -#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr -#else -#define __get_FPSCR() ((uint32_t)0U) -#endif +#define __STLEXH (uint32_t)__builtin_arm_stlex + /** - \brief Set FPSCR - \details Assigns the given value to the Floating Point Status/Control register. - \param [in] fpscr Floating Point Status/Control value to set + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ - (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) -#define __set_FPSCR __builtin_arm_set_fpscr -#else -#define __set_FPSCR(x) ((void)(x)) -#endif +#define __STLEX (uint32_t)__builtin_arm_stlex +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ -/*@} end of CMSIS_Core_RegAccFunctions */ +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ -/* ########################## Core Instruction Access ######################### */ -/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface - Access to dedicated instructions +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions @{ -*/ + */ -/* Define macros for porting to both thumb1 and thumb2. - * For thumb1, use low register (r0-r7), specified by constraint "l" - * Otherwise, use general registers, specified by constraint "r" */ -#if defined (__thumb__) && !defined (__thumb2__) -#define __CMSIS_GCC_OUT_REG(r) "=l" (r) -#define __CMSIS_GCC_RW_REG(r) "+l" (r) -#define __CMSIS_GCC_USE_REG(r) "l" (r) -#else -#define __CMSIS_GCC_OUT_REG(r) "=r" (r) -#define __CMSIS_GCC_RW_REG(r) "+r" (r) -#define __CMSIS_GCC_USE_REG(r) "r" (r) +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} +#endif + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} #endif + /** - \brief No Operation - \details No Operation does nothing. This instruction can be used for code alignment purposes. + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value */ -#define __NOP __builtin_arm_nop +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Wait For Interrupt - \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value */ -#define __WFI __builtin_arm_wfi +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif /** - \brief Wait For Event - \details Wait For Event is a hint instruction that permits the processor to enter - a low-power state until one of a number of events occurs. + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set */ -#define __WFE __builtin_arm_wfe +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); + __ISB(); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Send Event - \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set */ -#define __SEV __builtin_arm_sev +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); + __ISB(); +} +#endif /** - \brief Instruction Synchronization Barrier - \details Instruction Synchronization Barrier flushes the pipeline in the processor, - so that all instructions following the ISB are fetched from cache or memory, - after the instruction has been completed. + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value */ -#define __ISB() __builtin_arm_isb(0xF) +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + /** - \brief Data Synchronization Barrier - \details Acts as a special kind of Data Memory Barrier. - It completes when all explicit memory accesses before this instruction complete. + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value */ -#define __DSB() __builtin_arm_dsb(0xF) +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} /** - \brief Data Memory Barrier - \details Ensures the apparent order of the explicit memory operations before - and after the instruction, without ensuring their completion. + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value */ -#define __DMB() __builtin_arm_dmb(0xF) +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} /** - \brief Reverse byte order (32 bit) - \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. - \param [in] value Value to reverse - \return Reversed value + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value */ -#define __REV(value) __builtin_bswap32(value) +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Reverse byte order (16 bit) - \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. - \param [in] value Value to reverse - \return Reversed value + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value */ -#define __REV16(value) __ROR(__REV(value), 16) +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif /** - \brief Reverse byte order (16 bit) - \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. - \param [in] value Value to reverse - \return Reversed value + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set */ -#define __REVSH(value) (int16_t)__builtin_bswap16(value) +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Rotate Right in unsigned value (32 bit) - \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - \param [in] op1 Value to rotate - \param [in] op2 Number of Bits to rotate - \return Rotated value + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set */ -__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) { - op2 %= 32U; - if (op2 == 0U) - { - return op1; - } - return (op1 >> op2) | (op1 << (32U - op2)); + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); } +#endif /** - \brief Breakpoint - \details Causes the processor to enter Debug state. - Debug tools can use this to investigate system state when the instruction at a particular address is reached. - \param [in] value is ignored by the processor. - If required, a debugger can use it to store additional information about the breakpoint. + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value */ -#define __BKPT(value) __ASM volatile ("bkpt "#value) +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Reverse bit order of value - \details Reverses the bit order of the given value. - \param [in] value Value to reverse - \return Reversed value + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value */ -#define __RBIT __builtin_arm_rbit +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + /** - \brief Count leading zeros - \details Counts the number of leading zeros of a data value. - \param [in] value Value to count the leading zeros - \return number of leading zeros in value + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set */ -__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) { - /* Even though __builtin_clz produces a CLZ instruction on ARM, formally - __builtin_clz(0) is undefined behaviour, so handle this case specially. - This guarantees ARM-compatible results if happening to compile on a non-ARM - target, and ensures the compiler doesn't decide to activate any - optimisations using the logic "value was passed to __builtin_clz, so it - is non-zero". - ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a - single CLZ instruction. - */ - if (value == 0U) - { - return 32U; - } - return __builtin_clz(value); + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); } -#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) - +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief LDR Exclusive (8 bit) - \details Executes a exclusive LDR instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set */ -#define __LDREXB (uint8_t)__builtin_arm_ldrex +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief LDR Exclusive (16 bit) - \details Executes a exclusive LDR instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value */ -#define __LDREXH (uint16_t)__builtin_arm_ldrex +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} /** - \brief LDR Exclusive (32 bit) - \details Executes a exclusive LDR instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set */ -#define __LDREXW (uint32_t)__builtin_arm_ldrex +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif /** - \brief STR Exclusive (8 bit) - \details Executes a exclusive STR instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value */ -#define __STREXB (uint32_t)__builtin_arm_strex +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief STR Exclusive (16 bit) - \details Executes a exclusive STR instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value */ -#define __STREXH (uint32_t)__builtin_arm_strex +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif /** - \brief STR Exclusive (32 bit) - \details Executes a exclusive STR instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask */ -#define __STREXW (uint32_t)__builtin_arm_strex +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Remove the exclusive lock - \details Removes the exclusive lock which is created by LDREX. + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask */ -#define __CLREX __builtin_arm_clrex - -#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) - /** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. */ -#define __SSAT __builtin_arm_ssat +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} /** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. */ -#define __USAT __builtin_arm_usat +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} /** - \brief Rotate Right with Extend (32 bit) - \details Moves each bit of a bitstring right by one bit. - The carry input is shifted in at the left end of the bitstring. - \param [in] value Value to rotate - \return Rotated value + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value */ -__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) { uint32_t result; - __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); return(result); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief LDRT Unprivileged (8 bit) - \details Executes a Unprivileged LDRT instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value */ -__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) { uint32_t result; - __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint8_t) result); /* Add explicit type cast here */ + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); } +#endif /** - \brief LDRT Unprivileged (16 bit) - \details Executes a Unprivileged LDRT instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set */ -__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) { - uint32_t result; - - __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint16_t) result); /* Add explicit type cast here */ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief LDRT Unprivileged (32 bit) - \details Executes a Unprivileged LDRT instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set */ -__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) { - uint32_t result; - - __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); - return(result); + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); } +#endif /** - \brief STRT Unprivileged (8 bit) - \details Executes a Unprivileged STRT instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set */ -__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) { - __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); } /** - \brief STRT Unprivileged (16 bit) - \details Executes a Unprivileged STRT instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value */ -__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) { - __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief STRT Unprivileged (32 bit) - \details Executes a Unprivileged STRT instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value */ -__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) { - __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); } +#endif -#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ /** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set */ -__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) { - if ((sat >= 1U) && (sat <= 32U)) - { - const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); - const int32_t min = -1 - max ; - if (val > max) - { - return max; - } - else if (val < min) - { - return min; - } - } - return val; + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); } + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value - */ -__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) -{ - if (sat <= 31U) - { - const uint32_t max = ((1U << sat) - 1U); - if (val > (int32_t)max) - { - return max; - } - else if (val < 0) - { - return 0U; - } - } - return (uint32_t)val; + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); } +#endif #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ @@ -1228,152 +1195,219 @@ __STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) - + /** - \brief Load-Acquire (8 bit) - \details Executes a LDAB instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value */ -__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) { +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else uint32_t result; - - __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return ((uint8_t) result); + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif } - +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Load-Acquire (16 bit) - \details Executes a LDAH instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value */ -__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) { +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else uint32_t result; - - __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return ((uint16_t) result); + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif } +#endif /** - \brief Load-Acquire (32 bit) - \details Executes a LDA instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set */ -__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) { - uint32_t result; - - __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return(result); +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Store-Release (8 bit) - \details Executes a STLB instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set */ -__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) { - __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif } +#endif /** - \brief Store-Release (16 bit) - \details Executes a STLH instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value */ -__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) { - __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Store-Release (32 bit) - \details Executes a STL instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value */ -__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) { - __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif } +#endif /** - \brief Load-Acquire Exclusive (8 bit) - \details Executes a LDAB exclusive instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -#define __LDAEXB (uint8_t)__builtin_arm_ldaex - + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. -/** - \brief Load-Acquire Exclusive (16 bit) - \details Executes a LDAH exclusive instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set */ -#define __LDAEXH (uint16_t)__builtin_arm_ldaex +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Load-Acquire Exclusive (32 bit) - \details Executes a LDA exclusive instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -#define __LDAEX (uint32_t)__builtin_arm_ldaex - + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. -/** - \brief Store-Release Exclusive (8 bit) - \details Executes a STLB exclusive instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set */ -#define __STLEXB (uint32_t)__builtin_arm_stlex +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ /** - \brief Store-Release Exclusive (16 bit) - \details Executes a STLH exclusive instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value */ -#define __STLEXH (uint32_t)__builtin_arm_stlex - +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr +#else +#define __get_FPSCR() ((uint32_t)0U) +#endif /** - \brief Store-Release Exclusive (32 bit) - \details Executes a STL exclusive instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set */ -#define __STLEX (uint32_t)__builtin_arm_stlex +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __set_FPSCR __builtin_arm_set_fpscr +#else +#define __set_FPSCR(x) ((void)(x)) +#endif -#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ -/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ +/*@} end of CMSIS_Core_RegAccFunctions */ /* ################### Compiler specific Intrinsics ########################### */ @@ -1452,6 +1486,8 @@ __STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) #define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + __STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) { int32_t result; diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armclang_ltm.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armclang_ltm.h index 0e5c7349d3e..1e255d5907f 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armclang_ltm.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armclang_ltm.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file cmsis_armclang_ltm.h * @brief CMSIS compiler armclang (Arm Compiler 6) header file - * @version V1.3.0 - * @date 26. March 2020 + * @version V1.5.3 + * @date 27. May 2021 ******************************************************************************/ /* - * Copyright (c) 2018-2020 Arm Limited. All rights reserved. + * Copyright (c) 2018-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -29,10 +29,6 @@ #pragma clang system_header /* treat file as system include file */ -#ifndef __ARM_COMPAT_H -#include /* Compatibility header for Arm Compiler 5 intrinsics */ -#endif - /* CMSIS compiler specific defines */ #ifndef __ASM #define __ASM __asm @@ -136,1070 +132,1047 @@ #define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET"))) #endif +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL Image$$STACKSEAL$$ZI$$Base +#endif -/* ########################### Core Function Access ########################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif + + +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; +} +#endif + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. */ +#define __NOP __builtin_arm_nop /** - \brief Enable IRQ Interrupts - \details Enables IRQ interrupts by clearing the I-bit in the CPSR. - Can only be executed in Privileged modes. + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. */ -/* intrinsic void __enable_irq(); see arm_compat.h */ +#define __WFI __builtin_arm_wfi /** - \brief Disable IRQ Interrupts - \details Disables IRQ interrupts by setting the I-bit in the CPSR. - Can only be executed in Privileged modes. + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. */ -/* intrinsic void __disable_irq(); see arm_compat.h */ +#define __WFE __builtin_arm_wfe /** - \brief Get Control Register - \details Returns the content of the Control Register. - \return Control Register value + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. */ -__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, control" : "=r" (result) ); - return(result); -} +#define __SEV __builtin_arm_sev -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Control Register (non-secure) - \details Returns the content of the non-secure Control Register when in secure mode. - \return non-secure Control Register value + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. */ -__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) -{ - uint32_t result; +#define __ISB() __builtin_arm_isb(0xF) - __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); - return(result); -} -#endif +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF) /** - \brief Set Control Register - \details Writes the given value to the Control Register. - \param [in] control Control Register value to set + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. */ -__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) -{ - __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); -} +#define __DMB() __builtin_arm_dmb(0xF) -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Control Register (non-secure) - \details Writes the given value to the non-secure Control Register when in secure state. - \param [in] control Control Register value to set + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value */ -__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) -{ - __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); -} -#endif +#define __REV(value) __builtin_bswap32(value) /** - \brief Get IPSR Register - \details Returns the content of the IPSR Register. - \return IPSR Register value + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value */ -__STATIC_FORCEINLINE uint32_t __get_IPSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); - return(result); -} +#define __REV16(value) __ROR(__REV(value), 16) /** - \brief Get APSR Register - \details Returns the content of the APSR Register. - \return APSR Register value + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value */ -__STATIC_FORCEINLINE uint32_t __get_APSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, apsr" : "=r" (result) ); - return(result); -} +#define __REVSH(value) (int16_t)__builtin_bswap16(value) /** - \brief Get xPSR Register - \details Returns the content of the xPSR Register. - \return xPSR Register value + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value */ -__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) { - uint32_t result; - - __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); - return(result); + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); } /** - \brief Get Process Stack Pointer - \details Returns the current value of the Process Stack Pointer (PSP). - \return PSP Register value + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. */ -__STATIC_FORCEINLINE uint32_t __get_PSP(void) -{ - uint32_t result; +#define __BKPT(value) __ASM volatile ("bkpt "#value) - __ASM volatile ("MRS %0, psp" : "=r" (result) ); - return(result); -} +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __builtin_arm_rbit -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Process Stack Pointer (non-secure) - \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. - \return PSP Register value + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value */ -__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) { - uint32_t result; - - __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); - return(result); + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); } -#endif +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** - \brief Set Process Stack Pointer - \details Assigns the given value to the Process Stack Pointer (PSP). - \param [in] topOfProcStack Process Stack Pointer value to set + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) */ -__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) -{ - __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); -} +#define __LDREXB (uint8_t)__builtin_arm_ldrex -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Process Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. - \param [in] topOfProcStack Process Stack Pointer value to set + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) */ -__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) -{ - __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); -} -#endif +#define __LDREXH (uint16_t)__builtin_arm_ldrex /** - \brief Get Main Stack Pointer - \details Returns the current value of the Main Stack Pointer (MSP). - \return MSP Register value + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __get_MSP(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, msp" : "=r" (result) ); - return(result); -} +#define __LDREXW (uint32_t)__builtin_arm_ldrex -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Main Stack Pointer (non-secure) - \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. - \return MSP Register value + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); - return(result); -} -#endif +#define __STREXB (uint32_t)__builtin_arm_strex /** - \brief Set Main Stack Pointer - \details Assigns the given value to the Main Stack Pointer (MSP). - \param [in] topOfMainStack Main Stack Pointer value to set + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) -{ - __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); -} +#define __STREXH (uint32_t)__builtin_arm_strex -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Main Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. - \param [in] topOfMainStack Main Stack Pointer value to set + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) -{ - __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); -} -#endif +#define __STREXW (uint32_t)__builtin_arm_strex -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Stack Pointer (non-secure) - \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. - \return SP Register value + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. */ -__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) -{ - uint32_t result; +#define __CLREX __builtin_arm_clrex + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ - __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); - return(result); -} +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) /** - \brief Set Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. - \param [in] topOfStack Stack Pointer value to set + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value */ -__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) -{ - __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); -} -#endif +#define __SSAT __builtin_arm_ssat /** - \brief Get Priority Mask - \details Returns the current state of the priority mask bit from the Priority Mask Register. - \return Priority Mask value + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value */ -__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, primask" : "=r" (result) ); - return(result); -} +#define __USAT __builtin_arm_usat -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Priority Mask (non-secure) - \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. - \return Priority Mask value + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value */ -__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) { uint32_t result; - __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); return(result); } -#endif /** - \brief Set Priority Mask - \details Assigns the given value to the Priority Mask Register. - \param [in] priMask Priority Mask + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) */ -__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) { - __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); -} - + uint32_t result; -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Set Priority Mask (non-secure) - \details Assigns the given value to the non-secure Priority Mask Register when in secure state. - \param [in] priMask Priority Mask - */ -__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) -{ - __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ } -#endif - - -#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) -/** - \brief Enable FIQ - \details Enables FIQ interrupts by clearing the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -#define __enable_fault_irq __enable_fiq /* see arm_compat.h */ - - -/** - \brief Disable FIQ - \details Disables FIQ interrupts by setting the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -#define __disable_fault_irq __disable_fiq /* see arm_compat.h */ /** - \brief Get Base Priority - \details Returns the current value of the Base Priority register. - \return Base Priority register value + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) { uint32_t result; - __ASM volatile ("MRS %0, basepri" : "=r" (result) ); - return(result); + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Base Priority (non-secure) - \details Returns the current value of the non-secure Base Priority register when in secure state. - \return Base Priority register value + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) { uint32_t result; - __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); return(result); } -#endif /** - \brief Set Base Priority - \details Assigns the given value to the Base Priority register. - \param [in] basePri Base Priority value to set + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) { - __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Base Priority (non-secure) - \details Assigns the given value to the non-secure Base Priority register when in secure state. - \param [in] basePri Base Priority value to set + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) { - __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } -#endif /** - \brief Set Base Priority with condition - \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, - or the new value increases the BASEPRI priority level. - \param [in] basePri Base Priority value to set + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) { - __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); } +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ /** - \brief Get Fault Mask - \details Returns the current value of the Fault Mask register. - \return Fault Mask register value + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value */ -__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) { - uint32_t result; - - __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); - return(result); + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; } - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Fault Mask (non-secure) - \details Returns the current value of the non-secure Fault Mask register when in secure state. - \return Fault Mask register value + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value */ -__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) { - uint32_t result; - - __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); - return(result); + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; } -#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** - \brief Set Fault Mask - \details Assigns the given value to the Fault Mask register. - \param [in] faultMask Fault Mask value to set + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) */ -__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) { - __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint8_t) result); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Fault Mask (non-secure) - \details Assigns the given value to the non-secure Fault Mask register when in secure state. - \param [in] faultMask Fault Mask value to set + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) */ -__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) { - __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); -} -#endif - -#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + uint32_t result; + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint16_t) result); +} -#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** - \brief Get Process Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always in non-secure - mode. - - \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). - \return PSPLIM Register value + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) { -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure PSPLIM is RAZ/WI - return 0U; -#else uint32_t result; - __ASM volatile ("MRS %0, psplim" : "=r" (result) ); - return result; -#endif + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return(result); } -#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Get Process Stack Pointer Limit (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always in non-secure - mode. - \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. - \return PSPLIM Register value +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) { -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) - // without main extensions, the non-secure PSPLIM is RAZ/WI - return 0U; -#else - uint32_t result; - __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); - return result; -#endif + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); } -#endif /** - \brief Set Process Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored in non-secure - mode. - - \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). - \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) { -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure PSPLIM is RAZ/WI - (void)ProcStackPtrLimit; -#else - __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); -#endif + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Process Stack Pointer (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored in non-secure - mode. - - \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. - \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) { -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) - // without main extensions, the non-secure PSPLIM is RAZ/WI - (void)ProcStackPtrLimit; -#else - __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); -#endif + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); } -#endif /** - \brief Get Main Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always. - - \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). - \return MSPLIM Register value + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) -{ -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure MSPLIM is RAZ/WI - return 0U; -#else - uint32_t result; - __ASM volatile ("MRS %0, msplim" : "=r" (result) ); - return result; -#endif -} +#define __LDAEXB (uint8_t)__builtin_arm_ldaex -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Main Stack Pointer Limit (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always. - - \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. - \return MSPLIM Register value + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) -{ -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) - // without main extensions, the non-secure MSPLIM is RAZ/WI - return 0U; -#else - uint32_t result; - __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); - return result; -#endif -} -#endif +#define __LDAEXH (uint16_t)__builtin_arm_ldaex /** - \brief Set Main Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored. + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex - \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). - \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) -{ -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure MSPLIM is RAZ/WI - (void)MainStackPtrLimit; -#else - __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); -#endif -} +#define __STLEXB (uint32_t)__builtin_arm_stlex -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Main Stack Pointer Limit (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored. + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex - \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. - \param [in] MainStackPtrLimit Main Stack Pointer value to set + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) -{ -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) - // without main extensions, the non-secure MSPLIM is RAZ/WI - (void)MainStackPtrLimit; -#else - __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); -#endif -} -#endif +#define __STLEX (uint32_t)__builtin_arm_stlex #endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + /** - \brief Get FPSCR - \details Returns the current value of the Floating Point Status/Control register. - \return Floating Point Status/Control register value + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. */ -#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ - (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) -#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr -#else -#define __get_FPSCR() ((uint32_t)0U) +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} #endif + /** - \brief Set FPSCR - \details Assigns the given value to the Floating Point Status/Control register. - \param [in] fpscr Floating Point Status/Control value to set + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. */ -#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ - (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) -#define __set_FPSCR __builtin_arm_set_fpscr -#else -#define __set_FPSCR(x) ((void)(x)) +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} #endif -/*@} end of CMSIS_Core_RegAccFunctions */ - +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; -/* ########################## Core Instruction Access ######################### */ -/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface - Access to dedicated instructions - @{ -*/ + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} -/* Define macros for porting to both thumb1 and thumb2. - * For thumb1, use low register (r0-r7), specified by constraint "l" - * Otherwise, use general registers, specified by constraint "r" */ -#if defined (__thumb__) && !defined (__thumb2__) -#define __CMSIS_GCC_OUT_REG(r) "=l" (r) -#define __CMSIS_GCC_USE_REG(r) "l" (r) -#else -#define __CMSIS_GCC_OUT_REG(r) "=r" (r) -#define __CMSIS_GCC_USE_REG(r) "r" (r) -#endif +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief No Operation - \details No Operation does nothing. This instruction can be used for code alignment purposes. + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value */ -#define __NOP __builtin_arm_nop +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; -/** - \brief Wait For Interrupt - \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. - */ -#define __WFI __builtin_arm_wfi + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif /** - \brief Wait For Event - \details Wait For Event is a hint instruction that permits the processor to enter - a low-power state until one of a number of events occurs. + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set */ -#define __WFE __builtin_arm_wfe +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); + __ISB(); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Send Event - \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set */ -#define __SEV __builtin_arm_sev +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); + __ISB(); +} +#endif /** - \brief Instruction Synchronization Barrier - \details Instruction Synchronization Barrier flushes the pipeline in the processor, - so that all instructions following the ISB are fetched from cache or memory, - after the instruction has been completed. + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value */ -#define __ISB() __builtin_arm_isb(0xF) +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + /** - \brief Data Synchronization Barrier - \details Acts as a special kind of Data Memory Barrier. - It completes when all explicit memory accesses before this instruction complete. + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value */ -#define __DSB() __builtin_arm_dsb(0xF) +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} /** - \brief Data Memory Barrier - \details Ensures the apparent order of the explicit memory operations before - and after the instruction, without ensuring their completion. + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value */ -#define __DMB() __builtin_arm_dmb(0xF) +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} /** - \brief Reverse byte order (32 bit) - \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. - \param [in] value Value to reverse - \return Reversed value + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value */ -#define __REV(value) __builtin_bswap32(value) +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Reverse byte order (16 bit) - \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. - \param [in] value Value to reverse - \return Reversed value + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value */ -#define __REV16(value) __ROR(__REV(value), 16) +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif /** - \brief Reverse byte order (16 bit) - \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. - \param [in] value Value to reverse - \return Reversed value + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set */ -#define __REVSH(value) (int16_t)__builtin_bswap16(value) +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Rotate Right in unsigned value (32 bit) - \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - \param [in] op1 Value to rotate - \param [in] op2 Number of Bits to rotate - \return Rotated value + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set */ -__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) { - op2 %= 32U; - if (op2 == 0U) - { - return op1; - } - return (op1 >> op2) | (op1 << (32U - op2)); + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); } +#endif /** - \brief Breakpoint - \details Causes the processor to enter Debug state. - Debug tools can use this to investigate system state when the instruction at a particular address is reached. - \param [in] value is ignored by the processor. - If required, a debugger can use it to store additional information about the breakpoint. + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value */ -#define __BKPT(value) __ASM volatile ("bkpt "#value) +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Reverse bit order of value - \details Reverses the bit order of the given value. - \param [in] value Value to reverse - \return Reversed value + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value */ -#define __RBIT __builtin_arm_rbit +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + /** - \brief Count leading zeros - \details Counts the number of leading zeros of a data value. - \param [in] value Value to count the leading zeros - \return number of leading zeros in value + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set */ -__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) { - /* Even though __builtin_clz produces a CLZ instruction on ARM, formally - __builtin_clz(0) is undefined behaviour, so handle this case specially. - This guarantees ARM-compatible results if happening to compile on a non-ARM - target, and ensures the compiler doesn't decide to activate any - optimisations using the logic "value was passed to __builtin_clz, so it - is non-zero". - ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a - single CLZ instruction. - */ - if (value == 0U) - { - return 32U; - } - return __builtin_clz(value); + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); } -#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief LDR Exclusive (8 bit) - \details Executes a exclusive LDR instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set */ -#define __LDREXB (uint8_t)__builtin_arm_ldrex +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief LDR Exclusive (16 bit) - \details Executes a exclusive LDR instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value */ -#define __LDREXH (uint16_t)__builtin_arm_ldrex +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} /** - \brief LDR Exclusive (32 bit) - \details Executes a exclusive LDR instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set */ -#define __LDREXW (uint32_t)__builtin_arm_ldrex +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif /** - \brief STR Exclusive (8 bit) - \details Executes a exclusive STR instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value */ -#define __STREXB (uint32_t)__builtin_arm_strex +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief STR Exclusive (16 bit) - \details Executes a exclusive STR instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value */ -#define __STREXH (uint32_t)__builtin_arm_strex +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif /** - \brief STR Exclusive (32 bit) - \details Executes a exclusive STR instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask */ -#define __STREXW (uint32_t)__builtin_arm_strex +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Remove the exclusive lock - \details Removes the exclusive lock which is created by LDREX. + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask */ -#define __CLREX __builtin_arm_clrex - -#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) - /** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. */ -#define __SSAT __builtin_arm_ssat +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} /** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. */ -#define __USAT __builtin_arm_usat +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} /** - \brief Rotate Right with Extend (32 bit) - \details Moves each bit of a bitstring right by one bit. - The carry input is shifted in at the left end of the bitstring. - \param [in] value Value to rotate - \return Rotated value + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value */ -__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) { uint32_t result; - __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); return(result); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief LDRT Unprivileged (8 bit) - \details Executes a Unprivileged LDRT instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value */ -__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) { uint32_t result; - __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint8_t) result); /* Add explicit type cast here */ + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); } +#endif /** - \brief LDRT Unprivileged (16 bit) - \details Executes a Unprivileged LDRT instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set */ -__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) { - uint32_t result; - - __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint16_t) result); /* Add explicit type cast here */ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief LDRT Unprivileged (32 bit) - \details Executes a Unprivileged LDRT instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set */ -__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) { - uint32_t result; - - __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); - return(result); + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); } +#endif /** - \brief STRT Unprivileged (8 bit) - \details Executes a Unprivileged STRT instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set */ -__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) { - __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); } /** - \brief STRT Unprivileged (16 bit) - \details Executes a Unprivileged STRT instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value */ -__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) { - __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief STRT Unprivileged (32 bit) - \details Executes a Unprivileged STRT instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value */ -__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) { - __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); } +#endif -#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ /** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set */ -__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) { - if ((sat >= 1U) && (sat <= 32U)) - { - const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); - const int32_t min = -1 - max ; - if (val > max) - { - return max; - } - else if (val < min) - { - return min; - } - } - return val; + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); } + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set */ -__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) { - if (sat <= 31U) - { - const uint32_t max = ((1U << sat) - 1U); - if (val > (int32_t)max) - { - return max; - } - else if (val < 0) - { - return 0U; - } - } - return (uint32_t)val; + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); } +#endif #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ @@ -1208,150 +1181,210 @@ __STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + /** - \brief Load-Acquire (8 bit) - \details Executes a LDAB instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value */ -__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) { +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else uint32_t result; - - __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return ((uint8_t) result); + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif } - +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Load-Acquire (16 bit) - \details Executes a LDAH instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value */ -__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) { +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else uint32_t result; - - __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return ((uint16_t) result); + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif } +#endif /** - \brief Load-Acquire (32 bit) - \details Executes a LDA instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set */ -__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) { - uint32_t result; - - __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return(result); +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Store-Release (8 bit) - \details Executes a STLB instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set */ -__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) { - __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif } +#endif /** - \brief Store-Release (16 bit) - \details Executes a STLH instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value */ -__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) { - __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Store-Release (32 bit) - \details Executes a STL instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value */ -__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) { - __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif } +#endif /** - \brief Load-Acquire Exclusive (8 bit) - \details Executes a LDAB exclusive instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -#define __LDAEXB (uint8_t)__builtin_arm_ldaex - + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. -/** - \brief Load-Acquire Exclusive (16 bit) - \details Executes a LDAH exclusive instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set */ -#define __LDAEXH (uint16_t)__builtin_arm_ldaex +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Load-Acquire Exclusive (32 bit) - \details Executes a LDA exclusive instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -#define __LDAEX (uint32_t)__builtin_arm_ldaex - + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. -/** - \brief Store-Release Exclusive (8 bit) - \details Executes a STLB exclusive instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set */ -#define __STLEXB (uint32_t)__builtin_arm_stlex +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ /** - \brief Store-Release Exclusive (16 bit) - \details Executes a STLH exclusive instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value */ -#define __STLEXH (uint32_t)__builtin_arm_stlex - +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr +#else +#define __get_FPSCR() ((uint32_t)0U) +#endif /** - \brief Store-Release Exclusive (32 bit) - \details Executes a STL exclusive instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set */ -#define __STLEX (uint32_t)__builtin_arm_stlex +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __set_FPSCR __builtin_arm_set_fpscr +#else +#define __set_FPSCR(x) ((void)(x)) +#endif -#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ -/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ +/*@} end of CMSIS_Core_RegAccFunctions */ /* ################### Compiler specific Intrinsics ########################### */ @@ -1878,6 +1911,8 @@ __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) #define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + __STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) { int32_t result; diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_gcc.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_gcc.h index a2778f58e8f..67bda4ef3c3 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_gcc.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_gcc.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file cmsis_gcc.h * @brief CMSIS compiler GCC header file - * @version V5.3.0 - * @date 26. March 2020 + * @version V5.4.1 + * @date 27. May 2021 ******************************************************************************/ /* - * Copyright (c) 2009-2020 Arm Limited. All rights reserved. + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -46,9 +46,9 @@ #ifndef __STATIC_INLINE #define __STATIC_INLINE static inline #endif -#ifndef __STATIC_FORCEINLINE +#ifndef __STATIC_FORCEINLINE #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline -#endif +#endif #ifndef __NO_RETURN #define __NO_RETURN __attribute__((__noreturn__)) #endif @@ -126,23 +126,23 @@ \details This default implementations initialized all data and additional bss sections relying on .copy.table and .zero.table specified properly in the used linker script. - + */ __STATIC_FORCEINLINE __NO_RETURN void __cmsis_start(void) { extern void _start(void) __NO_RETURN; - + typedef struct { uint32_t const* src; uint32_t* dest; uint32_t wlen; } __copy_table_t; - + typedef struct { uint32_t* dest; uint32_t wlen; } __zero_table_t; - + extern const __copy_table_t __copy_table_start__; extern const __copy_table_t __copy_table_end__; extern const __zero_table_t __zero_table_start__; @@ -153,16 +153,16 @@ __STATIC_FORCEINLINE __NO_RETURN void __cmsis_start(void) pTable->dest[i] = pTable->src[i]; } } - + for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) { for(uint32_t i=0u; iwlen; ++i) { pTable->dest[i] = 0u; } } - + _start(); } - + #define __PROGRAM_START __cmsis_start #endif @@ -182,462 +182,569 @@ __STATIC_FORCEINLINE __NO_RETURN void __cmsis_start(void) #define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section(".vectors"))) #endif -/* ########################### Core Function Access ########################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions - @{ - */ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL __StackSeal +#endif -/** - \brief Enable IRQ Interrupts - \details Enables IRQ interrupts by clearing the I-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__STATIC_FORCEINLINE void __enable_irq(void) -{ - __ASM volatile ("cpsie i" : : : "memory"); -} +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif -/** - \brief Disable IRQ Interrupts - \details Disables IRQ interrupts by setting the I-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__STATIC_FORCEINLINE void __disable_irq(void) -{ - __ASM volatile ("cpsid i" : : : "memory"); +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; } +#endif + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif /** - \brief Get Control Register - \details Returns the content of the Control Register. - \return Control Register value + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. */ -__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) -{ - uint32_t result; +#define __NOP() __ASM volatile ("nop") - __ASM volatile ("MRS %0, control" : "=r" (result) ); - return(result); -} +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI() __ASM volatile ("wfi":::"memory") -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Control Register (non-secure) - \details Returns the content of the non-secure Control Register when in secure mode. - \return non-secure Control Register value + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. */ -__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); - return(result); -} -#endif +#define __WFE() __ASM volatile ("wfe":::"memory") /** - \brief Set Control Register - \details Writes the given value to the Control Register. - \param [in] control Control Register value to set + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. */ -__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) -{ - __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); -} +#define __SEV() __ASM volatile ("sev") -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Control Register (non-secure) - \details Writes the given value to the non-secure Control Register when in secure state. - \param [in] control Control Register value to set + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. */ -__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +__STATIC_FORCEINLINE void __ISB(void) { - __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); + __ASM volatile ("isb 0xF":::"memory"); } -#endif /** - \brief Get IPSR Register - \details Returns the content of the IPSR Register. - \return IPSR Register value + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. */ -__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +__STATIC_FORCEINLINE void __DSB(void) { - uint32_t result; - - __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); - return(result); + __ASM volatile ("dsb 0xF":::"memory"); } /** - \brief Get APSR Register - \details Returns the content of the APSR Register. - \return APSR Register value + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. */ -__STATIC_FORCEINLINE uint32_t __get_APSR(void) +__STATIC_FORCEINLINE void __DMB(void) { - uint32_t result; - - __ASM volatile ("MRS %0, apsr" : "=r" (result) ); - return(result); + __ASM volatile ("dmb 0xF":::"memory"); } /** - \brief Get xPSR Register - \details Returns the content of the xPSR Register. - \return xPSR Register value + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value */ -__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +__STATIC_FORCEINLINE uint32_t __REV(uint32_t value) { +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else uint32_t result; - __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); - return(result); + __ASM ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif } /** - \brief Get Process Stack Pointer - \details Returns the current value of the Process Stack Pointer (PSP). - \return PSP Register value + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value */ -__STATIC_FORCEINLINE uint32_t __get_PSP(void) +__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value) { uint32_t result; - __ASM volatile ("MRS %0, psp" : "=r" (result) ); - return(result); + __ASM ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Process Stack Pointer (non-secure) - \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. - \return PSP Register value + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value */ -__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +__STATIC_FORCEINLINE int16_t __REVSH(int16_t value) { - uint32_t result; +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (int16_t)__builtin_bswap16(value); +#else + int16_t result; - __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); - return(result); -} + __ASM ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; #endif +} /** - \brief Set Process Stack Pointer - \details Assigns the given value to the Process Stack Pointer (PSP). - \param [in] topOfProcStack Process Stack Pointer value to set + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value */ -__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) { - __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Process Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. - \param [in] topOfProcStack Process Stack Pointer value to set + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. */ -__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) -{ - __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); -} -#endif +#define __BKPT(value) __ASM volatile ("bkpt "#value) /** - \brief Get Main Stack Pointer - \details Returns the current value of the Main Stack Pointer (MSP). - \return MSP Register value + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value */ -__STATIC_FORCEINLINE uint32_t __get_MSP(void) +__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value) { uint32_t result; - __ASM volatile ("MRS %0, msp" : "=r" (result) ); - return(result); +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) + __ASM ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value != 0U; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return result; } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Main Stack Pointer (non-secure) - \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. - \return MSP Register value + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value */ -__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) { - uint32_t result; - - __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); - return(result); + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM GCC 7.3 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); } -#endif +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** - \brief Set Main Stack Pointer - \details Assigns the given value to the Main Stack Pointer (MSP). - \param [in] topOfMainStack Main Stack Pointer value to set + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) */ -__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +__STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) { - __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); -} - + uint32_t result; -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Set Main Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. - \param [in] topOfMainStack Main Stack Pointer value to set - */ -__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) -{ - __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); -} +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); #endif + return ((uint8_t) result); /* Add explicit type cast here */ +} -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Stack Pointer (non-secure) - \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. - \return SP Register value + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +__STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); - return(result); +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ } /** - \brief Set Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. - \param [in] topOfStack Stack Pointer value to set + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) */ -__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +__STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) { - __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); } -#endif /** - \brief Get Priority Mask - \details Returns the current state of the priority mask bit from the Priority Mask Register. - \return Priority Mask value + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +__STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, primask" : "=r" (result) ); - return(result); + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Priority Mask (non-secure) - \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. - \return Priority Mask value + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +__STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); - return(result); + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); } -#endif /** - \brief Set Priority Mask - \details Assigns the given value to the Priority Mask Register. - \param [in] priMask Priority Mask + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +__STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) { - __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Priority Mask (non-secure) - \details Assigns the given value to the non-secure Priority Mask Register when in secure state. - \param [in] priMask Priority Mask + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. */ -__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +__STATIC_FORCEINLINE void __CLREX(void) { - __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); + __ASM volatile ("clrex" ::: "memory"); } -#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) /** - \brief Enable FIQ - \details Enables FIQ interrupts by clearing the F-bit in the CPSR. - Can only be executed in Privileged modes. + \brief Signed Saturate + \details Saturates a signed value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (1..32) + \return Saturated value */ -__STATIC_FORCEINLINE void __enable_fault_irq(void) -{ - __ASM volatile ("cpsie f" : : : "memory"); -} +#define __SSAT(ARG1, ARG2) \ +__extension__ \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM volatile ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ + __RES; \ + }) /** - \brief Disable FIQ - \details Disables FIQ interrupts by setting the F-bit in the CPSR. - Can only be executed in Privileged modes. + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (0..31) + \return Saturated value */ -__STATIC_FORCEINLINE void __disable_fault_irq(void) -{ - __ASM volatile ("cpsid f" : : : "memory"); -} +#define __USAT(ARG1, ARG2) \ +__extension__ \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM volatile ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ + __RES; \ + }) /** - \brief Get Base Priority - \details Returns the current value of the Base Priority register. - \return Base Priority register value + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value */ -__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) { uint32_t result; - __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); return(result); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Base Priority (non-secure) - \details Returns the current value of the non-secure Base Priority register when in secure state. - \return Base Priority register value + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); - return(result); -} +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); #endif + return ((uint8_t) result); /* Add explicit type cast here */ +} /** - \brief Set Base Priority - \details Assigns the given value to the Base Priority register. - \param [in] basePri Base Priority value to set + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) */ -__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) { - __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Base Priority (non-secure) - \details Assigns the given value to the non-secure Base Priority register when in secure state. - \param [in] basePri Base Priority value to set + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) */ -__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) { - __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); } -#endif /** - \brief Set Base Priority with condition - \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, - or the new value increases the BASEPRI priority level. - \param [in] basePri Base Priority value to set + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) { - __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** - \brief Get Fault Mask - \details Returns the current value of the Fault Mask register. - \return Fault Mask register value + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) { - uint32_t result; - - __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); - return(result); + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Fault Mask (non-secure) - \details Returns the current value of the non-secure Fault Mask register when in secure state. - \return Fault Mask register value + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) { - uint32_t result; - - __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); - return(result); + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); } -#endif +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ /** - \brief Set Fault Mask - \details Assigns the given value to the Fault Mask register. - \param [in] faultMask Fault Mask value to set + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value */ -__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) { - __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; } - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Fault Mask (non-secure) - \details Assigns the given value to the non-secure Fault Mask register when in secure state. - \param [in] faultMask Fault Mask value to set + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value */ -__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) { - __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; } -#endif #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ @@ -646,780 +753,646 @@ __STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) - /** - \brief Get Process Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always in non-secure - mode. - - \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). - \return PSPLIM Register value + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) { -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure PSPLIM is RAZ/WI - return 0U; -#else - uint32_t result; - __ASM volatile ("MRS %0, psplim" : "=r" (result) ); - return result; -#endif + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint8_t) result); } -#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Get Process Stack Pointer Limit (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always. - \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. - \return PSPLIM Register value +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) */ -__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) { -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) - // without main extensions, the non-secure PSPLIM is RAZ/WI - return 0U; -#else - uint32_t result; - __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); - return result; -#endif + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint16_t) result); } -#endif /** - \brief Set Process Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored in non-secure - mode. - - \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). - \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) */ -__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) { -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure PSPLIM is RAZ/WI - (void)ProcStackPtrLimit; -#else - __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); -#endif + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return(result); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Process Stack Pointer (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored. - - \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. - \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) { -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) - // without main extensions, the non-secure PSPLIM is RAZ/WI - (void)ProcStackPtrLimit; -#else - __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); -#endif + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); } -#endif /** - \brief Get Main Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always in non-secure - mode. - - \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). - \return MSPLIM Register value + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) { -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure MSPLIM is RAZ/WI - return 0U; -#else - uint32_t result; - __ASM volatile ("MRS %0, msplim" : "=r" (result) ); - return result; -#endif + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Get Main Stack Pointer Limit (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always. - - \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. - \return MSPLIM Register value + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location */ -__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) { -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) - // without main extensions, the non-secure MSPLIM is RAZ/WI - return 0U; -#else - uint32_t result; - __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); - return result; -#endif + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); } -#endif /** - \brief Set Main Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored in non-secure - mode. - - \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). - \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) */ -__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +__STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr) { -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure MSPLIM is RAZ/WI - (void)MainStackPtrLimit; -#else - __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); -#endif + uint32_t result; + + __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint8_t) result); } -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Set Main Stack Pointer Limit (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored. + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr) +{ + uint32_t result; - \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. - \param [in] MainStackPtrLimit Main Stack Pointer value to set + __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) */ -__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +__STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr) { -#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) - // without main extensions, the non-secure MSPLIM is RAZ/WI - (void)MainStackPtrLimit; -#else - __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); -#endif + uint32_t result; + + __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return(result); } -#endif -#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); + return(result); +} /** - \brief Get FPSCR - \details Returns the current value of the Floating Point Status/Control register. - \return Floating Point Status/Control register value + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -__STATIC_FORCEINLINE uint32_t __get_FPSCR(void) +__STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) { -#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ - (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) -#if __has_builtin(__builtin_arm_get_fpscr) -// Re-enable using built-in when GCC has been fixed -// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) - /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ - return __builtin_arm_get_fpscr(); -#else - uint32_t result; + uint32_t result; - __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); - return(result); -#endif -#else - return(0U); -#endif + __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); + return(result); } /** - \brief Set FPSCR - \details Assigns the given value to the Floating Point Status/Control register. - \param [in] fpscr Floating Point Status/Control value to set + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed */ -__STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) +__STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) { -#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ - (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) -#if __has_builtin(__builtin_arm_set_fpscr) -// Re-enable using built-in when GCC has been fixed -// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) - /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ - __builtin_arm_set_fpscr(fpscr); -#else - __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); -#endif -#else - (void)fpscr; -#endif + uint32_t result; + + __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); + return(result); } +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ -/*@} end of CMSIS_Core_RegAccFunctions */ +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ -/* ########################## Core Instruction Access ######################### */ -/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface - Access to dedicated instructions +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions @{ -*/ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} -/* Define macros for porting to both thumb1 and thumb2. - * For thumb1, use low register (r0-r7), specified by constraint "l" - * Otherwise, use general registers, specified by constraint "r" */ -#if defined (__thumb__) && !defined (__thumb2__) -#define __CMSIS_GCC_OUT_REG(r) "=l" (r) -#define __CMSIS_GCC_RW_REG(r) "+l" (r) -#define __CMSIS_GCC_USE_REG(r) "l" (r) -#else -#define __CMSIS_GCC_OUT_REG(r) "=r" (r) -#define __CMSIS_GCC_RW_REG(r) "+r" (r) -#define __CMSIS_GCC_USE_REG(r) "r" (r) -#endif /** - \brief No Operation - \details No Operation does nothing. This instruction can be used for code alignment purposes. + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. */ -#define __NOP() __ASM volatile ("nop") +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + /** - \brief Wait For Interrupt - \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value */ -#define __WFI() __ASM volatile ("wfi":::"memory") +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Wait For Event - \details Wait For Event is a hint instruction that permits the processor to enter - a low-power state until one of a number of events occurs. + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value */ -#define __WFE() __ASM volatile ("wfe":::"memory") +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif /** - \brief Send Event - \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set */ -#define __SEV() __ASM volatile ("sev") +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); + __ISB(); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Instruction Synchronization Barrier - \details Instruction Synchronization Barrier flushes the pipeline in the processor, - so that all instructions following the ISB are fetched from cache or memory, - after the instruction has been completed. + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set */ -__STATIC_FORCEINLINE void __ISB(void) +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) { - __ASM volatile ("isb 0xF":::"memory"); + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); + __ISB(); } +#endif /** - \brief Data Synchronization Barrier - \details Acts as a special kind of Data Memory Barrier. - It completes when all explicit memory accesses before this instruction complete. + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value */ -__STATIC_FORCEINLINE void __DSB(void) +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) { - __ASM volatile ("dsb 0xF":::"memory"); + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); } /** - \brief Data Memory Barrier - \details Ensures the apparent order of the explicit memory operations before - and after the instruction, without ensuring their completion. + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value */ -__STATIC_FORCEINLINE void __DMB(void) +__STATIC_FORCEINLINE uint32_t __get_APSR(void) { - __ASM volatile ("dmb 0xF":::"memory"); + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); } /** - \brief Reverse byte order (32 bit) - \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. - \param [in] value Value to reverse - \return Reversed value + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value */ -__STATIC_FORCEINLINE uint32_t __REV(uint32_t value) +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) { -#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) - return __builtin_bswap32(value); -#else uint32_t result; - __ASM ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return result; -#endif + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Reverse byte order (16 bit) - \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. - \param [in] value Value to reverse - \return Reversed value + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value */ -__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value) +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) { uint32_t result; - __ASM ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return result; + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); } +#endif /** - \brief Reverse byte order (16 bit) - \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. - \param [in] value Value to reverse - \return Reversed value + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set */ -__STATIC_FORCEINLINE int16_t __REVSH(int16_t value) +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) { -#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) - return (int16_t)__builtin_bswap16(value); -#else - int16_t result; - - __ASM ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return result; -#endif + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Rotate Right in unsigned value (32 bit) - \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - \param [in] op1 Value to rotate - \param [in] op2 Number of Bits to rotate - \return Rotated value + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set */ -__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) { - op2 %= 32U; - if (op2 == 0U) - { - return op1; - } - return (op1 >> op2) | (op1 << (32U - op2)); + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); } +#endif /** - \brief Breakpoint - \details Causes the processor to enter Debug state. - Debug tools can use this to investigate system state when the instruction at a particular address is reached. - \param [in] value is ignored by the processor. - If required, a debugger can use it to store additional information about the breakpoint. + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value */ -#define __BKPT(value) __ASM volatile ("bkpt "#value) +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Reverse bit order of value - \details Reverses the bit order of the given value. - \param [in] value Value to reverse - \return Reversed value + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value */ -__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value) +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) { uint32_t result; -#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) - __ASM ("rbit %0, %1" : "=r" (result) : "r" (value) ); -#else - uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ - - result = value; /* r will be reversed bits of v; first get LSB of v */ - for (value >>= 1U; value != 0U; value >>= 1U) - { - result <<= 1U; - result |= value & 1U; - s--; - } - result <<= s; /* shift when v's highest bits are zero */ -#endif - return result; + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); } +#endif /** - \brief Count leading zeros - \details Counts the number of leading zeros of a data value. - \param [in] value Value to count the leading zeros - \return number of leading zeros in value + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set */ -__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) { - /* Even though __builtin_clz produces a CLZ instruction on ARM, formally - __builtin_clz(0) is undefined behaviour, so handle this case specially. - This guarantees ARM-compatible results if happening to compile on a non-ARM - target, and ensures the compiler doesn't decide to activate any - optimisations using the logic "value was passed to __builtin_clz, so it - is non-zero". - ARM GCC 7.3 and possibly earlier will optimise this test away, leaving a - single CLZ instruction. - */ - if (value == 0U) - { - return 32U; - } - return __builtin_clz(value); + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); } -#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief LDR Exclusive (8 bit) - \details Executes a exclusive LDR instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set */ -__STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) { - uint32_t result; - -#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) - __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); -#else - /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not - accepted by assembler. So has to use following less efficient pattern. - */ - __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); -#endif - return ((uint8_t) result); /* Add explicit type cast here */ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); } +#endif +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief LDR Exclusive (16 bit) - \details Executes a exclusive LDR instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value */ -__STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) { - uint32_t result; + uint32_t result; -#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) - __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); -#else - /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not - accepted by assembler. So has to use following less efficient pattern. - */ - __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); -#endif - return ((uint16_t) result); /* Add explicit type cast here */ + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); } /** - \brief LDR Exclusive (32 bit) - \details Executes a exclusive LDR instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set */ -__STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) { - uint32_t result; - - __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); - return(result); + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); } +#endif /** - \brief STR Exclusive (8 bit) - \details Executes a exclusive STR instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value */ -__STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); - return(result); + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief STR Exclusive (16 bit) - \details Executes a exclusive STR instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value */ -__STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); - return(result); + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); } +#endif /** - \brief STR Exclusive (32 bit) - \details Executes a exclusive STR instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask */ -__STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) { - uint32_t result; - - __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); - return(result); + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Remove the exclusive lock - \details Removes the exclusive lock which is created by LDREX. + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask */ -__STATIC_FORCEINLINE void __CLREX(void) +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) { - __ASM volatile ("clrex" ::: "memory"); + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); } - -#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ +#endif #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) /** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] ARG1 Value to be saturated - \param [in] ARG2 Bit position to saturate to (1..32) - \return Saturated value + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. */ -#define __SSAT(ARG1, ARG2) \ -__extension__ \ -({ \ - int32_t __RES, __ARG1 = (ARG1); \ - __ASM volatile ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ - __RES; \ - }) +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} /** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] ARG1 Value to be saturated - \param [in] ARG2 Bit position to saturate to (0..31) - \return Saturated value + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. */ -#define __USAT(ARG1, ARG2) \ - __extension__ \ -({ \ - uint32_t __RES, __ARG1 = (ARG1); \ - __ASM volatile ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ - __RES; \ - }) +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} /** - \brief Rotate Right with Extend (32 bit) - \details Moves each bit of a bitstring right by one bit. - The carry input is shifted in at the left end of the bitstring. - \param [in] value Value to rotate - \return Rotated value + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value */ -__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) { uint32_t result; - __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); return(result); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief LDRT Unprivileged (8 bit) - \details Executes a Unprivileged LDRT instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value */ -__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) { - uint32_t result; + uint32_t result; -#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) - __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); -#else - /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not - accepted by assembler. So has to use following less efficient pattern. - */ - __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); -#endif - return ((uint8_t) result); /* Add explicit type cast here */ + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); } +#endif /** - \brief LDRT Unprivileged (16 bit) - \details Executes a Unprivileged LDRT instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set */ -__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) { - uint32_t result; - -#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) - __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); -#else - /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not - accepted by assembler. So has to use following less efficient pattern. - */ - __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); -#endif - return ((uint16_t) result); /* Add explicit type cast here */ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief LDRT Unprivileged (32 bit) - \details Executes a Unprivileged LDRT instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set */ -__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) { - uint32_t result; - - __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); - return(result); + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); } +#endif /** - \brief STRT Unprivileged (8 bit) - \details Executes a Unprivileged STRT instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set */ -__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) { - __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); } /** - \brief STRT Unprivileged (16 bit) - \details Executes a Unprivileged STRT instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value */ -__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) { - __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief STRT Unprivileged (32 bit) - \details Executes a Unprivileged STRT instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value */ -__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) { - __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); } +#endif -#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ /** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set */ -__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) { - if ((sat >= 1U) && (sat <= 32U)) - { - const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); - const int32_t min = -1 - max ; - if (val > max) - { - return max; - } - else if (val < min) - { - return min; - } - } - return val; + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); } + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set */ -__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) { - if (sat <= 31U) - { - const uint32_t max = ((1U << sat) - 1U); - if (val > (int32_t)max) - { - return max; - } - else if (val < 0) - { - return 0U; - } - } - return (uint32_t)val; + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); } +#endif #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ @@ -1428,186 +1401,235 @@ __STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) -/** - \brief Load-Acquire (8 bit) - \details Executes a LDAB instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) -{ - uint32_t result; - - __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return ((uint8_t) result); -} - /** - \brief Load-Acquire (16 bit) - \details Executes a LDAH instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) -{ - uint32_t result; - - __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return ((uint16_t) result); -} - + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. -/** - \brief Load-Acquire (32 bit) - \details Executes a LDA instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value */ -__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) { - uint32_t result; - - __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return(result); +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif } - +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Store-Release (8 bit) - \details Executes a STLB instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value */ -__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) { - __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif } +#endif /** - \brief Store-Release (16 bit) - \details Executes a STLH instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set */ -__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) { - __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Store-Release (32 bit) - \details Executes a STL instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set */ -__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) { - __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif } +#endif /** - \brief Load-Acquire Exclusive (8 bit) - \details Executes a LDAB exclusive instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value */ -__STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr) +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) { - uint32_t result; - - __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return ((uint8_t) result); +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Load-Acquire Exclusive (16 bit) - \details Executes a LDAH exclusive instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value */ -__STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr) +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) { - uint32_t result; - - __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return ((uint16_t) result); +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif } +#endif /** - \brief Load-Acquire Exclusive (32 bit) - \details Executes a LDA exclusive instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set */ -__STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr) +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) { - uint32_t result; - - __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return(result); +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** - \brief Store-Release Exclusive (8 bit) - \details Executes a STLB exclusive instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set */ -__STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) { - uint32_t result; - - __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); - return(result); +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif } +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ /** - \brief Store-Release Exclusive (16 bit) - \details Executes a STLH exclusive instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value */ -__STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) +__STATIC_FORCEINLINE uint32_t __get_FPSCR(void) { - uint32_t result; +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_get_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + return __builtin_arm_get_fpscr(); +#else + uint32_t result; - __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); - return(result); + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + return(result); +#endif +#else + return(0U); +#endif } /** - \brief Store-Release Exclusive (32 bit) - \details Executes a STL exclusive instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set */ -__STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) +__STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) { - uint32_t result; - - __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); - return(result); +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_set_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + __builtin_arm_set_fpscr(fpscr); +#else + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); +#endif +#else + (void)fpscr; +#endif } -#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ -/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ +/*@} end of CMSIS_Core_RegAccFunctions */ /* ################### Compiler specific Intrinsics ########################### */ @@ -1925,6 +1947,7 @@ __STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) } #define __SSAT16(ARG1, ARG2) \ +__extension__ \ ({ \ int32_t __RES, __ARG1 = (ARG1); \ __ASM volatile ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ @@ -1932,6 +1955,7 @@ __STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) }) #define __USAT16(ARG1, ARG2) \ +__extension__ \ ({ \ uint32_t __RES, __ARG1 = (ARG1); \ __ASM volatile ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ @@ -1965,9 +1989,11 @@ __STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) __STATIC_FORCEINLINE uint32_t __SXTB16_RORn(uint32_t op1, uint32_t rotate) { uint32_t result; - - __ASM ("sxtb16 %0, %1, ROR %2" : "=r" (result) : "r" (op1), "i" (rotate) ); - + if (__builtin_constant_p(rotate) && ((rotate == 8U) || (rotate == 16U) || (rotate == 24U))) { + __ASM volatile ("sxtb16 %0, %1, ROR %2" : "=r" (result) : "r" (op1), "i" (rotate) ); + } else { + result = __SXTB16(__ROR(op1, rotate)) ; + } return result; } @@ -1979,6 +2005,18 @@ __STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) return(result); } +__STATIC_FORCEINLINE uint32_t __SXTAB16_RORn(uint32_t op1, uint32_t op2, uint32_t rotate) +{ + uint32_t result; + if (__builtin_constant_p(rotate) && ((rotate == 8U) || (rotate == 16U) || (rotate == 24U))) { + __ASM volatile ("sxtab16 %0, %1, %2, ROR %3" : "=r" (result) : "r" (op1) , "r" (op2) , "i" (rotate)); + } else { + result = __SXTAB16(op1, __ROR(op2, rotate)); + } + return result; +} + + __STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) { uint32_t result; @@ -2135,8 +2173,9 @@ __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) return(result); } -#if 0 + #define __PKHBT(ARG1,ARG2,ARG3) \ +__extension__ \ ({ \ uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ @@ -2144,6 +2183,7 @@ __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) }) #define __PKHTB(ARG1,ARG2,ARG3) \ +__extension__ \ ({ \ uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ if (ARG3 == 0) \ @@ -2152,13 +2192,7 @@ __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ __RES; \ }) -#endif - -#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ - ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) -#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ - ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) __STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) { diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_iccarm.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_iccarm.h index 7eeffca5c71..65b824b009c 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_iccarm.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_iccarm.h @@ -1,14 +1,14 @@ /**************************************************************************//** * @file cmsis_iccarm.h * @brief CMSIS compiler ICCARM (IAR Compiler for Arm) header file - * @version V5.2.0 - * @date 28. January 2020 + * @version V5.3.0 + * @date 14. April 2021 ******************************************************************************/ //------------------------------------------------------------------------------ // -// Copyright (c) 2017-2019 IAR Systems -// Copyright (c) 2017-2019 Arm Limited. All rights reserved. +// Copyright (c) 2017-2021 IAR Systems +// Copyright (c) 2017-2021 Arm Limited. All rights reserved. // // SPDX-License-Identifier: Apache-2.0 // @@ -238,6 +238,7 @@ __packed struct __iar_u32 { uint32_t v; }; #endif #endif +#undef __WEAK /* undo the definition from DLib_Defaults.h */ #ifndef __WEAK #if __ICCARM_V8 #define __WEAK __attribute__((weak)) @@ -266,6 +267,24 @@ __packed struct __iar_u32 { uint32_t v; }; #define __VECTOR_TABLE_ATTRIBUTE @".intvec" #endif +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL STACKSEAL$$Base +#endif + +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif + +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; +} +#endif + #ifndef __ICCARM_INTRINSICS_VERSION__ #define __ICCARM_INTRINSICS_VERSION__ 0 #endif @@ -336,7 +355,13 @@ __packed struct __iar_u32 { uint32_t v; }; #define __set_BASEPRI(VALUE) (__arm_wsr("BASEPRI", (VALUE))) #define __set_BASEPRI_MAX(VALUE) (__arm_wsr("BASEPRI_MAX", (VALUE))) - #define __set_CONTROL(VALUE) (__arm_wsr("CONTROL", (VALUE))) + +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __arm_wsr("CONTROL", control); + __iar_builtin_ISB(); +} + #define __set_FAULTMASK(VALUE) (__arm_wsr("FAULTMASK", (VALUE))) #define __set_MSP(VALUE) (__arm_wsr("MSP", (VALUE))) @@ -358,7 +383,13 @@ __packed struct __iar_u32 { uint32_t v; }; #endif #define __TZ_get_CONTROL_NS() (__arm_rsr("CONTROL_NS")) - #define __TZ_set_CONTROL_NS(VALUE) (__arm_wsr("CONTROL_NS", (VALUE))) + +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __arm_wsr("CONTROL_NS", control); + __iar_builtin_ISB(); +} + #define __TZ_get_PSP_NS() (__arm_rsr("PSP_NS")) #define __TZ_set_PSP_NS(VALUE) (__arm_wsr("PSP_NS", (VALUE))) #define __TZ_get_MSP_NS() (__arm_rsr("MSP_NS")) @@ -680,6 +711,7 @@ __packed struct __iar_u32 { uint32_t v; }; __IAR_FT void __TZ_set_CONTROL_NS(uint32_t value) { __asm volatile("MSR CONTROL_NS,%0" :: "r" (value)); + __iar_builtin_ISB(); } __IAR_FT uint32_t __TZ_get_PSP_NS(void) @@ -965,4 +997,6 @@ __packed struct __iar_u32 { uint32_t v; }; #define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + #endif /* __CMSIS_ICCARM_H__ */ diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_armv81mml.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_armv81mml.h index 1ad19e215ac..33df4554361 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_armv81mml.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_armv81mml.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file core_armv81mml.h * @brief CMSIS Armv8.1-M Mainline Core Peripheral Access Layer Header File - * @version V1.3.1 - * @date 27. March 2020 + * @version V1.4.1 + * @date 04. June 2021 ******************************************************************************/ /* - * Copyright (c) 2018-2020 Arm Limited. All rights reserved. + * Copyright (c) 2018-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -210,14 +210,14 @@ #define __FPU_PRESENT 0U #warning "__FPU_PRESENT not defined in device header file; using default!" #endif - + #if __FPU_PRESENT != 0U #ifndef __FPU_DP #define __FPU_DP 0U #warning "__FPU_DP not defined in device header file; using default!" #endif #endif - + #ifndef __MPU_PRESENT #define __MPU_PRESENT 0U #warning "__MPU_PRESENT not defined in device header file; using default!" @@ -232,7 +232,7 @@ #define __DCACHE_PRESENT 0U #warning "__DCACHE_PRESENT not defined in device header file; using default!" #endif - + #ifndef __PMU_PRESENT #define __PMU_PRESENT 0U #warning "__PMU_PRESENT not defined in device header file; using default!" @@ -261,7 +261,7 @@ #define __VTOR_PRESENT 1U #warning "__VTOR_PRESENT not defined in device header file; using default!" #endif - + #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" @@ -766,22 +766,22 @@ typedef struct #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ -#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ #define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ -#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ -#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ -#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ -#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ @@ -1508,12 +1508,12 @@ typedef struct /** \brief PMU Event Counter Registers (0-30) Definitions */ #define PMU_EVCNTR_CNT_Pos 0U /*!< PMU EVCNTR: Counter Position */ -#define PMU_EVCNTR_CNT_Msk (16UL /*<< PMU_EVCNTRx_CNT_Pos*/) /*!< PMU EVCNTR: Counter Mask */ +#define PMU_EVCNTR_CNT_Msk (0xFFFFUL /*<< PMU_EVCNTRx_CNT_Pos*/) /*!< PMU EVCNTR: Counter Mask */ /** \brief PMU Event Type and Filter Registers (0-30) Definitions */ #define PMU_EVTYPER_EVENTTOCNT_Pos 0U /*!< PMU EVTYPER: Event to Count Position */ -#define PMU_EVTYPER_EVENTTOCNT_Msk (16UL /*<< EVTYPERx_EVENTTOCNT_Pos*/) /*!< PMU EVTYPER: Event to Count Mask */ +#define PMU_EVTYPER_EVENTTOCNT_Msk (0xFFFFUL /*<< EVTYPERx_EVENTTOCNT_Pos*/) /*!< PMU EVTYPER: Event to Count Mask */ /** \brief PMU Count Enable Set Register Definitions */ @@ -2221,10 +2221,10 @@ typedef struct /** \brief PMU Type Register Definitions */ #define PMU_TYPE_NUM_CNTS_Pos 0U /*!< PMU TYPE: Number of Counters Position */ -#define PMU_TYPE_NUM_CNTS_Msk (8UL /*<< PMU_TYPE_NUM_CNTS_Pos*/) /*!< PMU TYPE: Number of Counters Mask */ +#define PMU_TYPE_NUM_CNTS_Msk (0xFFUL /*<< PMU_TYPE_NUM_CNTS_Pos*/) /*!< PMU TYPE: Number of Counters Mask */ #define PMU_TYPE_SIZE_CNTS_Pos 8U /*!< PMU TYPE: Size of Counters Position */ -#define PMU_TYPE_SIZE_CNTS_Msk (6UL << PMU_TYPE_SIZE_CNTS_Pos) /*!< PMU TYPE: Size of Counters Mask */ +#define PMU_TYPE_SIZE_CNTS_Msk (0x3FUL << PMU_TYPE_SIZE_CNTS_Pos) /*!< PMU TYPE: Size of Counters Mask */ #define PMU_TYPE_CYCCNT_PRESENT_Pos 14U /*!< PMU TYPE: Cycle Counter Present Position */ #define PMU_TYPE_CYCCNT_PRESENT_Msk (1UL << PMU_TYPE_CYCCNT_PRESENT_Pos) /*!< PMU TYPE: Cycle Counter Present Mask */ @@ -2235,6 +2235,32 @@ typedef struct #define PMU_TYPE_TRACE_ON_OV_SUPPORT_Pos 23U /*!< PMU TYPE: Trace-on-overflow Support Position */ #define PMU_TYPE_TRACE_ON_OV_SUPPORT_Msk (1UL << PMU_TYPE_FRZ_OV_SUPPORT_Pos) /*!< PMU TYPE: Trace-on-overflow Support Mask */ +/** \brief PMU Authentication Status Register Definitions */ + +#define PMU_AUTHSTATUS_NSID_Pos 0U /*!< PMU AUTHSTATUS: Non-secure Invasive Debug Position */ +#define PMU_AUTHSTATUS_NSID_Msk (0x3UL /*<< PMU_AUTHSTATUS_NSID_Pos*/) /*!< PMU AUTHSTATUS: Non-secure Invasive Debug Mask */ + +#define PMU_AUTHSTATUS_NSNID_Pos 2U /*!< PMU AUTHSTATUS: Non-secure Non-invasive Debug Position */ +#define PMU_AUTHSTATUS_NSNID_Msk (0x3UL << PMU_AUTHSTATUS_NSNID_Pos) /*!< PMU AUTHSTATUS: Non-secure Non-invasive Debug Mask */ + +#define PMU_AUTHSTATUS_SID_Pos 4U /*!< PMU AUTHSTATUS: Secure Invasive Debug Position */ +#define PMU_AUTHSTATUS_SID_Msk (0x3UL << PMU_AUTHSTATUS_SID_Pos) /*!< PMU AUTHSTATUS: Secure Invasive Debug Mask */ + +#define PMU_AUTHSTATUS_SNID_Pos 6U /*!< PMU AUTHSTATUS: Secure Non-invasive Debug Position */ +#define PMU_AUTHSTATUS_SNID_Msk (0x3UL << PMU_AUTHSTATUS_SNID_Pos) /*!< PMU AUTHSTATUS: Secure Non-invasive Debug Mask */ + +#define PMU_AUTHSTATUS_NSUID_Pos 16U /*!< PMU AUTHSTATUS: Non-secure Unprivileged Invasive Debug Position */ +#define PMU_AUTHSTATUS_NSUID_Msk (0x3UL << PMU_AUTHSTATUS_NSUID_Pos) /*!< PMU AUTHSTATUS: Non-secure Unprivileged Invasive Debug Mask */ + +#define PMU_AUTHSTATUS_NSUNID_Pos 18U /*!< PMU AUTHSTATUS: Non-secure Unprivileged Non-invasive Debug Position */ +#define PMU_AUTHSTATUS_NSUNID_Msk (0x3UL << PMU_AUTHSTATUS_NSUNID_Pos) /*!< PMU AUTHSTATUS: Non-secure Unprivileged Non-invasive Debug Mask */ + +#define PMU_AUTHSTATUS_SUID_Pos 20U /*!< PMU AUTHSTATUS: Secure Unprivileged Invasive Debug Position */ +#define PMU_AUTHSTATUS_SUID_Msk (0x3UL << PMU_AUTHSTATUS_SUID_Pos) /*!< PMU AUTHSTATUS: Secure Unprivileged Invasive Debug Mask */ + +#define PMU_AUTHSTATUS_SUNID_Pos 22U /*!< PMU AUTHSTATUS: Secure Unprivileged Non-invasive Debug Position */ +#define PMU_AUTHSTATUS_SUNID_Msk (0x3UL << PMU_AUTHSTATUS_SUNID_Pos) /*!< PMU AUTHSTATUS: Secure Unprivileged Non-invasive Debug Mask */ + /*@} end of group CMSIS_PMU */ #endif diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_armv8mml.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_armv8mml.h index 71f000bcadf..2bd9e76064d 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_armv8mml.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_armv8mml.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file core_armv8mml.h * @brief CMSIS Armv8-M Mainline Core Peripheral Access Layer Header File - * @version V5.2.0 - * @date 27. March 2020 + * @version V5.2.2 + * @date 04. June 2021 ******************************************************************************/ /* - * Copyright (c) 2009-2020 Arm Limited. All rights reserved. + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -254,7 +254,7 @@ #define __VTOR_PRESENT 1U #warning "__VTOR_PRESENT not defined in device header file; using default!" #endif - + #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" @@ -545,6 +545,7 @@ typedef struct __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + __OM uint32_t BPIALL; /*!< Offset: 0x278 ( /W) Branch Predictor Invalidate All */ } SCB_Type; /* SCB CPUID Register Definitions */ @@ -745,22 +746,22 @@ typedef struct #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ -#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ #define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ -#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ -#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ -#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ -#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ @@ -2939,7 +2940,7 @@ __STATIC_INLINE void TZ_SAU_Disable(void) @{ */ - + /** \brief Set Debug Authentication Control Register \details writes to Debug Authentication Control register. @@ -3006,7 +3007,7 @@ __STATIC_INLINE uint32_t TZ_DCB_GetAuthCtrl_NS(void) @{ */ - + /** \brief Get Debug Authentication Status Register \details Reads Debug Authentication Status register. diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm3.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm3.h index 24453a88633..74fb87e5c56 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm3.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm3.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file core_cm3.h * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File - * @version V5.1.1 - * @date 27. March 2020 + * @version V5.1.2 + * @date 04. June 2021 ******************************************************************************/ /* - * Copyright (c) 2009-2020 Arm Limited. All rights reserved. + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -146,7 +146,7 @@ #define __VTOR_PRESENT 1U #warning "__VTOR_PRESENT not defined in device header file; using default!" #endif - + #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" @@ -565,19 +565,19 @@ typedef struct #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ -#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ -#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ -#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ -#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm33.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm33.h index 13359be3ed0..f9cf6ab183a 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm33.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm33.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file core_cm33.h * @brief CMSIS Cortex-M33 Core Peripheral Access Layer Header File - * @version V5.2.0 - * @date 27. March 2020 + * @version V5.2.2 + * @date 04. June 2021 ******************************************************************************/ /* - * Copyright (c) 2009-2020 Arm Limited. All rights reserved. + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -254,7 +254,7 @@ #define __VTOR_PRESENT 1U #warning "__VTOR_PRESENT not defined in device header file; using default!" #endif - + #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" @@ -545,6 +545,7 @@ typedef struct __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + __OM uint32_t BPIALL; /*!< Offset: 0x278 ( /W) Branch Predictor Invalidate All */ } SCB_Type; /* SCB CPUID Register Definitions */ @@ -745,22 +746,22 @@ typedef struct #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ -#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ #define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ -#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ -#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ -#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ -#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ @@ -3007,7 +3008,7 @@ __STATIC_INLINE void TZ_SAU_Disable(void) @{ */ - + /** \brief Set Debug Authentication Control Register \details writes to Debug Authentication Control register. @@ -3074,7 +3075,7 @@ __STATIC_INLINE uint32_t TZ_DCB_GetAuthCtrl_NS(void) @{ */ - + /** \brief Get Debug Authentication Status Register \details Reads Debug Authentication Status register. diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm35p.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm35p.h index 6a5f6ad1471..552c29464de 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm35p.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm35p.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file core_cm35p.h * @brief CMSIS Cortex-M35P Core Peripheral Access Layer Header File - * @version V1.1.0 - * @date 27. March 2020 + * @version V1.1.2 + * @date 04. June 2021 ******************************************************************************/ /* - * Copyright (c) 2018-2020 Arm Limited. All rights reserved. + * Copyright (c) 2018-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -249,12 +249,12 @@ #define __DSP_PRESENT 0U #warning "__DSP_PRESENT not defined in device header file; using default!" #endif - + #ifndef __VTOR_PRESENT #define __VTOR_PRESENT 1U #warning "__VTOR_PRESENT not defined in device header file; using default!" #endif - + #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" @@ -545,6 +545,7 @@ typedef struct __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + __OM uint32_t BPIALL; /*!< Offset: 0x278 ( /W) Branch Predictor Invalidate All */ } SCB_Type; /* SCB CPUID Register Definitions */ @@ -745,22 +746,22 @@ typedef struct #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ -#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ #define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ -#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ -#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ -#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ -#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ @@ -3007,7 +3008,7 @@ __STATIC_INLINE void TZ_SAU_Disable(void) @{ */ - + /** \brief Set Debug Authentication Control Register \details writes to Debug Authentication Control register. @@ -3074,7 +3075,7 @@ __STATIC_INLINE uint32_t TZ_DCB_GetAuthCtrl_NS(void) @{ */ - + /** \brief Get Debug Authentication Status Register \details Reads Debug Authentication Status register. diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm4.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm4.h index 4e0e8866970..e21cd149256 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm4.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm4.h @@ -1,8 +1,8 @@ /**************************************************************************//** * @file core_cm4.h * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File - * @version V5.1.1 - * @date 27. March 2020 + * @version V5.1.2 + * @date 04. June 2021 ******************************************************************************/ /* * Copyright (c) 2009-2020 Arm Limited. All rights reserved. @@ -198,7 +198,7 @@ #define __VTOR_PRESENT 1U #warning "__VTOR_PRESENT not defined in device header file; using default!" #endif - + #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" @@ -623,22 +623,22 @@ typedef struct #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ -#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ #define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ -#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ -#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ -#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ -#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm55.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm55.h index 6efaa3f8429..ecee4e0afb2 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm55.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm55.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file core_cm55.h * @brief CMSIS Cortex-M55 Core Peripheral Access Layer Header File - * @version V1.0.0 - * @date 27. March 2020 + * @version V1.2.1 + * @date 04. June 2021 ******************************************************************************/ /* - * Copyright (c) 2018-2020 Arm Limited. All rights reserved. + * Copyright (c) 2018-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -210,7 +210,7 @@ #define __FPU_PRESENT 0U #warning "__FPU_PRESENT not defined in device header file; using default!" #endif - + #if __FPU_PRESENT != 0U #ifndef __FPU_DP #define __FPU_DP 0U @@ -232,12 +232,12 @@ #define __DCACHE_PRESENT 0U #warning "__DCACHE_PRESENT not defined in device header file; using default!" #endif - + #ifndef __VTOR_PRESENT #define __VTOR_PRESENT 1U #warning "__VTOR_PRESENT not defined in device header file; using default!" #endif - + #ifndef __PMU_PRESENT #define __PMU_PRESENT 0U #warning "__PMU_PRESENT not defined in device header file; using default!" @@ -766,22 +766,22 @@ typedef struct #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ -#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ #define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ -#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ -#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ -#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ -#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ @@ -1349,6 +1349,40 @@ typedef struct /*@}*/ /* end of group CMSIS_DWT */ +/** + \ingroup CMSIS_core_register + \defgroup PwrModCtl_Type Power Mode Control Registers + \brief Type definitions for the Power Mode Control Registers (PWRMODCTL) + @{ + */ + +/** + \brief Structure type to access the Power Mode Control Registers (PWRMODCTL). + */ +typedef struct +{ + __IOM uint32_t CPDLPSTATE; + __IOM uint32_t DPDLPSTATE; +} PwrModCtl_Type; + + +/* PWRMODCTL Core Power Domain Low Power State (CPDLPSTATE) Register Definitions */ +#define PWRMODCTL_CPDLPSTATE_CLPSTATE_Pos 0U /*!< PWRMODCTL CPDLPSTATE CLPSTATE Position */ +#define PWRMODCTL_CPDLPSTATE_CLPSTATE_Msk 3UL /*!< PWRMODCTL CPDLPSTATE CLPSTATE Mask */ + +#define PWRMODCTL_CPDLPSTATE_ELPSTATE_Pos 4U /*!< PWRMODCTL CPDLPSTATE ELPSTATE Position */ +#define PWRMODCTL_CPDLPSTATE_ELPSTATE_Msk 3UL /*!< PWRMODCTL CPDLPSTATE ELPSTATE Mask */ + +#define PWRMODCTL_CPDLPSTATE_RLPSTATE_Pos 8U /*!< PWRMODCTL CPDLPSTATE RLPSTATE Position */ +#define PWRMODCTL_CPDLPSTATE_RLPSTATE_Msk 3UL /*!< PWRMODCTL CPDLPSTATE RLPSTATE Mask */ + +/* PWRMODCTL Debug Power Domain Low Power State (DPDLPSTATE) Register Definitions */ +#define PWRMODCTL_DPDLPSTATE_DLPSTATE_Pos 0U /*!< PWRMODCTL DPDLPSTATE DLPSTATE Position */ +#define PWRMODCTL_DPDLPSTATE_DLPSTATE_Msk 3UL /*!< PWRMODCTL DPDLPSTATE DLPSTATE Mask */ + +/*@}*/ /* end of group CMSIS_PWRMODCTL */ + + /** \ingroup CMSIS_core_register \defgroup CMSIS_TPI Trace Port Interface (TPI) @@ -1508,12 +1542,12 @@ typedef struct /** \brief PMU Event Counter Registers (0-30) Definitions */ #define PMU_EVCNTR_CNT_Pos 0U /*!< PMU EVCNTR: Counter Position */ -#define PMU_EVCNTR_CNT_Msk (16UL /*<< PMU_EVCNTRx_CNT_Pos*/) /*!< PMU EVCNTR: Counter Mask */ +#define PMU_EVCNTR_CNT_Msk (0xFFFFUL /*<< PMU_EVCNTRx_CNT_Pos*/) /*!< PMU EVCNTR: Counter Mask */ /** \brief PMU Event Type and Filter Registers (0-30) Definitions */ #define PMU_EVTYPER_EVENTTOCNT_Pos 0U /*!< PMU EVTYPER: Event to Count Position */ -#define PMU_EVTYPER_EVENTTOCNT_Msk (16UL /*<< EVTYPERx_EVENTTOCNT_Pos*/) /*!< PMU EVTYPER: Event to Count Mask */ +#define PMU_EVTYPER_EVENTTOCNT_Msk (0xFFFFUL /*<< EVTYPERx_EVENTTOCNT_Pos*/) /*!< PMU EVTYPER: Event to Count Mask */ /** \brief PMU Count Enable Set Register Definitions */ @@ -2221,10 +2255,10 @@ typedef struct /** \brief PMU Type Register Definitions */ #define PMU_TYPE_NUM_CNTS_Pos 0U /*!< PMU TYPE: Number of Counters Position */ -#define PMU_TYPE_NUM_CNTS_Msk (8UL /*<< PMU_TYPE_NUM_CNTS_Pos*/) /*!< PMU TYPE: Number of Counters Mask */ +#define PMU_TYPE_NUM_CNTS_Msk (0xFFUL /*<< PMU_TYPE_NUM_CNTS_Pos*/) /*!< PMU TYPE: Number of Counters Mask */ #define PMU_TYPE_SIZE_CNTS_Pos 8U /*!< PMU TYPE: Size of Counters Position */ -#define PMU_TYPE_SIZE_CNTS_Msk (6UL << PMU_TYPE_SIZE_CNTS_Pos) /*!< PMU TYPE: Size of Counters Mask */ +#define PMU_TYPE_SIZE_CNTS_Msk (0x3FUL << PMU_TYPE_SIZE_CNTS_Pos) /*!< PMU TYPE: Size of Counters Mask */ #define PMU_TYPE_CYCCNT_PRESENT_Pos 14U /*!< PMU TYPE: Cycle Counter Present Position */ #define PMU_TYPE_CYCCNT_PRESENT_Msk (1UL << PMU_TYPE_CYCCNT_PRESENT_Pos) /*!< PMU TYPE: Cycle Counter Present Mask */ @@ -2235,6 +2269,33 @@ typedef struct #define PMU_TYPE_TRACE_ON_OV_SUPPORT_Pos 23U /*!< PMU TYPE: Trace-on-overflow Support Position */ #define PMU_TYPE_TRACE_ON_OV_SUPPORT_Msk (1UL << PMU_TYPE_FRZ_OV_SUPPORT_Pos) /*!< PMU TYPE: Trace-on-overflow Support Mask */ +/** \brief PMU Authentication Status Register Definitions */ + +#define PMU_AUTHSTATUS_NSID_Pos 0U /*!< PMU AUTHSTATUS: Non-secure Invasive Debug Position */ +#define PMU_AUTHSTATUS_NSID_Msk (0x3UL /*<< PMU_AUTHSTATUS_NSID_Pos*/) /*!< PMU AUTHSTATUS: Non-secure Invasive Debug Mask */ + +#define PMU_AUTHSTATUS_NSNID_Pos 2U /*!< PMU AUTHSTATUS: Non-secure Non-invasive Debug Position */ +#define PMU_AUTHSTATUS_NSNID_Msk (0x3UL << PMU_AUTHSTATUS_NSNID_Pos) /*!< PMU AUTHSTATUS: Non-secure Non-invasive Debug Mask */ + +#define PMU_AUTHSTATUS_SID_Pos 4U /*!< PMU AUTHSTATUS: Secure Invasive Debug Position */ +#define PMU_AUTHSTATUS_SID_Msk (0x3UL << PMU_AUTHSTATUS_SID_Pos) /*!< PMU AUTHSTATUS: Secure Invasive Debug Mask */ + +#define PMU_AUTHSTATUS_SNID_Pos 6U /*!< PMU AUTHSTATUS: Secure Non-invasive Debug Position */ +#define PMU_AUTHSTATUS_SNID_Msk (0x3UL << PMU_AUTHSTATUS_SNID_Pos) /*!< PMU AUTHSTATUS: Secure Non-invasive Debug Mask */ + +#define PMU_AUTHSTATUS_NSUID_Pos 16U /*!< PMU AUTHSTATUS: Non-secure Unprivileged Invasive Debug Position */ +#define PMU_AUTHSTATUS_NSUID_Msk (0x3UL << PMU_AUTHSTATUS_NSUID_Pos) /*!< PMU AUTHSTATUS: Non-secure Unprivileged Invasive Debug Mask */ + +#define PMU_AUTHSTATUS_NSUNID_Pos 18U /*!< PMU AUTHSTATUS: Non-secure Unprivileged Non-invasive Debug Position */ +#define PMU_AUTHSTATUS_NSUNID_Msk (0x3UL << PMU_AUTHSTATUS_NSUNID_Pos) /*!< PMU AUTHSTATUS: Non-secure Unprivileged Non-invasive Debug Mask */ + +#define PMU_AUTHSTATUS_SUID_Pos 20U /*!< PMU AUTHSTATUS: Secure Unprivileged Invasive Debug Position */ +#define PMU_AUTHSTATUS_SUID_Msk (0x3UL << PMU_AUTHSTATUS_SUID_Pos) /*!< PMU AUTHSTATUS: Secure Unprivileged Invasive Debug Mask */ + +#define PMU_AUTHSTATUS_SUNID_Pos 22U /*!< PMU AUTHSTATUS: Secure Unprivileged Non-invasive Debug Position */ +#define PMU_AUTHSTATUS_SUNID_Msk (0x3UL << PMU_AUTHSTATUS_SUNID_Pos) /*!< PMU AUTHSTATUS: Secure Unprivileged Non-invasive Debug Mask */ + + /*@} end of group CMSIS_PMU */ #endif @@ -3066,6 +3127,7 @@ typedef struct #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define PWRMODCTL_BASE (0xE001E300UL) /*!< Power Mode Control Base Address */ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ #define CoreDebug_BASE (0xE000EDF0UL) /*!< \deprecated Core Debug Base Address */ #define DCB_BASE (0xE000EDF0UL) /*!< DCB Base Address */ @@ -3081,6 +3143,7 @@ typedef struct #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define PWRMODCTL ((PwrModCtl_Type *) PWRMODCTL_BASE ) /*!< Power Mode Control configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< \deprecated Core Debug configuration struct */ #define DCB ((DCB_Type *) DCB_BASE ) /*!< DCB configuration struct */ #define DIB ((DIB_Type *) DIB_BASE ) /*!< DIB configuration struct */ diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm7.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm7.h index e1c31c275dc..010506e9fa4 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm7.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm7.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file core_cm7.h * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File - * @version V5.1.2 - * @date 27. March 2020 + * @version V5.1.6 + * @date 04. June 2021 ******************************************************************************/ /* - * Copyright (c) 2009-2020 Arm Limited. All rights reserved. + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -213,7 +213,7 @@ #define __VTOR_PRESENT 1U #warning "__VTOR_PRESENT not defined in device header file; using default!" #endif - + #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" @@ -501,7 +501,8 @@ typedef struct __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ - uint32_t RESERVED7[6U]; + __OM uint32_t BPIALL; /*!< Offset: 0x278 ( /W) Branch Predictor Invalidate All */ + uint32_t RESERVED7[5U]; __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ @@ -676,22 +677,22 @@ typedef struct #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ -#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ #define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ -#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ -#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ -#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ -#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ @@ -875,21 +876,24 @@ typedef struct #define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ #define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ -#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */ -#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */ +#define SCB_CACR_ECCEN_Pos 1U /*!< \deprecated SCB CACR: ECCEN Position */ +#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< \deprecated SCB CACR: ECCEN Mask */ + +#define SCB_CACR_ECCDIS_Pos 1U /*!< SCB CACR: ECCDIS Position */ +#define SCB_CACR_ECCDIS_Msk (1UL << SCB_CACR_ECCDIS_Pos) /*!< SCB CACR: ECCDIS Mask */ #define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ #define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ /* AHBS Control Register Definitions */ #define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ -#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ +#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBSCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ #define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ -#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ +#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBSCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ #define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ -#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ +#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBSCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ /* Auxiliary Bus Fault Status Register Definitions */ #define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_sc300.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_sc300.h index e8914ba601d..d66621031e0 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_sc300.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_sc300.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file core_sc300.h * @brief CMSIS SC300 Core Peripheral Access Layer Header File - * @version V5.0.9 - * @date 27. March 2020 + * @version V5.0.10 + * @date 04. June 2021 ******************************************************************************/ /* - * Copyright (c) 2009-2020 Arm Limited. All rights reserved. + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -562,19 +562,19 @@ typedef struct #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ -#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ -#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ -#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ -#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/mpu_armv7.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/mpu_armv7.h index 791a8dae65a..d9eedf81a64 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/mpu_armv7.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/mpu_armv7.h @@ -1,8 +1,8 @@ /****************************************************************************** * @file mpu_armv7.h * @brief CMSIS MPU API for Armv7-M MPU - * @version V5.1.1 - * @date 10. February 2020 + * @version V5.1.2 + * @date 25. May 2020 ******************************************************************************/ /* * Copyright (c) 2017-2020 Arm Limited. All rights reserved. @@ -223,7 +223,7 @@ __STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) /** Configure an MPU region. * \param rbar Value for RBAR register. -* \param rsar Value for RSAR register. +* \param rasr Value for RASR register. */ __STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr) { @@ -234,7 +234,7 @@ __STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr) /** Configure the given MPU region. * \param rnr Region number to be configured. * \param rbar Value for RBAR register. -* \param rsar Value for RSAR register. +* \param rasr Value for RASR register. */ __STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr) { @@ -243,7 +243,7 @@ __STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t r MPU->RASR = rasr; } -/** Memcopy with strictly ordered memory access, e.g. for register targets. +/** Memcpy with strictly ordered memory access, e.g. used by code in ARM_MPU_Load(). * \param dst Destination data is copied to. * \param src Source data is copied from. * \param len Amount of data words to be copied. diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/mpu_armv8.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/mpu_armv8.h index ef44ad01df0..3de16efc86a 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/mpu_armv8.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/mpu_armv8.h @@ -1,11 +1,11 @@ /****************************************************************************** * @file mpu_armv8.h * @brief CMSIS MPU API for Armv8-M and Armv8.1-M MPU - * @version V5.1.2 - * @date 10. February 2020 + * @version V5.1.3 + * @date 03. February 2021 ******************************************************************************/ /* - * Copyright (c) 2017-2020 Arm Limited. All rights reserved. + * Copyright (c) 2017-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -281,7 +281,7 @@ __STATIC_INLINE void ARM_MPU_SetRegion_NS(uint32_t rnr, uint32_t rbar, uint32_t } #endif -/** Memcopy with strictly ordered memory access, e.g. for register targets. +/** Memcpy with strictly ordered memory access, e.g. used by code in ARM_MPU_LoadEx() * \param dst Destination data is copied to. * \param src Source data is copied from. * \param len Amount of data words to be copied. diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/pmu_armv8.h b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/pmu_armv8.h index dbd39d20c73..f8f3d8935b8 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/pmu_armv8.h +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/pmu_armv8.h @@ -1,8 +1,8 @@ /****************************************************************************** * @file pmu_armv8.h * @brief CMSIS PMU API for Armv8.1-M PMU - * @version V1.0.0 - * @date 24. March 2020 + * @version V1.0.1 + * @date 15. April 2020 ******************************************************************************/ /* * Copyright (c) 2020 Arm Limited. All rights reserved. @@ -274,7 +274,7 @@ __STATIC_INLINE uint32_t ARM_PMU_Get_CCNTR(void) */ __STATIC_INLINE uint32_t ARM_PMU_Get_EVCNTR(uint32_t num) { - return PMU->EVCNTR[num]; + return PMU_EVCNTR_CNT_Msk & PMU->EVCNTR[num]; } /** diff --git a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Source/mbed_tz_context.c b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Source/mbed_tz_context.c index 917eeaeeced..8e9541f75dc 100644 --- a/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Source/mbed_tz_context.c +++ b/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Source/mbed_tz_context.c @@ -5,7 +5,7 @@ * @date 10. January 2018 ******************************************************************************/ /* - * Copyright (c) 2016-2020 Arm Limited. All rights reserved. + * Copyright (c) 2016-2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -22,8 +22,6 @@ * limitations under the License. */ -#if !FEATURE_TFM - #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) #include "RTE_Components.h" @@ -203,5 +201,3 @@ uint32_t TZ_StoreContext_S (TZ_MemoryId_t id) { return 1U; // Success } #endif - -#endif // !FEATURE_TFM diff --git a/cmsis/CMakeLists.txt b/cmsis/CMakeLists.txt index b2442a67a1b..ecfe69c76a6 100644 --- a/cmsis/CMakeLists.txt +++ b/cmsis/CMakeLists.txt @@ -4,3 +4,6 @@ add_subdirectory(CMSIS_5) add_subdirectory(device) +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING) + add_subdirectory(tests/UNITTESTS/doubles) +endif() diff --git a/cmsis/device/rtos/include/mbed_rtx_conf.h b/cmsis/device/rtos/include/mbed_rtx_conf.h index 1ea84140a02..5ccb3dcf87b 100644 --- a/cmsis/device/rtos/include/mbed_rtx_conf.h +++ b/cmsis/device/rtos/include/mbed_rtx_conf.h @@ -159,6 +159,8 @@ //#define EVR_RTX_MEMORY_POOL_ERROR_DISABLE //#define EVR_RTX_MESSAGE_QUEUE_ERROR_DISABLE +#if !MBED_CONF_RTOS_ENABLE_ALL_RTX_EVENTS + //Following events are NOT used by Mbed-OS, you may enable them if needed for debug purposes #define EVR_RTX_MEMORY_INIT_DISABLE #define EVR_RTX_MEMORY_ALLOC_DISABLE @@ -320,4 +322,6 @@ #define EVR_RTX_MESSAGE_QUEUE_DELETE_DISABLE #define EVR_RTX_MESSAGE_QUEUE_DESTROYED_DISABLE +#endif /* !MBED_CONF_RTOS_ENABLE_ALL_RTX_EVENTS */ + #endif /* MBED_RTX_CONF_H */ diff --git a/cmsis/device/rtos/mbed_lib.json b/cmsis/device/rtos/mbed_lib.json index b1e1a7e0f67..231ee3c0755 100644 --- a/cmsis/device/rtos/mbed_lib.json +++ b/cmsis/device/rtos/mbed_lib.json @@ -57,6 +57,10 @@ "msgqueue-data-size": { "help": "The total memory available for all CMSIS-RTOSv2 object-pool message queues combined", "value": 0 + }, + "enable-all-rtx-events": { + "help": "Enables all of the RTX events which are disabled by default for optimization", + "value": false } }, "macros": ["_RTE_"], diff --git a/cmsis/tests/UNITTESTS/.mbedignore b/cmsis/tests/UNITTESTS/.mbedignore new file mode 100644 index 00000000000..72e8ffc0db8 --- /dev/null +++ b/cmsis/tests/UNITTESTS/.mbedignore @@ -0,0 +1 @@ +* diff --git a/cmsis/tests/UNITTESTS/doubles/CMakeLists.txt b/cmsis/tests/UNITTESTS/doubles/CMakeLists.txt new file mode 100644 index 00000000000..f220a6fdc17 --- /dev/null +++ b/cmsis/tests/UNITTESTS/doubles/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2021 Arm Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +add_library(mbed-headers-cmsis INTERFACE) + +target_include_directories(mbed-headers-cmsis + INTERFACE + . +) diff --git a/UNITTESTS/target_h/cmsis.h b/cmsis/tests/UNITTESTS/doubles/cmsis.h similarity index 100% rename from UNITTESTS/target_h/cmsis.h rename to cmsis/tests/UNITTESTS/doubles/cmsis.h diff --git a/UNITTESTS/target_h/cmsis_compiler.h b/cmsis/tests/UNITTESTS/doubles/cmsis_compiler.h similarity index 100% rename from UNITTESTS/target_h/cmsis_compiler.h rename to cmsis/tests/UNITTESTS/doubles/cmsis_compiler.h diff --git a/UNITTESTS/target_h/cmsis_os.h b/cmsis/tests/UNITTESTS/doubles/cmsis_os.h similarity index 100% rename from UNITTESTS/target_h/cmsis_os.h rename to cmsis/tests/UNITTESTS/doubles/cmsis_os.h diff --git a/UNITTESTS/target_h/cmsis_os2.h b/cmsis/tests/UNITTESTS/doubles/cmsis_os2.h similarity index 100% rename from UNITTESTS/target_h/cmsis_os2.h rename to cmsis/tests/UNITTESTS/doubles/cmsis_os2.h diff --git a/UNITTESTS/target_h/mbed_rtx.h b/cmsis/tests/UNITTESTS/doubles/mbed_rtx.h similarity index 100% rename from UNITTESTS/target_h/mbed_rtx.h rename to cmsis/tests/UNITTESTS/doubles/mbed_rtx.h diff --git a/UNITTESTS/target_h/mbed_rtx_conf.h b/cmsis/tests/UNITTESTS/doubles/mbed_rtx_conf.h similarity index 100% rename from UNITTESTS/target_h/mbed_rtx_conf.h rename to cmsis/tests/UNITTESTS/doubles/mbed_rtx_conf.h diff --git a/UNITTESTS/target_h/rtx_lib.h b/cmsis/tests/UNITTESTS/doubles/rtx_lib.h similarity index 100% rename from UNITTESTS/target_h/rtx_lib.h rename to cmsis/tests/UNITTESTS/doubles/rtx_lib.h diff --git a/UNITTESTS/target_h/rtx_os.h b/cmsis/tests/UNITTESTS/doubles/rtx_os.h similarity index 100% rename from UNITTESTS/target_h/rtx_os.h rename to cmsis/tests/UNITTESTS/doubles/rtx_os.h diff --git a/connectivity/CMakeLists.txt b/connectivity/CMakeLists.txt index 9d75d3b3216..dcf9b48c36d 100644 --- a/connectivity/CMakeLists.txt +++ b/connectivity/CMakeLists.txt @@ -43,4 +43,5 @@ else() add_subdirectory(netsocket) add_subdirectory(mbedtls) add_subdirectory(libraries) + add_subdirectory(FEATURE_BLE) endif() diff --git a/connectivity/FEATURE_BLE/CMakeLists.txt b/connectivity/FEATURE_BLE/CMakeLists.txt index c2e0c02d2df..1e9da9185a7 100644 --- a/connectivity/FEATURE_BLE/CMakeLists.txt +++ b/connectivity/FEATURE_BLE/CMakeLists.txt @@ -1,6 +1,10 @@ # Copyright (c) 2020 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING) + add_subdirectory(tests/UNITTESTS) +endif() + add_subdirectory(libraries) add_subdirectory(source) diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn.c index 766c5170ec7..5bc21901441 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn.c @@ -514,14 +514,16 @@ void lctrFreeConnCtx(lctrConnCtx_t *pCtx) WsfMsgFree(pBuf); } + uint16_t handle = LCTR_GET_CONN_HANDLE(pCtx); + + lmgrPersistCb.sendCompCback(handle, numTxBufs); + /* Cleanup timers. */ WsfTimerStop(&pCtx->tmrSupTimeout); WsfTimerStop(&pCtx->tmrProcRsp); WsfTimerStop(&pCtx->tmrPingTimeout); WsfTimerStop(&pCtx->tmrAuthTimeout); - uint16_t handle = LCTR_GET_CONN_HANDLE(pCtx); - /* VS cleanup. */ if (pLctrVsHdlrs && pLctrVsHdlrs->connCleanup) { diff --git a/connectivity/FEATURE_BLE/source/cordio/TESTS/cordio_hci/driver/main.cpp b/connectivity/FEATURE_BLE/source/cordio/TESTS/cordio_hci/driver/main.cpp index 44b944f525b..d45a82d340e 100644 --- a/connectivity/FEATURE_BLE/source/cordio/TESTS/cordio_hci/driver/main.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/TESTS/cordio_hci/driver/main.cpp @@ -37,8 +37,9 @@ using namespace utest::v1; using mbed::callback; +using namespace std::chrono_literals; -#define INITIALIZATION_TIMEOUT (10 * 1000) +#define INITIALIZATION_TIMEOUT 10000ms static EventQueue event_queue(/* event count */ 10 * EVENTS_EVENT_SIZE); @@ -72,7 +73,7 @@ static void test_stack_initialization() BLE &ble = BLE::Instance(); ble.onEventsToProcess(process_ble_events); ble.init(on_initialization_complete); - event_queue.dispatch(INITIALIZATION_TIMEOUT); + event_queue.dispatch_for(INITIALIZATION_TIMEOUT); // At this point ble is suppose to be initialized; inspect the various state // of the stack. diff --git a/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp index 4a93bc41eec..abe30f20809 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp @@ -26,7 +26,9 @@ #include "source/pal/PalAttClient.h" #include "source/pal/PalSecurityManager.h" #include "source/pal/PalGap.h" +#if BLE_FEATURE_SIGNING #include "source/pal/PalSigningMonitor.h" +#endif //BLE_FEATURE_SIGNING #include "source/pal/PalAttClientToGattClient.h" #include "source/BLEInstanceBaseImpl.h" @@ -283,6 +285,7 @@ PalGattClient &BLEInstanceBase::getPalGattClient() #if BLE_FEATURE_SECURITY ble::impl::SecurityManager &BLEInstanceBase::getSecurityManagerImpl() { +#if BLE_FEATURE_SIGNING // Creation of a proxy monitor to let the security manager register to // the gatt client and gatt server. static struct : ble::PalSigningMonitor { @@ -296,11 +299,14 @@ ble::impl::SecurityManager &BLEInstanceBase::getSecurityManagerImpl() #endif // BLE_FEATURE_GATT_SERVER } } signing_event_monitor; +#endif //BLE_FEATURE_SIGNING static ble::impl::SecurityManager m_instance( ble::impl::PalSecurityManager::get_security_manager(), - getGapImpl(), - signing_event_monitor + getGapImpl() +#if BLE_FEATURE_SIGNING + , signing_event_monitor +#endif //BLE_FEATURE_SIGNING #if BLE_FEATURE_PRIVACY , getPrivateAddressRegistry() #endif //BLE_FEATURE_PRIVACY diff --git a/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.h b/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.h index 9d2289ae6d3..16ad08d4d2d 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.h +++ b/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.h @@ -54,8 +54,9 @@ #endif namespace ble { - +#if BLE_FEATURE_SIGNING class PalSigningMonitor; +#endif //BLE_FEATURE_SIGNING namespace impl { @@ -70,8 +71,9 @@ class BLEInstanceBase final : public ble::BLEInstanceBase { using Timeout = mbed::Timeout; using Timer = mbed::Timer; #endif - +#if BLE_FEATURE_SIGNING friend PalSigningMonitor; +#endif //BLE_FEATURE_SIGNING /** * Construction with an HCI driver. diff --git a/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.cpp index bd28238352d..c770ab932b7 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.cpp @@ -1629,7 +1629,9 @@ GattServer::GattServer() : updatesEnabledCallback(nullptr), updatesDisabledCallback(nullptr), confirmationReceivedCallback(nullptr), +#if BLE_FEATURE_SIGNING _signing_event_handler(nullptr), +#endif //BLE_FEATURE_SIGNING cccds(), cccd_values(), cccd_handles(), @@ -1645,12 +1647,14 @@ GattServer::GattServer() : { } +#if BLE_FEATURE_SIGNING void GattServer::set_signing_event_handler( PalSigningMonitorEventHandler *signing_event_handler ) { _signing_event_handler = signing_event_handler; } +#endif //BLE_FEATURE_SIGNING void GattServer::onDataSent(const DataSentCallback_t &callback) { diff --git a/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.h b/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.h index 73374c50b13..fbef21aa46b 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.h +++ b/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.h @@ -39,7 +39,9 @@ #include "source/BLEInstanceBase.h" #include "source/generic/GattServerEvents.h" +#if BLE_FEATURE_SIGNING #include "source/pal/PalSigningMonitor.h" +#endif //BLE_FEATURE_SIGNING namespace ble { @@ -49,10 +51,16 @@ class PalGenericAccessService; class BLE; namespace impl { -class GattServer : public PalSigningMonitor { +class GattServer +#if BLE_FEATURE_SIGNING + : public PalSigningMonitor +#endif //BLE_FEATURE_SIGNING +{ friend ble::BLE; friend ble::PalAttClient; +#if BLE_FEATURE_SIGNING friend PalSigningMonitor; +#endif //BLE_FEATURE_SIGNING friend PalGenericAccessService; using EventHandler = ble::GattServer::EventHandler; @@ -214,11 +222,11 @@ class GattServer : public PalSigningMonitor { void initialize(); static uint8_t atts_auth_cb(dmConnId_t connId, uint8_t permit, uint16_t handle); - +#if BLE_FEATURE_SIGNING void set_signing_event_handler( PalSigningMonitorEventHandler *signing_event_handler ) override; - +#endif //BLE_FEATURE_SIGNING private: GattServer(); @@ -361,8 +369,9 @@ class GattServer : public PalSigningMonitor { * The registered callback handler for confirmation received events. */ EventCallback_t confirmationReceivedCallback; - +#if BLE_FEATURE_SIGNING PalSigningMonitorEventHandler *_signing_event_handler; +#endif //BLE_FEATURE_SIGNING attsCccSet_t cccds[MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CCCD_COUNT]; uint16_t cccd_values[MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CCCD_COUNT]; diff --git a/connectivity/FEATURE_BLE/source/generic/GattClientImpl.h b/connectivity/FEATURE_BLE/source/generic/GattClientImpl.h index bf13e13e6ec..ee1a3e23dfa 100644 --- a/connectivity/FEATURE_BLE/source/generic/GattClientImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GattClientImpl.h @@ -30,7 +30,9 @@ #include "ble/gatt/CharacteristicDescriptorDiscovery.h" #include "ble/gatt/GattCallbackParamTypes.h" #include "source/pal/PalGattClient.h" +#if BLE_FEATURE_SIGNING #include "source/pal/PalSigningMonitor.h" +#endif //BLE_FEATURE_SIGNING #include "ble/GattClient.h" namespace ble { @@ -40,9 +42,13 @@ class BLEInstanceBase; namespace impl { class GattClient : +#if BLE_FEATURE_SIGNING public PalSigningMonitor, +#endif //BLE_FEATURE_SIGNING public PalGattClientEventHandler { +#if BLE_FEATURE_SIGNING friend PalSigningMonitor; +#endif //BLE_FEATURE_SIGNING friend BLEInstanceBase; public: using EventHandler = ble::GattClient::EventHandler; @@ -163,11 +169,12 @@ class GattClient : /* private implementation follows */ private: +#if BLE_FEATURE_SIGNING /** * @see ble::PalSigningMonitor::set_signing_event_handler */ void set_signing_event_handler(PalSigningMonitorEventHandler *signing_event_handler) override; - +#endif //BLE_FEATURE_SIGNING /** * @see PalGattClient::EventHandler::on_att_mtu_change */ @@ -244,7 +251,9 @@ class GattClient : PalGattClient &_pal_client; ServiceDiscovery::TerminationCallback_t _termination_callback; +#if BLE_FEATURE_SIGNING PalSigningMonitorEventHandler *_signing_event_handler; +#endif // BLE_FEATURE_SIGNING mutable ProcedureControlBlock *control_blocks; bool _is_reseting; diff --git a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp index e999375e22c..630e17741b9 100644 --- a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp @@ -1210,15 +1210,23 @@ ble_error_t SecurityManager::init_database( const char *db_path ) { - tr_info("Initialize database. Path = %s", db_path); + tr_info("Initialize database."); delete _db; #if BLE_SECURITY_DATABASE_FILESYSTEM - FILE* db_file = FileSecurityDb::open_db_file(db_path); + FILE* db_file = nullptr; + if (db_path) { + tr_info("Using filesystem path = %s", db_path); + db_file = FileSecurityDb::open_db_file(db_path); + } if (db_file) { _db = new (std::nothrow) FileSecurityDb(db_file); } else +#else + if (db_path) { + tr_error("Passed in a path for BLE security DB init but BLE_SECURITY_DATABASE_FILESYSTEM is disabled"); + } #endif #if BLE_SECURITY_DATABASE_KVSTORE if (KVStoreSecurityDb::open_db()) { diff --git a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.h b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.h index 22a92f736bb..8f144a755a8 100644 --- a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.h @@ -33,7 +33,9 @@ #include "source/pal/GapTypes.h" #include "source/pal/PalConnectionMonitor.h" +#if BLE_FEATURE_SIGNING #include "source/pal/PalSigningMonitor.h" +#endif //BLE_FEATURE_SIGNING #include "source/pal/PalSecurityManager.h" #include "source/generic/SecurityDb.h" @@ -479,15 +481,19 @@ class SecurityManager : public: SecurityManager( ble::PalSecurityManager &palImpl, - ble::PalConnectionMonitor &connMonitorImpl, - ble::PalSigningMonitor &signingMonitorImpl + ble::PalConnectionMonitor &connMonitorImpl +#if BLE_FEATURE_SIGNING + , ble::PalSigningMonitor &signingMonitorImpl +#endif //BLE_FEATURE_SIGNING #if BLE_FEATURE_PRIVACY , PrivateAddressController &privateAddressController #endif // BLE_FEATURE_PRIVACY ) : eventHandler(nullptr), _pal(palImpl), _connection_monitor(connMonitorImpl), +#if BLE_FEATURE_SIGNING _signing_monitor(signingMonitorImpl), +#endif //BLE_FEATURE_SIGNING _db(nullptr), #if BLE_FEATURE_PRIVACY _private_address_controller(privateAddressController), @@ -681,7 +687,9 @@ class SecurityManager : PalSecurityManager &_pal; PalConnectionMonitor &_connection_monitor; +#if BLE_FEATURE_SIGNING PalSigningMonitor &_signing_monitor; +#endif //BLE_FEATURE_SIGNING SecurityDb *_db; #if BLE_FEATURE_PRIVACY diff --git a/connectivity/FEATURE_BLE/source/pal/PalAttClientToGattClient.cpp b/connectivity/FEATURE_BLE/source/pal/PalAttClientToGattClient.cpp index 6fe57930429..037e7831842 100644 --- a/connectivity/FEATURE_BLE/source/pal/PalAttClientToGattClient.cpp +++ b/connectivity/FEATURE_BLE/source/pal/PalAttClientToGattClient.cpp @@ -184,7 +184,7 @@ ble_error_t PalAttClientToGattClient::write_without_response( ); } - +#if BLE_FEATURE_SIGNING ble_error_t PalAttClientToGattClient::signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, @@ -197,7 +197,7 @@ ble_error_t PalAttClientToGattClient::signed_write_without_response( value ); } - +#endif // BLE_FEATURE_SIGNING ble_error_t PalAttClientToGattClient::write_attribute( connection_handle_t connection_handle, diff --git a/connectivity/FEATURE_BLE/source/pal/PalAttClientToGattClient.h b/connectivity/FEATURE_BLE/source/pal/PalAttClientToGattClient.h index bb843760e67..860f8e3822a 100644 --- a/connectivity/FEATURE_BLE/source/pal/PalAttClientToGattClient.h +++ b/connectivity/FEATURE_BLE/source/pal/PalAttClientToGattClient.h @@ -140,7 +140,7 @@ class PalAttClientToGattClient : public PalGattClient { attribute_handle_t characteristic_value_handle, const Span& value ) override; - +#if BLE_FEATURE_SIGNING /** * @see ble::PalGattClient::signed_write_without_response */ @@ -149,7 +149,7 @@ class PalAttClientToGattClient : public PalGattClient { attribute_handle_t characteristic_value_handle, const Span& value ) override; - +#endif //BLE_FEATURE_SIGNING /** * @see ble::PalGattClient::write_attribute */ diff --git a/connectivity/FEATURE_BLE/source/pal/PalGattClient.h b/connectivity/FEATURE_BLE/source/pal/PalGattClient.h index c9a11d2b60c..677de1d29af 100644 --- a/connectivity/FEATURE_BLE/source/pal/PalGattClient.h +++ b/connectivity/FEATURE_BLE/source/pal/PalGattClient.h @@ -472,7 +472,7 @@ class PalGattClient { attribute_handle_t characteristic_value_handle, const Span& value ) = 0; - +#if BLE_FEATURE_SIGNING /** * Send a Signed Write without Response command to the server. * @@ -494,7 +494,7 @@ class PalGattClient { attribute_handle_t characteristic_value_handle, const Span& value ) = 0; - +#endif //BLE_FEATURE_SIGNING /** * Send a write request to the server. * diff --git a/connectivity/FEATURE_BLE/tests/UNITTESTS/.mbedignore b/connectivity/FEATURE_BLE/tests/UNITTESTS/.mbedignore new file mode 100644 index 00000000000..72e8ffc0db8 --- /dev/null +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/.mbedignore @@ -0,0 +1 @@ +* diff --git a/connectivity/FEATURE_BLE/tests/UNITTESTS/CMakeLists.txt b/connectivity/FEATURE_BLE/tests/UNITTESTS/CMakeLists.txt new file mode 100644 index 00000000000..fa602edaab1 --- /dev/null +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/CMakeLists.txt @@ -0,0 +1,3 @@ +# Copyright (c) 2021 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +add_subdirectory(doubles) diff --git a/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/CMakeLists.txt b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/CMakeLists.txt new file mode 100644 index 00000000000..93a943c9aea --- /dev/null +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2021 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(fakes) + +add_library(mbed-headers-feature-ble INTERFACE) + +target_include_directories(mbed-headers-feature-ble + INTERFACE + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/include + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/include/ble +) diff --git a/UNITTESTS/fakes/ble/BLE.cpp b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/BLE.cpp similarity index 99% rename from UNITTESTS/fakes/ble/BLE.cpp rename to connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/BLE.cpp index 57eb53d52b1..9dbedb14dfb 100644 --- a/UNITTESTS/fakes/ble/BLE.cpp +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/BLE.cpp @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/UNITTESTS/fakes/ble/CMakeLists.txt b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/CMakeLists.txt similarity index 55% rename from UNITTESTS/fakes/ble/CMakeLists.txt rename to connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/CMakeLists.txt index c8fb84935de..aabae2f3f36 100644 --- a/UNITTESTS/fakes/ble/CMakeLists.txt +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/CMakeLists.txt @@ -5,7 +5,7 @@ add_library(mbed-fakes-ble) target_include_directories(mbed-fakes-ble PUBLIC - ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/ + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/include ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/include/ble ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/source @@ -24,18 +24,23 @@ target_sources(mbed-fakes-ble ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/source/GattClient.cpp ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/source/GattServer.cpp ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/source/SecurityManager.cpp - ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/BLE.cpp - ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/source/GattServerImpl_mock.cpp - ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/ble_mocks.h - ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/GapImpl_mock.h - ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/GattClientImpl_mock.h - ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/GattServerImpl_mock.h - ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/SecurityManagerImpl_mock.h + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/BLE.cpp + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/GattServerImpl_mock.cpp + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/ble_mocks.h + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/GapImpl_mock.h + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/GattClientImpl_mock.h + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/GattServerImpl_mock.h + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/SecurityManagerImpl_mock.h +) + +target_link_options(mbed-fakes-ble + PRIVATE + --coverage ) target_link_libraries(mbed-fakes-ble PRIVATE - mbed-headers - mbed-stubs-headers - gcov + mbed-headers-base + mbed-headers-platform + mbed-headers-events ) diff --git a/UNITTESTS/fakes/ble/GapImpl_mock.h b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/GapImpl_mock.h similarity index 99% rename from UNITTESTS/fakes/ble/GapImpl_mock.h rename to connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/GapImpl_mock.h index b59461da140..6ef5aba2267 100644 --- a/UNITTESTS/fakes/ble/GapImpl_mock.h +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/GapImpl_mock.h @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/UNITTESTS/fakes/ble/GattClientImpl_mock.h b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/GattClientImpl_mock.h similarity index 99% rename from UNITTESTS/fakes/ble/GattClientImpl_mock.h rename to connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/GattClientImpl_mock.h index 6150ad1697e..d0221a5dbb9 100644 --- a/UNITTESTS/fakes/ble/GattClientImpl_mock.h +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/GattClientImpl_mock.h @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/UNITTESTS/fakes/ble/GattServerImpl_mock.h b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/GattServerImpl_mock.h similarity index 99% rename from UNITTESTS/fakes/ble/GattServerImpl_mock.h rename to connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/GattServerImpl_mock.h index bfafb524005..527a71fb21c 100644 --- a/UNITTESTS/fakes/ble/GattServerImpl_mock.h +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/GattServerImpl_mock.h @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/UNITTESTS/fakes/ble/SecurityManagerImpl_mock.h b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/SecurityManagerImpl_mock.h similarity index 99% rename from UNITTESTS/fakes/ble/SecurityManagerImpl_mock.h rename to connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/SecurityManagerImpl_mock.h index 014b077596c..d0fd45214a0 100644 --- a/UNITTESTS/fakes/ble/SecurityManagerImpl_mock.h +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/SecurityManagerImpl_mock.h @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/UNITTESTS/fakes/ble/ble_mocks.h b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/ble_mocks.h similarity index 99% rename from UNITTESTS/fakes/ble/ble_mocks.h rename to connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/ble_mocks.h index d92904e1738..2f927a7a092 100644 --- a/UNITTESTS/fakes/ble/ble_mocks.h +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/ble_mocks.h @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/UNITTESTS/fakes/ble/source/GattServerImpl.h b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/GattServerImpl.h similarity index 99% rename from UNITTESTS/fakes/ble/source/GattServerImpl.h rename to connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/GattServerImpl.h index d4b43490d37..6583a33e296 100644 --- a/UNITTESTS/fakes/ble/source/GattServerImpl.h +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/GattServerImpl.h @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/UNITTESTS/fakes/ble/source/GattServerImpl_mock.cpp b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/GattServerImpl_mock.cpp similarity index 99% rename from UNITTESTS/fakes/ble/source/GattServerImpl_mock.cpp rename to connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/GattServerImpl_mock.cpp index baf6d0c8a6f..de6fdf168a3 100644 --- a/UNITTESTS/fakes/ble/source/GattServerImpl_mock.cpp +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/GattServerImpl_mock.cpp @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2021 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/UNITTESTS/fakes/ble/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/generic/GapImpl.h similarity index 99% rename from UNITTESTS/fakes/ble/source/generic/GapImpl.h rename to connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/generic/GapImpl.h index 6cd3bbf41f9..64704ef30d1 100644 --- a/UNITTESTS/fakes/ble/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/generic/GapImpl.h @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/UNITTESTS/fakes/ble/source/generic/GattClientImpl.h b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/generic/GattClientImpl.h similarity index 99% rename from UNITTESTS/fakes/ble/source/generic/GattClientImpl.h rename to connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/generic/GattClientImpl.h index 2795ffeec9e..a0bc5e8b1cd 100644 --- a/UNITTESTS/fakes/ble/source/generic/GattClientImpl.h +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/generic/GattClientImpl.h @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/UNITTESTS/fakes/ble/source/generic/SecurityManagerImpl.h b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/generic/SecurityManagerImpl.h similarity index 99% rename from UNITTESTS/fakes/ble/source/generic/SecurityManagerImpl.h rename to connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/generic/SecurityManagerImpl.h index 7f033f4a1bf..8bc12344406 100644 --- a/UNITTESTS/fakes/ble/source/generic/SecurityManagerImpl.h +++ b/connectivity/FEATURE_BLE/tests/UNITTESTS/doubles/fakes/source/generic/SecurityManagerImpl.h @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -27,7 +27,7 @@ class SecurityManager { SecurityManager(const SecurityManager&) = delete; SecurityManager& operator=(const SecurityManager&) = delete; virtual ~SecurityManager() {}; - + using SecurityIOCapabilities_t = ble::SecurityManager::SecurityIOCapabilities_t; using SecurityMode_t = ble::SecurityManager::SecurityMode_t; using SecurityManagerShutdownCallback_t = ble::SecurityManager::SecurityManagerShutdownCallback_t; diff --git a/connectivity/cellular/CMakeLists.txt b/connectivity/cellular/CMakeLists.txt index d7ce11f90d4..1c87aedf697 100644 --- a/connectivity/cellular/CMakeLists.txt +++ b/connectivity/cellular/CMakeLists.txt @@ -2,7 +2,11 @@ # SPDX-License-Identifier: Apache-2.0 if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING) - add_subdirectory(tests/UNITTESTS) + if(BUILD_GREENTEA_TESTS) + # add greentea test + else() + add_subdirectory(tests/UNITTESTS) + endif() endif() add_subdirectory(source/framework) diff --git a/connectivity/cellular/include/cellular/framework/API/ATHandler.h b/connectivity/cellular/include/cellular/framework/API/ATHandler.h index 6ba6562fbe4..da2a6ea124a 100644 --- a/connectivity/cellular/include/cellular/framework/API/ATHandler.h +++ b/connectivity/cellular/include/cellular/framework/API/ATHandler.h @@ -352,8 +352,9 @@ class ATHandler { * * @param str input buffer to be converted to hex ascii * @param size of the input param str + * @param quote_string if true it will add the double-quote character at beginning and end of string */ - void write_hex_string(const char *str, size_t size); + void write_hex_string(const char *str, size_t size, bool quote_string = true); /** Reads as string and converts result to integer. Supports only non-negative integers. * diff --git a/connectivity/cellular/include/cellular/framework/AT/AT_CellularStack.h b/connectivity/cellular/include/cellular/framework/AT/AT_CellularStack.h index 11308f87cda..8fbb9e5100d 100644 --- a/connectivity/cellular/include/cellular/framework/AT/AT_CellularStack.h +++ b/connectivity/cellular/include/cellular/framework/AT/AT_CellularStack.h @@ -88,6 +88,21 @@ class AT_CellularStack : public NetworkStack { virtual void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data); + + nsapi_size_or_error_t socket_sendto_control(nsapi_socket_t handle, const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) override + { + return NSAPI_ERROR_UNSUPPORTED; + } + + nsapi_size_or_error_t socket_recvfrom_control(nsapi_socket_t handle, SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) override + { + return NSAPI_ERROR_UNSUPPORTED; + } + protected: class CellularSocket { public: diff --git a/connectivity/cellular/source/framework/device/ATHandler.cpp b/connectivity/cellular/source/framework/device/ATHandler.cpp index a3009e70fcd..034d586a142 100644 --- a/connectivity/cellular/source/framework/device/ATHandler.cpp +++ b/connectivity/cellular/source/framework/device/ATHandler.cpp @@ -1551,21 +1551,25 @@ void ATHandler::set_send_delay(uint16_t send_delay) _at_send_delay = std::chrono::duration(send_delay); } -void ATHandler::write_hex_string(const char *str, size_t size) +void ATHandler::write_hex_string(const char *str, size_t size, bool quote_string) { // do common checks before sending subparameter if (check_cmd_send() == false) { return; } - (void) write("\"", 1); + if (quote_string) { + (void) write("\"", 1); + } char hexbuf[2]; for (size_t i = 0; i < size; i++) { hexbuf[0] = hex_values[((str[i]) >> 4) & 0x0F]; hexbuf[1] = hex_values[(str[i]) & 0x0F]; write(hexbuf, 2); } - (void) write("\"", 1); + if (quote_string) { + (void) write("\"", 1); + } } void ATHandler::set_baud(int baud_rate) diff --git a/connectivity/cellular/tests/UNITTESTS/doubles/CMakeLists.txt b/connectivity/cellular/tests/UNITTESTS/doubles/CMakeLists.txt index 8e310cceeef..6cc9c2c0fc9 100644 --- a/connectivity/cellular/tests/UNITTESTS/doubles/CMakeLists.txt +++ b/connectivity/cellular/tests/UNITTESTS/doubles/CMakeLists.txt @@ -49,8 +49,6 @@ target_sources(mbed-stubs-cellular target_link_libraries(mbed-stubs-cellular PRIVATE - mbed-headers-base - mbed-headers-connectivity mbed-stubs-platform mbed-headers-rtos mbed-headers-drivers diff --git a/UNITTESTS/target_h/myCellularContext.h b/connectivity/cellular/tests/UNITTESTS/doubles/myCellularContext.h similarity index 98% rename from UNITTESTS/target_h/myCellularContext.h rename to connectivity/cellular/tests/UNITTESTS/doubles/myCellularContext.h index c7871c4eb90..e463ce22045 100644 --- a/UNITTESTS/target_h/myCellularContext.h +++ b/connectivity/cellular/tests/UNITTESTS/doubles/myCellularContext.h @@ -137,7 +137,8 @@ class myCellularContext : public CellularContext { return true; }; - const char* get_nonip_context_type_str() { + const char *get_nonip_context_type_str() + { return "Non-IP"; } diff --git a/UNITTESTS/target_h/myCellularDevice.h b/connectivity/cellular/tests/UNITTESTS/doubles/myCellularDevice.h similarity index 100% rename from UNITTESTS/target_h/myCellularDevice.h rename to connectivity/cellular/tests/UNITTESTS/doubles/myCellularDevice.h diff --git a/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularcontext/CMakeLists.txt b/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularcontext/CMakeLists.txt index ac50d03653e..d59d064c232 100644 --- a/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularcontext/CMakeLists.txt +++ b/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularcontext/CMakeLists.txt @@ -23,14 +23,20 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-platform + mbed-headers-events + mbed-headers-rtos + mbed-headers-drivers + mbed-headers-hal mbed-headers-netsocket mbed-headers-cellular mbed-headers-filesystem - mbed-stubs + mbed-stubs-platform + mbed-stubs-rtos + mbed-stubs-events + mbed-stubs-drivers mbed-stubs-netsocket mbed-stubs-cellular - mbed-stubs-headers gmock_main ) diff --git a/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellulardevice/CMakeLists.txt b/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellulardevice/CMakeLists.txt index 4fd647c4a2b..eb44678a860 100644 --- a/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellulardevice/CMakeLists.txt +++ b/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellulardevice/CMakeLists.txt @@ -29,14 +29,18 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-platform + mbed-headers-events + mbed-headers-rtos + mbed-headers-drivers + mbed-headers-hal mbed-headers-netsocket mbed-headers-cellular - mbed-stubs mbed-stubs-netsocket mbed-stubs-cellular - mbed-stubs-headers mbed-stubs-rtos + mbed-stubs-platform + mbed-stubs-events gmock_main ) diff --git a/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularinformation/CMakeLists.txt b/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularinformation/CMakeLists.txt index 3379dec8a53..f9d517d7218 100644 --- a/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularinformation/CMakeLists.txt +++ b/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularinformation/CMakeLists.txt @@ -21,13 +21,17 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-platform + mbed-headers-events + mbed-headers-rtos + mbed-headers-drivers + mbed-headers-hal mbed-headers-netsocket mbed-headers-cellular - mbed-stubs mbed-stubs-netsocket mbed-stubs-cellular - mbed-stubs-headers + mbed-stubs-platform + mbed-stubs-events gmock_main ) diff --git a/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularnetwork/CMakeLists.txt b/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularnetwork/CMakeLists.txt index 45488bf9f5b..8ae33840f50 100644 --- a/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularnetwork/CMakeLists.txt +++ b/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularnetwork/CMakeLists.txt @@ -22,13 +22,17 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-platform + mbed-headers-events + mbed-headers-rtos + mbed-headers-drivers + mbed-headers-hal mbed-headers-netsocket mbed-headers-cellular - mbed-stubs mbed-stubs-netsocket mbed-stubs-cellular - mbed-stubs-headers + mbed-stubs-platform + mbed-stubs-events gmock_main ) diff --git a/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularsms/CMakeLists.txt b/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularsms/CMakeLists.txt index d40d85ee03c..806857c5008 100644 --- a/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularsms/CMakeLists.txt +++ b/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularsms/CMakeLists.txt @@ -22,13 +22,17 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-platform + mbed-headers-events + mbed-headers-rtos + mbed-headers-drivers + mbed-headers-hal mbed-headers-netsocket mbed-headers-cellular - mbed-stubs mbed-stubs-netsocket mbed-stubs-cellular - mbed-stubs-headers + mbed-stubs-platform + mbed-stubs-events gmock_main ) diff --git a/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularstack/CMakeLists.txt b/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularstack/CMakeLists.txt index b7c7244f5e8..7051d597dff 100644 --- a/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularstack/CMakeLists.txt +++ b/connectivity/cellular/tests/UNITTESTS/framework/AT/at_cellularstack/CMakeLists.txt @@ -27,13 +27,17 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-platform + mbed-headers-events + mbed-headers-rtos + mbed-headers-drivers + mbed-headers-hal mbed-headers-nanostack-libservice mbed-headers-netsocket mbed-headers-cellular - mbed-stubs mbed-stubs-cellular - mbed-stubs-headers + mbed-stubs-platform + mbed-stubs-events gmock_main ) diff --git a/connectivity/cellular/tests/UNITTESTS/framework/common/list/CMakeLists.txt b/connectivity/cellular/tests/UNITTESTS/framework/common/list/CMakeLists.txt index 59ee4cb238d..04d5ec96917 100644 --- a/connectivity/cellular/tests/UNITTESTS/framework/common/list/CMakeLists.txt +++ b/connectivity/cellular/tests/UNITTESTS/framework/common/list/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME cellular-framework-common-list-unittest) add_executable(${TEST_NAME}) @@ -12,11 +14,8 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers mbed-headers-cellular gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "cellular") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "cellular") diff --git a/connectivity/cellular/tests/UNITTESTS/framework/common/util/CMakeLists.txt b/connectivity/cellular/tests/UNITTESTS/framework/common/util/CMakeLists.txt index 21cbc64bb4c..1272ecd6cf0 100644 --- a/connectivity/cellular/tests/UNITTESTS/framework/common/util/CMakeLists.txt +++ b/connectivity/cellular/tests/UNITTESTS/framework/common/util/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME cellular-framework-common-util-unittest) add_executable(${TEST_NAME}) @@ -13,13 +15,10 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers mbed-headers-netsocket mbed-headers-cellular mbed-stubs-platform gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "cellular") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "cellular") diff --git a/connectivity/cellular/tests/UNITTESTS/framework/device/athandler/CMakeLists.txt b/connectivity/cellular/tests/UNITTESTS/framework/device/athandler/CMakeLists.txt index 1d801efa87b..2f8e40ce47d 100644 --- a/connectivity/cellular/tests/UNITTESTS/framework/device/athandler/CMakeLists.txt +++ b/connectivity/cellular/tests/UNITTESTS/framework/device/athandler/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME cellular-framework-device-athandler-unittest) add_executable(${TEST_NAME}) @@ -24,15 +26,18 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-platform + mbed-headers-events + mbed-headers-rtos + mbed-headers-drivers + mbed-headers-hal mbed-headers-netsocket mbed-headers-cellular - mbed-stubs mbed-stubs-cellular - mbed-stubs-headers + mbed-stubs-platform + mbed-stubs-events + mbed-stubs-drivers gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "cellular") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "cellular") diff --git a/connectivity/cellular/tests/UNITTESTS/framework/device/athandler/athandlertest.cpp b/connectivity/cellular/tests/UNITTESTS/framework/device/athandler/athandlertest.cpp index a48c018c53f..cc01c0fd05b 100644 --- a/connectivity/cellular/tests/UNITTESTS/framework/device/athandler/athandlertest.cpp +++ b/connectivity/cellular/tests/UNITTESTS/framework/device/athandler/athandlertest.cpp @@ -906,6 +906,7 @@ TEST_F(TestATHandler, test_ATHandler_resp_start) filehandle_stub_table = NULL; filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; ATHandler at(&fh1, que, 0, ","); at.resp_start(); @@ -914,6 +915,7 @@ TEST_F(TestATHandler, test_ATHandler_resp_start) char table2[] = "\"2,\"OK\r\n\0"; filehandle_stub_table = table2; filehandle_stub_table_pos = 0; + mbed_poll_stub::int_value = strlen(table2); at.flush(); at.clear_error(); @@ -1052,12 +1054,14 @@ TEST_F(TestATHandler, test_ATHandler_resp_stop) { EventQueue que; FileHandle_stub fh1; + mbed_poll_stub::revents_value = POLLIN; ATHandler at(&fh1, que, 0, ","); char table[] = "21 OK\r\n\0"; filehandle_stub_table = table; filehandle_stub_table_pos = 0; + mbed_poll_stub::int_value = strlen(table); at.info_elem('2'); at.set_stop_tag("OK\r\n"); @@ -1266,6 +1270,7 @@ TEST_F(TestATHandler, test_ATHandler_at_cmd_str) { EventQueue que; FileHandle_stub fh1; + mbed_poll_stub::revents_value = POLLIN; ATHandler at(&fh1, que, 0, ","); uint8_t byte[] = {1, 2, 3, 4}; diff --git a/connectivity/cellular/tests/UNITTESTS/framework/device/cellularcontext/CMakeLists.txt b/connectivity/cellular/tests/UNITTESTS/framework/device/cellularcontext/CMakeLists.txt index 56e3e80aa01..af73d4776c7 100644 --- a/connectivity/cellular/tests/UNITTESTS/framework/device/cellularcontext/CMakeLists.txt +++ b/connectivity/cellular/tests/UNITTESTS/framework/device/cellularcontext/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME cellular-framework-device-cellular-context-unittest) add_executable(${TEST_NAME}) @@ -24,28 +26,24 @@ target_compile_definitions(${TEST_NAME} target_sources(${TEST_NAME} PRIVATE ${mbed-os_SOURCE_DIR}/connectivity/cellular/source/framework/device/CellularContext.cpp - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/ip4tos.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/ip6tos.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/SocketAddress.cpp cellularcontexttest.cpp ) target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-platform + mbed-headers-events + mbed-headers-rtos + mbed-headers-drivers + mbed-headers-hal mbed-headers-nanostack-libservice mbed-headers-netsocket mbed-headers-cellular - mbed-stubs mbed-stubs-cellular mbed-stubs-netsocket - mbed-stubs-headers + mbed-stubs-platform + mbed-stubs-events gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "cellular") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "cellular") diff --git a/connectivity/cellular/tests/UNITTESTS/framework/device/cellulardevice/CMakeLists.txt b/connectivity/cellular/tests/UNITTESTS/framework/device/cellulardevice/CMakeLists.txt index 272e30a1cce..48843591c97 100644 --- a/connectivity/cellular/tests/UNITTESTS/framework/device/cellulardevice/CMakeLists.txt +++ b/connectivity/cellular/tests/UNITTESTS/framework/device/cellulardevice/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME cellular-framework-device-cellular-device-unittest) add_executable(${TEST_NAME}) @@ -27,15 +29,17 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE + mbed-headers-platform + mbed-headers-events + mbed-headers-rtos + mbed-headers-drivers + mbed-headers-hal mbed-headers-netsocket - mbed-headers mbed-headers-cellular - mbed-stubs mbed-stubs-cellular - mbed-stubs-headers + mbed-stubs-platform + mbed-stubs-events gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "cellular") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "cellular") diff --git a/connectivity/cellular/tests/UNITTESTS/framework/device/cellularstatemachine/CMakeLists.txt b/connectivity/cellular/tests/UNITTESTS/framework/device/cellularstatemachine/CMakeLists.txt index 24cdefd4d27..e5e66bdc927 100644 --- a/connectivity/cellular/tests/UNITTESTS/framework/device/cellularstatemachine/CMakeLists.txt +++ b/connectivity/cellular/tests/UNITTESTS/framework/device/cellularstatemachine/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME cellular-framework-device-cellular-state-machine-unittest) add_executable(${TEST_NAME}) @@ -28,15 +30,18 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-platform + mbed-headers-events + mbed-headers-rtos + mbed-headers-drivers + mbed-headers-hal mbed-headers-netsocket mbed-headers-cellular - mbed-stubs mbed-stubs-cellular - mbed-stubs-headers + mbed-stubs-platform + mbed-stubs-events + mbed-stubs-rtos gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "cellular") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "cellular") diff --git a/connectivity/drivers/ble/FEATURE_BLE/COMPONENT_CYW43XXX/CyH4TransportDriver.cpp b/connectivity/drivers/ble/FEATURE_BLE/COMPONENT_CYW43XXX/CyH4TransportDriver.cpp index 148872aa6d3..ee79e18ca70 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/COMPONENT_CYW43XXX/CyH4TransportDriver.cpp +++ b/connectivity/drivers/ble/FEATURE_BLE/COMPONENT_CYW43XXX/CyH4TransportDriver.cpp @@ -29,6 +29,17 @@ #include "rtos/ThisThread.h" #include +// BT settling time after power on +#if !defined (CY_BT_POWER_ON_SETTLING_TIME) + #define CY_BT_POWER_ON_SETTLING_TIME (500ms) +#endif /* !defined (CY_BT_POWER_ON_SETTLING_TIME) */ + +// Power on reset time +#if !defined (CY_BT_POWER_ON_RESET_TIME) + #define CY_BT_POWER_ON_RESET_TIME (1ms) +#endif /* !defined (CY_BT_POWER_ON_RESET_TIME) */ + + namespace ble { namespace vendor { namespace cypress_ble { @@ -44,15 +55,13 @@ CyH4TransportDriver::CyH4TransportDriver(PinName tx, PinName rx, PinName cts, Pi cts(cts), rts(rts), bt_host_wake_name(bt_host_wake_name), bt_device_wake_name(bt_device_wake_name), - bt_power(bt_power_name, PIN_OUTPUT, PullNone, 0), + bt_power(bt_power_name, PIN_OUTPUT, PullUp, 0), bt_host_wake(bt_host_wake_name, PIN_INPUT, PullNone, 0), bt_device_wake(bt_device_wake_name, PIN_OUTPUT, PullNone, 1), host_wake_irq_event(host_wake_irq), dev_wake_irq_event(dev_wake_irq) - { enabled_powersave = true; - bt_host_wake_active = false; } CyH4TransportDriver::CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, PinName bt_power_name, int baud) : @@ -70,20 +79,11 @@ CyH4TransportDriver::CyH4TransportDriver(PinName tx, PinName rx, PinName cts, Pi { enabled_powersave = false; - bt_host_wake_active = false; - - sleep_manager_lock_deep_sleep(); // locking deep sleep because this option - // does not include a host wake pin - holding_deep_sleep_lock = true; } CyH4TransportDriver::~CyH4TransportDriver() { - if (holding_deep_sleep_lock) - { - sleep_manager_unlock_deep_sleep(); - holding_deep_sleep_lock = false; - } + } void CyH4TransportDriver::bt_host_wake_rise_irq_handler(void) @@ -91,12 +91,12 @@ void CyH4TransportDriver::bt_host_wake_rise_irq_handler(void) if (host_wake_irq_event == WAKE_EVENT_ACTIVE_LOW) { if(bt_host_wake_active == true) { - /* lock PSoC 6 DeepSleep entry as long as host_wake is asserted */ + /* lock MCU Deep Sleep entry as long as host_wake is asserted */ sleep_manager_unlock_deep_sleep(); bt_host_wake_active = false; } } else { - /* lock PSoC 6 DeepSleep entry as long as host_wake is asserted */ + /* lock MCU Deep Sleep entry as long as host_wake is asserted */ sleep_manager_lock_deep_sleep(); bt_host_wake_active = true; } @@ -105,13 +105,13 @@ void CyH4TransportDriver::bt_host_wake_rise_irq_handler(void) void CyH4TransportDriver::bt_host_wake_fall_irq_handler(void) { if (host_wake_irq_event == WAKE_EVENT_ACTIVE_LOW) { - /* lock PSoC 6 DeepSleep entry as long as host_wake is asserted */ + /* lock MCU Deep Sleep entry as long as host_wake is asserted */ sleep_manager_lock_deep_sleep(); bt_host_wake_active = true; } else { if(bt_host_wake_active == true) { - /* lock PSoC 6 DeepSleep entry as long as host_wake is asserted */ + /* lock MCU Deep Sleep entry as long as host_wake is asserted */ sleep_manager_unlock_deep_sleep(); bt_host_wake_active = false; } @@ -150,10 +150,23 @@ static void on_controller_irq(void *callback_arg, cyhal_uart_event_t event) void CyH4TransportDriver::initialize() { + // Initial MCU Deep Sleep locking. CyH4TransportDriver has the following MCU Deep Sleep locking + // scenarios: + // a) A BT device or MCU does not support Low Power mode (MBED configuration does not include + // MBED_TICKLESS, DEVICE_SLEEP, DEVICE_LPTICKER or CYCFG_BT_LP_ENABLED features). + // In this case, CyH4TransportDriver locks Deep Sleep in the initialize() function and + // unlocks the terminate() function. + // b) A BT device and MCU support Low Power mode. + // In this case, the control of the unlock/lock of the Deep Sleep + // functionality will be done in bt_host_wake_rise_irq_handler and bt_host_wake_fall_irq_handler + // handlers. Finally, CyH4TransportDriver unlocks the Deep Sleep in terminate() function + // (if it was locked before) by checking the bt_host_wake_active flag. + bt_host_wake_active = true; sleep_manager_lock_deep_sleep(); + // Keep the bt_power line in the low level to ensure that the device resets. bt_power = 0; - rtos::ThisThread::sleep_for(1ms); + rtos::ThisThread::sleep_for(CY_BT_POWER_ON_RESET_TIME); #if defined(CYW43XXX_UNBUFFERED_UART) uart.baud(DEF_BT_BAUD_RATE); @@ -185,7 +198,9 @@ void CyH4TransportDriver::initialize() cyhal_uart_enable_event(&uart, CYHAL_UART_IRQ_RX_NOT_EMPTY, CYHAL_ISR_PRIORITY_DEFAULT, true); #endif + // Power up BT bt_power = 1; + rtos::ThisThread::sleep_for(CY_BT_POWER_ON_SETTLING_TIME); #if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER) if (bt_host_wake_name != NC) { @@ -202,7 +217,6 @@ void CyH4TransportDriver::initialize() if (bt_device_wake_name != NC) bt_device_wake = WAKE_EVENT_ACTIVE_HIGH; } - sleep_manager_unlock_deep_sleep(); } void CyH4TransportDriver::terminate() @@ -229,6 +243,7 @@ void CyH4TransportDriver::terminate() deassert_bt_dev_wake(); + // Power down BT bt_power = 0; //BT_POWER is an output, should not be freed only set inactive #if defined(CYW43XXX_UNBUFFERED_UART) @@ -236,6 +251,13 @@ void CyH4TransportDriver::terminate() #else cyhal_uart_free(&uart); #endif + + // Unlock Deep Sleep if it was locked by CyH4TransportDriver before. + if (bt_host_wake_active == true) + { + sleep_manager_unlock_deep_sleep(); + bt_host_wake_active = false; + } } uint16_t CyH4TransportDriver::write(uint8_t type, uint16_t len, uint8_t *pData) diff --git a/connectivity/drivers/ble/FEATURE_BLE/COMPONENT_CYW43XXX/CyH4TransportDriver.h b/connectivity/drivers/ble/FEATURE_BLE/COMPONENT_CYW43XXX/CyH4TransportDriver.h index 8babd0abec4..e5657b76407 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/COMPONENT_CYW43XXX/CyH4TransportDriver.h +++ b/connectivity/drivers/ble/FEATURE_BLE/COMPONENT_CYW43XXX/CyH4TransportDriver.h @@ -46,9 +46,9 @@ class CyH4TransportDriver : public CordioHCITransportDriver { * Initialize the transport driver. * */ - CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, PinName bt_power_name, int baud, PinName bt_host_wake_name, PinName bt_device_wake_name, - uint8_t host_wake_irq = 0, uint8_t dev_wake_irq = 0); - CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, PinName bt_power_name, int baud); + CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, PinName bt_power_name, int baud, PinName bt_host_wake_name, PinName bt_device_wake_name, + uint8_t host_wake_irq = 0, uint8_t dev_wake_irq = 0); + CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, PinName bt_power_name, int baud); /** * Destructor @@ -123,8 +123,6 @@ class CyH4TransportDriver : public CordioHCITransportDriver { bool enabled_powersave; uint8_t host_wake_irq_event; uint8_t dev_wake_irq_event; - - bool holding_deep_sleep_lock; }; } // namespace cypress diff --git a/connectivity/drivers/ble/FEATURE_BLE/COMPONENT_CYW43XXX/HCIDriver.cpp b/connectivity/drivers/ble/FEATURE_BLE/COMPONENT_CYW43XXX/HCIDriver.cpp index 1e339546e50..ff389c9f815 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/COMPONENT_CYW43XXX/HCIDriver.cpp +++ b/connectivity/drivers/ble/FEATURE_BLE/COMPONENT_CYW43XXX/HCIDriver.cpp @@ -75,16 +75,13 @@ class HCIDriver : public CordioHCIDriver { public: HCIDriver( ble::vendor::cypress_ble::CyH4TransportDriver& transport_driver, - PinName bt_power_name, - bool ps_enabled, - uint8_t host_wake_irq, - uint8_t dev_wake_irq + bool ps_enabled, + uint8_t host_wake_irq, + uint8_t dev_wake_irq ) : CordioHCIDriver(transport_driver), - bt_power_name(bt_power_name), - bt_power(bt_power_name, PIN_OUTPUT, PullUp, 0), - is_powersave_enabled(ps_enabled), - host_wake_irq(host_wake_irq), - dev_wake_irq(dev_wake_irq), + is_powersave_enabled(ps_enabled), + host_wake_irq(host_wake_irq), + dev_wake_irq(dev_wake_irq), service_pack_index(0), service_pack_ptr(0), service_pack_length(0), @@ -101,11 +98,6 @@ class HCIDriver : public CordioHCIDriver { virtual void do_initialize() { - //Prevent PSoC6 to enter deep-sleep till BT initialization is complete - sleep_manager_lock_deep_sleep(); - rtos::ThisThread::sleep_for(500ms); - bt_power = 1; - rtos::ThisThread::sleep_for(500ms); } virtual void do_terminate() { } @@ -175,7 +167,6 @@ class HCIDriver : public CordioHCIDriver { // Note: Reset is handled by ack_service_pack. case HCI_VS_CMD_SET_SLEEP_MODE: HciWriteLeHostSupport(); - sleep_manager_unlock_deep_sleep(); break; case HCI_OPCODE_WRITE_LE_HOST_SUPPORT: @@ -387,6 +378,16 @@ class HCIDriver : public CordioHCIDriver { #endif /* BT_UART_NO_3M_SUPPORT */ } + void inject_bdaddr(uint8_t* pBuf) + { + if (service_pack_ptr + service_pack_index == brcm_patchram_buf) { + uint8_t bdAddr[6] = { 0xFF, 0xFF, 0xFF, 0x0A, 0x61, 0xA8 }; + uint32_t uniqueId = HAL_GetUIDw0() ^ HAL_GetUIDw1() ^ HAL_GetUIDw2(); + memcpy(bdAddr, &uniqueId, 3); + memcpy(&pBuf[33], bdAddr, sizeof(bdAddr)); + } + } + void send_service_pack_command(void) { uint16_t cmd_len = service_pack_ptr[service_pack_index + 2]; @@ -394,6 +395,7 @@ class HCIDriver : public CordioHCIDriver { uint8_t *pBuf = hciCmdAlloc(cmd_opcode, cmd_len); if (pBuf) { memcpy(pBuf + HCI_CMD_HDR_LEN, service_pack_ptr + service_pack_index + HCI_CMD_HDR_LEN, cmd_len); + inject_bdaddr(pBuf); hciCmdSend(pBuf); } else { } @@ -422,68 +424,68 @@ class HCIDriver : public CordioHCIDriver { void set_sleep_mode() { - uint8_t *pBuf; - if ((pBuf = hciCmdAlloc(HCI_VS_CMD_SET_SLEEP_MODE, 12)) != NULL) - { - if (is_powersave_on()) { - pBuf[HCI_CMD_HDR_LEN] = 0x01; // sleep - } else { - pBuf[HCI_CMD_HDR_LEN] = 0x00; // no sleep - } - pBuf[HCI_CMD_HDR_LEN + 1] = 0x00; // no idle threshold host (N/A) - if (is_powersave_on()) { - pBuf[HCI_CMD_HDR_LEN + 2] = 0x05; // no idle threshold HC (N/A) - } else { - pBuf[HCI_CMD_HDR_LEN + 2] = 0x00; // no idle threshold HC (N/A) - } - if (is_powersave_on()) { - pBuf[HCI_CMD_HDR_LEN + 3] = dev_wake_irq; // BT WAKE - } else { - pBuf[HCI_CMD_HDR_LEN + 3] = 0x00; // BT WAKE - } - if (is_powersave_on()) { - pBuf[HCI_CMD_HDR_LEN + 4] = host_wake_irq; // HOST WAKE - } else { - pBuf[HCI_CMD_HDR_LEN + 4] = 0x00; // HOST WAKE - } - pBuf[HCI_CMD_HDR_LEN + 5] = 0x00; // Sleep during SCO - pBuf[HCI_CMD_HDR_LEN + 6] = 0x00; // Combining sleep mode and SCM - pBuf[HCI_CMD_HDR_LEN + 7] = 0x00; // Tristate TX - pBuf[HCI_CMD_HDR_LEN + 8] = 0x00; // Active connection handling on suspend - pBuf[HCI_CMD_HDR_LEN + 9] = 0x00; // resume timeout - pBuf[HCI_CMD_HDR_LEN + 10] = 0x00; // break to host - pBuf[HCI_CMD_HDR_LEN + 11] = 0x00; // Pulsed host wake - hciCmdSend(pBuf); + uint8_t *pBuf; + if ((pBuf = hciCmdAlloc(HCI_VS_CMD_SET_SLEEP_MODE, 12)) != NULL) + { + if (is_powersave_on()) { + pBuf[HCI_CMD_HDR_LEN] = 0x01; // sleep + } else { + pBuf[HCI_CMD_HDR_LEN] = 0x00; // no sleep } + pBuf[HCI_CMD_HDR_LEN + 1] = 0x00; // no idle threshold host (N/A) + if (is_powersave_on()) { + pBuf[HCI_CMD_HDR_LEN + 2] = 0x05; // no idle threshold HC (N/A) + } else { + pBuf[HCI_CMD_HDR_LEN + 2] = 0x00; // no idle threshold HC (N/A) + } + if (is_powersave_on()) { + pBuf[HCI_CMD_HDR_LEN + 3] = dev_wake_irq; // BT WAKE + } else { + pBuf[HCI_CMD_HDR_LEN + 3] = 0x00; // no BT WAKE + } + if (is_powersave_on()) { + pBuf[HCI_CMD_HDR_LEN + 4] = host_wake_irq; // HOST WAKE + } else { + pBuf[HCI_CMD_HDR_LEN + 4] = 0x00; // no HOST WAKE + } + pBuf[HCI_CMD_HDR_LEN + 5] = 0x00; // Sleep during SCO + pBuf[HCI_CMD_HDR_LEN + 6] = 0x00; // Combining sleep mode and SCM + pBuf[HCI_CMD_HDR_LEN + 7] = 0x00; // Tristate TX + pBuf[HCI_CMD_HDR_LEN + 8] = 0x00; // Active connection handling on suspend + pBuf[HCI_CMD_HDR_LEN + 9] = 0x00; // resume timeout + pBuf[HCI_CMD_HDR_LEN + 10] = 0x00; // break to host + pBuf[HCI_CMD_HDR_LEN + 11] = 0x00; // Pulsed host wake + hciCmdSend(pBuf); + } } // 0x18, 0xFC, 0x06, 0x00, 0x00, 0xC0, 0xC6, 0x2D, 0x00, //update uart baudrate 3 mbp void HciUpdateUartBaudRate() { - uint8_t *pBuf; - if ((pBuf = hciCmdAlloc(HCI_VS_CMD_UPDATE_UART_BAUD_RATE, 6)) != NULL) - { - pBuf[HCI_CMD_HDR_LEN] = 0x00; // encoded_baud_rate - pBuf[HCI_CMD_HDR_LEN + 1] = 0x00; // use_encoded_form - pBuf[HCI_CMD_HDR_LEN + 2] = 0xC0; // explicit baud rate bit 0-7 - pBuf[HCI_CMD_HDR_LEN + 3] = 0xC6; // explicit baud rate bit 8-15 - pBuf[HCI_CMD_HDR_LEN + 4] = 0x2D; // explicit baud rate bit 16-23 - pBuf[HCI_CMD_HDR_LEN + 5] = 0x00; // explicit baud rate bit 24-31 - hciCmdSend(pBuf); - } + uint8_t *pBuf; + if ((pBuf = hciCmdAlloc(HCI_VS_CMD_UPDATE_UART_BAUD_RATE, 6)) != NULL) + { + pBuf[HCI_CMD_HDR_LEN] = 0x00; // encoded_baud_rate + pBuf[HCI_CMD_HDR_LEN + 1] = 0x00; // use_encoded_form + pBuf[HCI_CMD_HDR_LEN + 2] = 0xC0; // explicit baud rate bit 0-7 + pBuf[HCI_CMD_HDR_LEN + 3] = 0xC6; // explicit baud rate bit 8-15 + pBuf[HCI_CMD_HDR_LEN + 4] = 0x2D; // explicit baud rate bit 16-23 + pBuf[HCI_CMD_HDR_LEN + 5] = 0x00; // explicit baud rate bit 24-31 + hciCmdSend(pBuf); + } } static const uint16_t HCI_OPCODE_WRITE_LE_HOST_SUPPORT = 0x0C6D; void HciWriteLeHostSupport() { - uint8_t *pBuf; - if ((pBuf = hciCmdAlloc(HCI_OPCODE_WRITE_LE_HOST_SUPPORT, 2)) != NULL) - { - pBuf[HCI_CMD_HDR_LEN] = 0x01; - pBuf[HCI_CMD_HDR_LEN + 1] = 0x00; - hciCmdSend(pBuf); - } + uint8_t *pBuf; + if ((pBuf = hciCmdAlloc(HCI_OPCODE_WRITE_LE_HOST_SUPPORT, 2)) != NULL) + { + pBuf[HCI_CMD_HDR_LEN] = 0x01; + pBuf[HCI_CMD_HDR_LEN + 1] = 0x00; + hciCmdSend(pBuf); + } } void hciCoreReadResolvingListSize(void) @@ -506,7 +508,7 @@ class HCIDriver : public CordioHCIDriver { void hciCoreReadMaxDataLen(void) { - /* if LE Data Packet Length Extensions is supported by Controller and included */ + /* if LE Data Packet Length Extensions is supported by Controller and included */ if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_DATA_LEN_EXT) && (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_DATA_LEN_EXT)) { @@ -525,9 +527,6 @@ class HCIDriver : public CordioHCIDriver { return (is_powersave_enabled); } - PinName bt_power_name; - mbed::DigitalInOut bt_power; - bool is_powersave_enabled; uint8_t host_wake_irq; uint8_t dev_wake_irq; @@ -549,12 +548,12 @@ ble::CordioHCIDriver& ble_cordio_get_hci_driver() { static ble::vendor::cypress_ble::CyH4TransportDriver& transport_driver = ble_cordio_get_h4_transport_driver(); + static ble::vendor::cypress::HCIDriver hci_driver( transport_driver, - /* bt_power */ CYBSP_BT_POWER, - transport_driver.get_enabled_powersave(), - transport_driver.get_host_wake_irq_event(), - transport_driver.get_dev_wake_irq_event() + transport_driver.get_enabled_powersave(), + transport_driver.get_host_wake_irq_event(), + transport_driver.get_dev_wake_irq_event() ); return hci_driver; } diff --git a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/mbed_lib.json b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/mbed_lib.json index 05e5a45eee8..3a3d85128d8 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/mbed_lib.json +++ b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/mbed_lib.json @@ -8,7 +8,7 @@ }, "hci-driver-buffer-size": { "help": "Defines the memory to be allocated by the NRFCordiHciDriver.", - "value": 12500 + "value": 13000 }, "wsf-pool-buffer-size": { "help": "Defines the memory allocated for the wsf memory pool.", diff --git a/connectivity/drivers/cellular/QUECTEL/BC95/QUECTEL_BC95_CellularStack.cpp b/connectivity/drivers/cellular/QUECTEL/BC95/QUECTEL_BC95_CellularStack.cpp index 1c92fe36e86..12499a6b0d2 100644 --- a/connectivity/drivers/cellular/QUECTEL/BC95/QUECTEL_BC95_CellularStack.cpp +++ b/connectivity/drivers/cellular/QUECTEL/BC95/QUECTEL_BC95_CellularStack.cpp @@ -211,7 +211,7 @@ nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_sendto_impl(CellularSoc return NSAPI_ERROR_PARAMETER; } - _at.write_hex_string((char *)data, size); + _at.write_hex_string((char *)data, size, false); _at.cmd_stop(); _at.resp_start(); // skip socket id diff --git a/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp b/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp index bc71cb26a2f..090cb328550 100644 --- a/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp +++ b/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp @@ -370,10 +370,6 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address, const void *data, nsapi_size_t size) { - if (size > BG96_MAX_SEND_SIZE) { - return NSAPI_ERROR_PARAMETER; - } - if (_ip_ver_sendto != address.get_ip_version()) { _ip_ver_sendto = address.get_ip_version(); socket_close_impl(socket->id); @@ -393,29 +389,59 @@ nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_sendto_impl(CellularSoc // Send if (socket->proto == NSAPI_UDP) { + if (size > BG96_MAX_SEND_SIZE) { + return NSAPI_ERROR_PARAMETER; + } char ipdot[NSAPI_IP_SIZE]; ip2dot(address, ipdot); _at.cmd_start_stop("+QISEND", "=", "%d%d%s%d", socket->id, size, ipdot, address.get_port()); - } else { - if (socket->tls_socket) { - _at.cmd_start_stop("+QSSLSEND", "=", "%d%d", socket->id, size); - } else { - _at.cmd_start_stop("+QISEND", "=", "%d%d", socket->id, size); + _at.resp_start(">"); + _at.write_bytes((uint8_t *)data, size); + _at.resp_start(); + _at.set_stop_tag("\r\n"); + // Possible responses are SEND OK, SEND FAIL or ERROR. + char response[16]; + response[0] = '\0'; + _at.read_string(response, sizeof(response)); + _at.resp_stop(); + if (strcmp(response, "SEND OK") != 0) { + return NSAPI_ERROR_DEVICE_ERROR; } - } + } else { + const char *buf = (const char *)data; + nsapi_size_t blk = BG96_MAX_SEND_SIZE; + nsapi_size_t count = size; - _at.resp_start(">"); - _at.write_bytes((uint8_t *)data, size); - _at.resp_start(); - _at.set_stop_tag("\r\n"); - // Possible responses are SEND OK, SEND FAIL or ERROR. - char response[16]; - response[0] = '\0'; - _at.read_string(response, sizeof(response)); - _at.resp_stop(); - if (strcmp(response, "SEND OK") != 0) { - return NSAPI_ERROR_DEVICE_ERROR; + while (count > 0) { + if (count < blk) { + blk = count; + } + + if (socket->tls_socket) { + _at.cmd_start_stop("+QSSLSEND", "=", "%d%d", socket->id, blk); + } + + else { + _at.cmd_start_stop("+QISEND", "=", "%d%d", socket->id, blk); + } + + _at.resp_start(">"); + _at.write_bytes((uint8_t *)buf, blk); + _at.resp_start(); + _at.set_stop_tag("\r\n"); + // Possible responses are SEND OK, SEND FAIL or ERROR. + char response[16]; + response[0] = '\0'; + _at.read_string(response, sizeof(response)); + _at.resp_stop(); + if (strcmp(response, "SEND OK") != 0) { + return NSAPI_ERROR_DEVICE_ERROR; + } + + buf += blk; + count -= blk; + } } // Get the sent count after sending diff --git a/connectivity/drivers/emac/TARGET_STM/CMakeLists.txt b/connectivity/drivers/emac/TARGET_STM/CMakeLists.txt index c7bd8eb88c7..354c246f016 100644 --- a/connectivity/drivers/emac/TARGET_STM/CMakeLists.txt +++ b/connectivity/drivers/emac/TARGET_STM/CMakeLists.txt @@ -19,4 +19,5 @@ target_include_directories(mbed-emac target_sources(mbed-emac INTERFACE stm32xx_emac.cpp + stm32xx_eth_irq_callback.cpp ) diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c index b0a2aec66e3..28836e03b8d 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c @@ -29,6 +29,7 @@ #ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT #include "stm32f7xx_hal.h" +#include "platform/mbed_critical.h" /** * Override HAL Eth Init function @@ -38,7 +39,9 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) GPIO_InitTypeDef GPIO_InitStructure; if (heth->Instance == ETH) { /* Disable DCache for STM32F7 family */ + core_util_critical_section_enter(); SCB_DisableDCache(); + core_util_critical_section_exit(); /* Enable GPIOs clocks */ __HAL_RCC_GPIOA_CLK_ENABLE(); diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F769NI/stm32f7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F769NI/stm32f7_eth_init.c index de6494121fc..d798504c34c 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F769NI/stm32f7_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F769NI/stm32f7_eth_init.c @@ -29,6 +29,7 @@ #ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT #include "stm32f7xx_hal.h" +#include "platform/mbed_critical.h" /** * Override HAL Eth Init function @@ -38,7 +39,9 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) GPIO_InitTypeDef GPIO_InitStructure; if (heth->Instance == ETH) { /* Disable DCache for STM32F7 family */ + core_util_critical_section_enter(); SCB_DisableDCache(); + core_util_critical_section_exit(); /* Enable GPIOs clocks */ __HAL_RCC_GPIOA_CLK_ENABLE(); diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F746ZG/stm32f7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F746ZG/stm32f7_eth_init.c index 019898b9f7b..404d9080169 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F746ZG/stm32f7_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F746ZG/stm32f7_eth_init.c @@ -29,6 +29,7 @@ #ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT #include "stm32f7xx_hal.h" +#include "platform/mbed_critical.h" /** * Override HAL Eth Init function @@ -38,7 +39,9 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) GPIO_InitTypeDef GPIO_InitStructure; if (heth->Instance == ETH) { /* Disable DCache for STM32F7 family */ + core_util_critical_section_enter(); SCB_DisableDCache(); + core_util_critical_section_exit(); /* Enable GPIOs clocks */ __HAL_RCC_GPIOA_CLK_ENABLE(); diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/stm32f7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/stm32f7_eth_init.c index 019898b9f7b..404d9080169 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/stm32f7_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/stm32f7_eth_init.c @@ -29,6 +29,7 @@ #ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT #include "stm32f7xx_hal.h" +#include "platform/mbed_critical.h" /** * Override HAL Eth Init function @@ -38,7 +39,9 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) GPIO_InitTypeDef GPIO_InitStructure; if (heth->Instance == ETH) { /* Disable DCache for STM32F7 family */ + core_util_critical_section_enter(); SCB_DisableDCache(); + core_util_critical_section_exit(); /* Enable GPIOs clocks */ __HAL_RCC_GPIOA_CLK_ENABLE(); diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F767ZI/stm32f7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F767ZI/stm32f7_eth_init.c index 019898b9f7b..404d9080169 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F767ZI/stm32f7_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F767ZI/stm32f7_eth_init.c @@ -29,6 +29,7 @@ #ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT #include "stm32f7xx_hal.h" +#include "platform/mbed_critical.h" /** * Override HAL Eth Init function @@ -38,7 +39,9 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) GPIO_InitTypeDef GPIO_InitStructure; if (heth->Instance == ETH) { /* Disable DCache for STM32F7 family */ + core_util_critical_section_enter(); SCB_DisableDCache(); + core_util_critical_section_exit(); /* Enable GPIOs clocks */ __HAL_RCC_GPIOA_CLK_ENABLE(); diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_DISCO_H747I/stm32h7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_DISCO_H747I/stm32h7_eth_init.c index 5255724adc0..79af6dd486e 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_DISCO_H747I/stm32h7_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_DISCO_H747I/stm32h7_eth_init.c @@ -36,6 +36,7 @@ #ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT #include "stm32h7xx_hal.h" +#include "platform/mbed_critical.h" #define ETH_TX_EN_Pin GPIO_PIN_11 #define ETH_TX_EN_GPIO_Port GPIOG @@ -66,7 +67,9 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) if (heth->Instance == ETH) { #if defined(CORE_CM7) /* Disable DCache for STM32H7 family */ + core_util_critical_section_enter(); SCB_DisableDCache(); + core_util_critical_section_exit(); #endif /* GPIO Ports Clock Enable */ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI/stm32h7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI/stm32h7_eth_init.c index 8c71ec7738f..0690d7bf67a 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI/stm32h7_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI/stm32h7_eth_init.c @@ -29,6 +29,7 @@ #ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT #include "stm32h7xx_hal.h" +#include "platform/mbed_critical.h" #define MCO_Pin GPIO_PIN_0 #define MCO_GPIO_Port GPIOH @@ -63,7 +64,9 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) GPIO_InitTypeDef GPIO_InitStruct; if (heth->Instance == ETH) { /* Disable DCache for STM32H7 family */ + core_util_critical_section_enter(); SCB_DisableDCache(); + core_util_critical_section_exit(); /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOH_CLK_ENABLE(); diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI2/stm32h7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI2/stm32h7_eth_init.c index 8c71ec7738f..0690d7bf67a 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI2/stm32h7_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI2/stm32h7_eth_init.c @@ -29,6 +29,7 @@ #ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT #include "stm32h7xx_hal.h" +#include "platform/mbed_critical.h" #define MCO_Pin GPIO_PIN_0 #define MCO_GPIO_Port GPIOH @@ -63,7 +64,9 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) GPIO_InitTypeDef GPIO_InitStruct; if (heth->Instance == ETH) { /* Disable DCache for STM32H7 family */ + core_util_critical_section_enter(); SCB_DisableDCache(); + core_util_critical_section_exit(); /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOH_CLK_ENABLE(); diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_PORTENTA_H7/stm32h7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_PORTENTA_H7/stm32h7_eth_init.c index 2adb1a9b99f..3fbac0555f1 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_PORTENTA_H7/stm32h7_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_PORTENTA_H7/stm32h7_eth_init.c @@ -35,6 +35,7 @@ #include "stm32h7xx_hal.h" #include "portenta_power.h" +#include "platform/mbed_critical.h" #define ETH_TX_EN_Pin GPIO_PIN_11 #define ETH_TX_EN_GPIO_Port GPIOG @@ -66,7 +67,9 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) #if !(defined(DUAL_CORE) && defined(CORE_CM4)) /* Disable DCache for STM32H7 family */ + core_util_critical_section_enter(); SCB_DisableDCache(); + core_util_critical_section_exit(); #endif /* GPIO Ports Clock Enable */ diff --git a/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.cpp b/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.cpp index 827c58f5db1..0230a90665c 100644 --- a/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.cpp +++ b/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.cpp @@ -144,8 +144,8 @@ extern "C" { #endif void _eth_config_mac(ETH_HandleTypeDef *heth); -void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth); void ETH_IRQHandler(void); +MBED_WEAK void STM_HAL_ETH_Handler(ETH_HandleTypeDef *heth); #ifdef __cplusplus } @@ -242,20 +242,14 @@ static void MPU_Config(void) #endif - - /** - * Ethernet Rx Transfer completed callback + * IRQ Handler * * @param heth: ETH handle * @retval None */ -void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) +MBED_WEAK void STM_HAL_ETH_Handler() { - STM32_EMAC &emac = STM32_EMAC::get_instance(); - if (emac.thread) { - osThreadFlagsSet(emac.thread, FLAG_RX); - } } /** @@ -266,8 +260,7 @@ void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) */ void ETH_IRQHandler(void) { - STM32_EMAC &emac = STM32_EMAC::get_instance(); - HAL_ETH_IRQHandler(&emac.EthHandle); + STM_HAL_ETH_Handler(); } STM32_EMAC::STM32_EMAC() diff --git a/connectivity/drivers/emac/TARGET_STM/stm32xx_eth_irq_callback.cpp b/connectivity/drivers/emac/TARGET_STM/stm32xx_eth_irq_callback.cpp new file mode 100644 index 00000000000..cfe7782a682 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/stm32xx_eth_irq_callback.cpp @@ -0,0 +1,51 @@ +/* Copyright (c) 2017-2019 ARM Limited + * Copyright (c) 2017-2019 STMicroelectronics + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef USE_USER_DEFINED_HAL_ETH_IRQ_CALLBACK + +#if DEVICE_EMAC + +#include "stm32xx_emac.h" +#define FLAG_RX 1 + +/** + * Override Ethernet Rx Transfer completed callback + * @param heth: ETH handle + * @retval None + */ +void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) +{ + STM32_EMAC &emac = STM32_EMAC::get_instance(); + if (emac.thread) { + osThreadFlagsSet(emac.thread, FLAG_RX); + } +} + +/** + * Override the IRQ Handler + * @param None + * @retval None + */ +void STM_HAL_ETH_Handler() +{ + STM32_EMAC &emac = STM32_EMAC::get_instance(); + HAL_ETH_IRQHandler(&emac.EthHandle); +} + +#endif /* DEVICE_EMAC */ + +#endif /* USE_USER_DEFINED_HAL_ETH_IRQ_CALLBACK */ diff --git a/connectivity/drivers/lora/COMPONENT_SX126X/SX126X_LoRaRadio.cpp b/connectivity/drivers/lora/COMPONENT_SX126X/SX126X_LoRaRadio.cpp index 041761c2196..5c3b29f32ad 100644 --- a/connectivity/drivers/lora/COMPONENT_SX126X/SX126X_LoRaRadio.cpp +++ b/connectivity/drivers/lora/COMPONENT_SX126X/SX126X_LoRaRadio.cpp @@ -431,7 +431,11 @@ void SX126X_LoRaRadio::cold_start_wakeup() write_opmode_command(RADIO_SET_REGULATORMODE, ®ulator_mode, 1); set_buffer_base_addr(0x00, 0x00); +#if MBED_CONF_SX126X_LORA_DRIVER_XTAL == -1 if (_crystal_select.is_connected() && _crystal_select == 0) { +#else + if (MBED_CONF_SX126X_LORA_DRIVER_XTAL == 0) { +#endif caliberation_params_t calib_param; set_dio3_as_tcxo_ctrl(TCXO_CTRL_1_7V, 320); //5 ms calib_param.value = 0x7F; @@ -692,6 +696,7 @@ void SX126X_LoRaRadio::read_fifo(uint8_t *buffer, uint8_t size, uint8_t offset) uint8_t SX126X_LoRaRadio::get_device_variant(void) { +#if MBED_CONF_SX126X_LORA_DRIVER_DEVICE_VARIANT == -1 uint16_t val = 0; val = _dev_select.read_u16(); @@ -702,10 +707,14 @@ uint8_t SX126X_LoRaRadio::get_device_variant(void) } else { return SX1261; } +#else + return MBED_CONF_SX126X_LORA_DRIVER_DEVICE_VARIANT; +#endif } uint8_t SX126X_LoRaRadio::get_frequency_support(void) { +#if MBED_CONF_SX126X_LORA_DRIVER_FREQ_SUPPORT == -1 uint16_t val = 0; val = _freq_select.read_u16(); @@ -724,6 +733,9 @@ uint8_t SX126X_LoRaRadio::get_frequency_support(void) } else { return (MATCHING_FREQ_868); } +#else + return MBED_CONF_SX126X_LORA_DRIVER_FREQ_SUPPORT; +#endif } uint8_t SX126X_LoRaRadio::get_fsk_bw_reg_val(uint32_t bandwidth) diff --git a/connectivity/drivers/lora/COMPONENT_SX126X/SX126X_LoRaRadio.h b/connectivity/drivers/lora/COMPONENT_SX126X/SX126X_LoRaRadio.h index b4fb7486aed..c9f672d46ca 100644 --- a/connectivity/drivers/lora/COMPONENT_SX126X/SX126X_LoRaRadio.h +++ b/connectivity/drivers/lora/COMPONENT_SX126X/SX126X_LoRaRadio.h @@ -306,11 +306,19 @@ class SX126X_LoRaRadio : public LoRaRadio { // module busy control mbed::DigitalIn _busy; - // module frequency selection +// module frequency selection +#if MBED_CONF_SX126X_LORA_DRIVER_FREQ_SUPPORT == -1 mbed::AnalogIn _freq_select; +#else + mbed::DigitalIn _freq_select; // AnalogIn errors if NC +#endif - // module device variant selection +// module device variant selection +#if MBED_CONF_SX126X_LORA_DRIVER_DEVICE_VARIANT == -1 mbed::AnalogIn _dev_select; +#else + mbed::DigitalIn _dev_select; // AnalogIn errors if NC +#endif // module TCXO/XTAL control mbed::DigitalIn _crystal_select; diff --git a/connectivity/drivers/lora/COMPONENT_SX126X/mbed_lib.json b/connectivity/drivers/lora/COMPONENT_SX126X/mbed_lib.json index 27505b1b609..2cce26389e9 100644 --- a/connectivity/drivers/lora/COMPONENT_SX126X/mbed_lib.json +++ b/connectivity/drivers/lora/COMPONENT_SX126X/mbed_lib.json @@ -25,6 +25,18 @@ "help": "Default: STDBY_RC = 0, STDBY_XOSC = 1", "value": 0 }, + "device-variant": { + "help": "Default: -1 = use device-select, SX1261, SX1262, SX1268", + "value": -1 + }, + "freq-support": { + "help": "Default: -1 = use freq-select, MATCHING_FREQ_169, MATCHING_FREQ_280, MATCHING_FREQ_434, MATCHING_FREQ_490, MATCHING_FREQ_780, MATCHING_FREQ_868, MATCHING_FREQ_915", + "value": -1 + }, + "xtal": { + "help": "Default: -1 = use crystal-select, TXCO = 0, XTAL = 1", + "value": -1 + }, "spi-mosi": { "value": "NC" }, diff --git a/connectivity/drivers/lora/TARGET_STM32WL/STM32WL_LoRaRadio.cpp b/connectivity/drivers/lora/TARGET_STM32WL/STM32WL_LoRaRadio.cpp index 6a7df14b8df..6a0327e380a 100644 --- a/connectivity/drivers/lora/TARGET_STM32WL/STM32WL_LoRaRadio.cpp +++ b/connectivity/drivers/lora/TARGET_STM32WL/STM32WL_LoRaRadio.cpp @@ -115,11 +115,11 @@ const float lora_symbol_time[3][6] = {{ 32.768, 16.384, 8.192, 4.096, 2.048, 1.0 #ifdef MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_RX -static DigitalOut _rf_dbg_rx(MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_RX, 0); +static DigitalOut _rf_dbg_rx(MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_RX, MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_INVERT); #endif #ifdef MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_TX -static DigitalOut _rf_dbg_tx(MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_TX, 0); +static DigitalOut _rf_dbg_tx(MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_TX, MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_INVERT); #endif @@ -302,7 +302,7 @@ void STM32WL_LoRaRadio::HAL_SUBGHZ_TxCpltCallback(void) #ifdef MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_TX /* Reset TX DBG pin */ - _rf_dbg_tx = 0; + _rf_dbg_tx = MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_INVERT; #endif } } @@ -330,7 +330,7 @@ void STM32WL_LoRaRadio::HAL_SUBGHZ_RxCpltCallback(void) #ifdef MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_RX /* Reset RX DBG pin */ - _rf_dbg_rx = 0; + _rf_dbg_rx = MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_INVERT; #endif } } @@ -360,7 +360,7 @@ void STM32WL_LoRaRadio::HAL_SUBGHZ_RxTxTimeoutCallback(void) #if MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_TX /* Reset TX DBG pin */ - _rf_dbg_tx = 0; + _rf_dbg_tx = MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_INVERT; #endif } else if ((_radio_events && _radio_events->rx_timeout) && (_operating_mode == MODE_RX)) { @@ -368,7 +368,7 @@ void STM32WL_LoRaRadio::HAL_SUBGHZ_RxTxTimeoutCallback(void) #ifdef MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_RX /* Reset RX DBG pin */ - _rf_dbg_rx = 0; + _rf_dbg_rx = MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_INVERT; #endif } } @@ -452,7 +452,25 @@ void STM32WL_LoRaRadio::SUBGRF_SetTxParams(uint8_t paSelect, int8_t power, radio // RegTxClampConfig = @address 0x08D8 write_to_register(REG_TX_CLAMP, read_register(REG_TX_CLAMP) | (0x0F << 1)); - set_pa_config(0x04, 0x07, 0x00, 0x01); + // if in mbed_app.json we have configured rf_switch_config in rfo_hp ONLY + // so "stm32wl-lora-driver.rf_switch_config": "RBI_CONF_RFO_HP" + // in this particular case it's not optimal settings for power<=20dBm + if (board_rf_switch_config == RBI_CONF_RFO_HP) { + // See Section 5.1.2 of the following Application Note + // https://www.st.com/resource/en/application_note/an5457-rf-matching-network-design-guide-for-stm32wl-series-stmicroelectronics.pdf + if (power > 20) { + set_pa_config(0x04, 0x07, 0x00, 0x01); + } else if (power > 17) { + set_pa_config(0x03, 0x05, 0x00, 0x01); + } else if (power > 14) { + set_pa_config(0x02, 0x03, 0x00, 0x01); + } else { + set_pa_config(0x02, 0x02, 0x00, 0x01); + } + } else { + set_pa_config(0x04, 0x07, 0x00, 0x01); + } + if (power > 22) { power = 22; } else if (power < -9) { @@ -1079,7 +1097,7 @@ void STM32WL_LoRaRadio::send(uint8_t *buffer, uint8_t size) #ifdef MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_TX /* Set TX DBG pin */ - _rf_dbg_tx = 1; + _rf_dbg_tx = !MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_INVERT; #endif /* Set RF switch */ @@ -1137,7 +1155,7 @@ void STM32WL_LoRaRadio::receive(void) #ifdef MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_RX /* Set RX DBG pin */ - _rf_dbg_rx = 1; + _rf_dbg_rx = !MBED_CONF_STM32WL_LORA_DRIVER_DEBUG_INVERT; #endif /* RF switch configuration */ diff --git a/connectivity/drivers/lora/TARGET_STM32WL/mbed_lib.json b/connectivity/drivers/lora/TARGET_STM32WL/mbed_lib.json index 4a5ab666fd6..3d3def03830 100644 --- a/connectivity/drivers/lora/TARGET_STM32WL/mbed_lib.json +++ b/connectivity/drivers/lora/TARGET_STM32WL/mbed_lib.json @@ -26,7 +26,7 @@ "value": "IS_TCXO_SUPPORTED" }, "rf_switch_config": { - "help": "Default: CONF_RFO_LP_HP = 0, CONF_RFO_LP = 1, CONF_RFO_HP = 2", + "help": "Default: RBI_CONF_RFO_LP_HP = 0, RBI_CONF_RFO_LP = 1, RBI_CONF_RFO_HP = 2", "value": "RBI_CONF_RFO_LP_HP" }, "rf_wakeup_time": { @@ -47,6 +47,10 @@ }, "debug_tx": { "help": "GPIO pin for TX debug" + }, + "debug_invert": { + "help": "invert levels of the debug_rx and debug_tx pins. Default: 0 standard, 1 invert", + "value" : 0 } }, "target_overrides": { diff --git a/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/src/bus_protocols/whd_bus_common.c b/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/src/bus_protocols/whd_bus_common.c index 4eacf4869aa..48c401a0a09 100755 --- a/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/src/bus_protocols/whd_bus_common.c +++ b/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/src/bus_protocols/whd_bus_common.c @@ -179,7 +179,7 @@ static whd_result_t whd_bus_common_download_resource(whd_driver_t whd_driver, wh uint32_t tmp; /* verify reset instruction value */ - result = whd_bus_read_backplane_value(whd_driver, 0, sizeof(tmp), (uint8_t *)&tmp); + result = whd_bus_read_backplane_value(whd_driver, 0, sizeof(tmp), (uint32_t *)&tmp); if ( (result == WHD_SUCCESS) && (tmp != reset_instr) ) { diff --git a/connectivity/lorawan/CMakeLists.txt b/connectivity/lorawan/CMakeLists.txt index 941b01e04e5..d30bdacfbce 100644 --- a/connectivity/lorawan/CMakeLists.txt +++ b/connectivity/lorawan/CMakeLists.txt @@ -2,7 +2,11 @@ # SPDX-License-Identifier: Apache-2.0 if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING) - add_subdirectory(tests/UNITTESTS) + if(BUILD_GREENTEA_TESTS) + # add greentea test + else() + add_subdirectory(tests/UNITTESTS) + endif() endif() add_subdirectory(lorastack) diff --git a/connectivity/lorawan/tests/UNITTESTS/doubles/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/doubles/CMakeLists.txt index ab15847a01a..70f5d3f4620 100644 --- a/connectivity/lorawan/tests/UNITTESTS/doubles/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/doubles/CMakeLists.txt @@ -5,6 +5,7 @@ add_library(mbed-headers-lorawan INTERFACE) target_include_directories(mbed-headers-lorawan INTERFACE + ${mbed-os_SOURCE_DIR}/connectivity ${mbed-os_SOURCE_DIR}/connectivity/lorawan/include/lorawan ${mbed-os_SOURCE_DIR}/connectivity/lorawan/lorastack ${mbed-os_SOURCE_DIR}/connectivity/lorawan/lorastack/mac @@ -39,11 +40,9 @@ target_sources(mbed-stubs-lorawan target_link_libraries(mbed-stubs-lorawan PRIVATE - mbed-headers-base mbed-headers-events mbed-headers-hal mbed-stubs-headers - mbed-headers-connectivity mbed-headers-platform mbed-headers-lorawan mbed-headers-mbedtls diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramac/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramac/CMakeLists.txt index d03b9428704..ebe9b3d6512 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramac/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramac/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-loramac-unittest) add_executable(${TEST_NAME}) @@ -33,7 +35,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-mbedtls mbed-headers-lorawan mbed-stubs @@ -42,6 +46,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramac/Test_LoRaMac.cpp b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramac/Test_LoRaMac.cpp index 4e5b540e610..6767cbbcd16 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramac/Test_LoRaMac.cpp +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramac/Test_LoRaMac.cpp @@ -432,7 +432,7 @@ TEST_F(Test_LoRaMac, post_process_mcps_req) LoRaMacCrypto_stub::int_table_idx_value = 0; LoRaMacCrypto_stub::int_table[0] = 4; LoRaMacCrypto_stub::int_table[1] = 4; -// LoRaPHY_stub::uint16_value = 0; + LoRaPHY_stub::uint16_value = 0; object->on_radio_rx_done(payload, 16, 0, 0); object->post_process_mcps_req(); diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramacchannelplan/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramacchannelplan/CMakeLists.txt index 6f65a60ccfd..523640378c1 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramacchannelplan/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramacchannelplan/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-loramac-channel-plan-unittest) add_executable(${TEST_NAME}) @@ -18,7 +20,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-lorawan mbed-stubs mbed-stubs-headers @@ -26,6 +30,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramaccommand/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramaccommand/CMakeLists.txt index f08c087905a..10c05b15f3f 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramaccommand/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramaccommand/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-loramac-command-unittest) add_executable(${TEST_NAME}) @@ -18,7 +20,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-mbedtls mbed-headers-lorawan mbed-stubs @@ -27,6 +31,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramaccrypto/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramaccrypto/CMakeLists.txt index b3b409405ae..e955f520bce 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramaccrypto/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loramaccrypto/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-loramac-crypto-unittest) add_executable(${TEST_NAME}) @@ -18,7 +20,7 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-platform mbed-headers-mbedtls mbed-headers-lorawan mbed-stubs @@ -27,6 +29,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphy/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphy/CMakeLists.txt index 59583ab07fe..4d3fd3fdc63 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphy/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphy/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-loraphy-unittest) add_executable(${TEST_NAME}) @@ -22,7 +24,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-lorawan mbed-stubs mbed-stubs-headers @@ -30,6 +34,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyas923/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyas923/CMakeLists.txt index 3709da416b8..abdb4da14d9 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyas923/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyas923/CMakeLists.txt @@ -1,13 +1,15 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-loraphy-as923-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} PRIVATE - MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 + MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 MBED_CONF_LORA_TX_MAX_SIZE=255 MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 ) @@ -20,7 +22,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-lorawan mbed-stubs mbed-stubs-headers @@ -28,6 +32,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyau915/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyau915/CMakeLists.txt index 5bba2dac85a..5bee043d9a8 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyau915/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyau915/CMakeLists.txt @@ -1,13 +1,15 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-loraphy-au915-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} PRIVATE - MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 + MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 MBED_CONF_LORA_TX_MAX_SIZE=255 MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 ) @@ -26,7 +28,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-lorawan mbed-stubs mbed-stubs-headers @@ -34,6 +38,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphycn470/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphycn470/CMakeLists.txt index 3d78f99389d..29d3905a654 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphycn470/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphycn470/CMakeLists.txt @@ -1,13 +1,15 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-loraphy-cn470-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} PRIVATE - MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 + MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 MBED_CONF_LORA_TX_MAX_SIZE=255 MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 ) @@ -26,7 +28,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-lorawan mbed-stubs mbed-stubs-headers @@ -34,6 +38,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphycn779/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphycn779/CMakeLists.txt index 7b95bb33e4f..f039e1999b4 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphycn779/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphycn779/CMakeLists.txt @@ -1,13 +1,15 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-loraphy-cn779-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} PRIVATE - MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 + MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 MBED_CONF_LORA_TX_MAX_SIZE=255 MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 ) @@ -20,7 +22,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-lorawan mbed-stubs mbed-stubs-headers @@ -28,6 +32,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyeu433/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyeu433/CMakeLists.txt index 357e350be96..f8ab984e561 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyeu433/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyeu433/CMakeLists.txt @@ -1,13 +1,15 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-loraphy-eu433-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} PRIVATE - MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 + MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 MBED_CONF_LORA_TX_MAX_SIZE=255 MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 ) @@ -20,7 +22,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-cellular mbed-headers-lorawan mbed-stubs @@ -29,6 +33,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyeu868/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyeu868/CMakeLists.txt index 6d4fd694625..740d320f562 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyeu868/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyeu868/CMakeLists.txt @@ -1,13 +1,15 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-loraphy-eu868-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} PRIVATE - MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 + MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 MBED_CONF_LORA_TX_MAX_SIZE=255 MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 ) @@ -20,7 +22,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-lorawan mbed-stubs mbed-stubs-headers @@ -28,6 +32,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyin865/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyin865/CMakeLists.txt index 0692f9825f4..713f5528f64 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyin865/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyin865/CMakeLists.txt @@ -1,13 +1,15 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-loraphy-in865-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} PRIVATE - MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 + MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 MBED_CONF_LORA_TX_MAX_SIZE=255 MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 ) @@ -20,7 +22,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-lorawan mbed-stubs mbed-stubs-headers @@ -28,6 +32,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphykr920/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphykr920/CMakeLists.txt index 4f5b1a7edf7..7d53df5b3dc 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphykr920/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphykr920/CMakeLists.txt @@ -1,13 +1,15 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-loraphy-kr920-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} PRIVATE - MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 + MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 MBED_CONF_LORA_TX_MAX_SIZE=255 MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 ) @@ -20,7 +22,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-cellular mbed-headers-lorawan mbed-stubs @@ -29,6 +33,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyus915/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyus915/CMakeLists.txt index 301c259f620..a9df57efc91 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyus915/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/loraphyus915/CMakeLists.txt @@ -1,13 +1,15 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-loraphy-us915-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} PRIVATE - MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 + MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5 MBED_CONF_LORA_TX_MAX_SIZE=255 MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 ) @@ -26,7 +28,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-cellular mbed-headers-lorawan mbed-stubs @@ -35,6 +39,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawaninterface/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawaninterface/CMakeLists.txt index adc5b11e755..20594a83139 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawaninterface/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawaninterface/CMakeLists.txt @@ -1,13 +1,15 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-lorawan-interface-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} PRIVATE - MBED_CONF_LORA_PHY=EU868 + MBED_CONF_LORA_PHY=EU868 MBED_CONF_LORA_TX_MAX_SIZE=255 ) @@ -19,7 +21,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-cellular mbed-headers-mbedtls mbed-headers-lorawan @@ -29,6 +33,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawanstack/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawanstack/CMakeLists.txt index 65598499a45..9c23ea676b8 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawanstack/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawanstack/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-lorawan-stack-unittest) add_executable(${TEST_NAME}) @@ -8,7 +10,7 @@ add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} PRIVATE MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION=true - MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE=true + MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE=true MBED_CONF_LORA_TX_MAX_SIZE=255 ) @@ -20,7 +22,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-hal + mbed-headers-platform mbed-headers-mbedtls mbed-headers-lorawan mbed-stubs @@ -29,6 +33,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawanstack/Test_LoRaWANStack.cpp b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawanstack/Test_LoRaWANStack.cpp index 13aca435fb1..33317c11f05 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawanstack/Test_LoRaWANStack.cpp +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawanstack/Test_LoRaWANStack.cpp @@ -554,7 +554,7 @@ TEST_F(Test_LoRaWANStack, handle_rx) } ind.buffer = ind_buf; ind.buffer_size = 50; - ind.type = mcps_type_t(66); + ind.type = MCPS_MULTICAST; radio._ev->rx_done(NULL, 0, 0, 0); EXPECT_TRUE(50 == object->handle_rx(data, 50, port, flags, false)); EXPECT_EQ(10, data[10]); @@ -631,6 +631,7 @@ TEST_F(Test_LoRaWANStack, acquire_tx_metadata) memset(&conf, 0, sizeof(conf)); conf.status = LORAMAC_EVENT_INFO_STATUS_OK; LoRaMac_stub::mcps_conf_ptr = &conf; + LoRaMac_stub::bool_true_counter = 1; radio._ev->tx_done(); LoRaMac_stub::slot_value = RX_SLOT_WIN_2; @@ -695,6 +696,11 @@ TEST_F(Test_LoRaWANStack, acquire_rx_metadata) cb.battery_level = batt_lvl; EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_lora_callbacks(&cb)); mlme.req_type = MLME_LINK_CHECK; + + loramac_mlme_indication_t ind2; + memset(&ind2, 0, sizeof(ind2)); + LoRaMac_stub::mlme_ind_ptr = &ind2; + mlme.status = LORAMAC_EVENT_INFO_STATUS_OK; LoRaMac_stub::bool_true_counter = true; radio._ev->rx_done(NULL, 0, 0, 0); diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawantimer/CMakeLists.txt b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawantimer/CMakeLists.txt index aeb84cbd3a7..5c7e8a5e708 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawantimer/CMakeLists.txt +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawantimer/CMakeLists.txt @@ -1,13 +1,15 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME lorawan-lorawan-timer-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} PRIVATE - NDEBUG=1 + NDEBUG=1 MBED_CONF_LORA_TX_MAX_SIZE=255 ) @@ -19,13 +21,12 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-platform mbed-headers-lorawan mbed-stubs mbed-stubs-headers gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "lorawan") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "lorawan") diff --git a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawantimer/Test_LoRaWANTimer.cpp b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawantimer/Test_LoRaWANTimer.cpp index 9fb10a39854..fd0ab985c86 100644 --- a/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawantimer/Test_LoRaWANTimer.cpp +++ b/connectivity/lorawan/tests/UNITTESTS/features/lorawan/lorawantimer/Test_LoRaWANTimer.cpp @@ -71,9 +71,12 @@ TEST_F(Test_LoRaWANTimer, init) TEST_F(Test_LoRaWANTimer, start) { - equeue_stub.void_ptr = NULL; + struct equeue_event ptr; + equeue_stub.void_ptr = &ptr; timer_event_t ev; memset(&ev, 0, sizeof(ev)); + object->init(ev, my_callback); + equeue_stub.call_cb_immediately = true; object->start(ev, 10); } diff --git a/connectivity/lwipstack/include/lwipstack/LWIPStack.h b/connectivity/lwipstack/include/lwipstack/LWIPStack.h index 994a4a0af3b..2707c52ef79 100644 --- a/connectivity/lwipstack/include/lwipstack/LWIPStack.h +++ b/connectivity/lwipstack/include/lwipstack/LWIPStack.h @@ -163,6 +163,9 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable { static void netif_status_irq(struct netif *netif); static Interface *our_if_from_netif(struct netif *netif); static void delete_interface(OnboardNetworkStack::Interface **interface_out); + NetworkInterface *network_if_from_netif_id(int id); + int netif_id_from_network_if(NetworkInterface *userInterface); + #if LWIP_ETHERNET static err_t emac_low_level_output(struct netif *netif, struct pbuf *p); @@ -222,6 +225,8 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable { void *hw; /**< alternative implementation pointer - used for PPP */ }; + NetworkInterface *user_network_interface; + mbed_rtos_storage_semaphore_t remove_interface_sem; osSemaphoreId_t remove_interface; mbed_rtos_storage_semaphore_t linked_sem; @@ -265,7 +270,7 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable { * @param[out] interface_out pointer to stack interface object controlling the EMAC * @return NSAPI_ERROR_OK on success, or error code */ - nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out) override; + nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, NetworkInterface *user_network_interface = NULL) override; /** Register a network interface with the IP stack * @@ -450,6 +455,27 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable { nsapi_size_or_error_t socket_send(nsapi_socket_t handle, const void *data, nsapi_size_t size) override; + /** Send a packet with ancillary data over a UDP socket + * + * Sends data to the specified address. Returns the number of bytes + * sent from the buffer. + * + * This call is non-blocking. If sendto would block, + * NSAPI_ERROR_WOULD_BLOCK is returned immediately. + * + * @param handle Socket handle + * @param address The SocketAddress of the remote host + * @param data Buffer of data to send to the host + * @param size Size of the buffer in bytes + * @param control Ancillary data storage + * @param control_size Size of the Ancillary data in bytes + * @return Number of sent bytes on success, negative error + * code on failure + */ + nsapi_size_or_error_t socket_sendto_control(nsapi_socket_t handle, const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) override; + /** Receive data over a TCP socket * * The socket must be connected to a remote host. Returns the number of @@ -493,6 +519,7 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable { * This call is non-blocking. If recvfrom would block, * NSAPI_ERROR_WOULD_BLOCK is returned immediately. * + * It uses socket_recvfrom_control with zero ancillary data. * @param handle Socket handle * @param address Destination for the source address or NULL * @param buffer Destination buffer for data received from the host @@ -503,6 +530,27 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable { nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *buffer, nsapi_size_t size) override; + /** Receive a packet with ancillary data over a UDP socket + * + * Receives data and stores the source address in address if address + * is not NULL. Returns the number of bytes received into the buffer. + * + * This call is non-blocking. If recvfrom would block, + * NSAPI_ERROR_WOULD_BLOCK is returned immediately. + * + * @param handle Socket handle + * @param address Destination for the source address or NULL + * @param buffer Destination buffer for data received from the host + * @param size Size of the buffer in bytes + * @param control Ancillary data storage + * @param control_size Size of the Ancillary data in bytes + * @return Number of received bytes on success, negative error + * code on failure + */ + nsapi_size_or_error_t socket_recvfrom_control(nsapi_socket_t handle, SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) override; + /** Register a callback on state change of the socket * * The specified callback will be called on state changes such as when diff --git a/connectivity/lwipstack/include/lwipstack/lwipopts.h b/connectivity/lwipstack/include/lwipstack/lwipopts.h index 0a0c2cf7a44..b2e509dbfdd 100644 --- a/connectivity/lwipstack/include/lwipstack/lwipopts.h +++ b/connectivity/lwipstack/include/lwipstack/lwipopts.h @@ -311,6 +311,8 @@ #endif +#define LWIP_NETBUF_RECVINFO MBED_CONF_LWIP_NETBUF_RECVINFO_ENABLED + // Make sure we default these to off, so // LWIP doesn't default to on #ifndef LWIP_ARP diff --git a/connectivity/lwipstack/lwip/test/unit/lwipopts.h b/connectivity/lwipstack/lwip/test/unit/lwipopts.h index c00ace1561f..3905e91afaa 100644 --- a/connectivity/lwipstack/lwip/test/unit/lwipopts.h +++ b/connectivity/lwipstack/lwip/test/unit/lwipopts.h @@ -46,7 +46,7 @@ #define LWIP_NETCONN !NO_SYS #define LWIP_SOCKET !NO_SYS #define LWIP_NETCONN_FULLDUPLEX LWIP_SOCKET -#define LWIP_NETBUF_RECVINFO 1 +#define LWIP_NETBUF_RECVINFO MBED_CONF_NETBUF_RECVINFO_ENABLED #define LWIP_HAVE_LOOPIF 1 #define TCPIP_THREAD_TEST diff --git a/connectivity/lwipstack/source/LWIPInterface.cpp b/connectivity/lwipstack/source/LWIPInterface.cpp index 164ff03e611..a1cfcf31c41 100644 --- a/connectivity/lwipstack/source/LWIPInterface.cpp +++ b/connectivity/lwipstack/source/LWIPInterface.cpp @@ -42,6 +42,28 @@ LWIP::Interface *LWIP::Interface::list; +NetworkInterface *LWIP::Interface::network_if_from_netif_id(int id) +{ + for (Interface *interface = list; interface; interface = interface->next) { + if (id == netif_get_index(&interface->netif)) { + return interface->user_network_interface; + } + } + return NULL; +} + +int LWIP::Interface::netif_id_from_network_if(NetworkInterface *userInterface) +{ + if (userInterface != NULL) { + for (Interface *interface = list; interface; interface = interface->next) { + if (userInterface == interface->user_network_interface) { + return netif_get_index(&interface->netif); + } + } + } + return 0; +} + LWIP::Interface *LWIP::Interface::our_if_from_netif(struct netif *netif) { for (Interface *interface = list; interface; interface = interface->next) { @@ -408,7 +430,7 @@ LWIP::Interface::Interface() : list = this; } -nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out) +nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, NetworkInterface *user_network_interface) { #if LWIP_ETHERNET Interface *interface = new (std::nothrow) Interface(); @@ -431,7 +453,7 @@ nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardN #endif interface->netif.hwaddr_len = 6; - + interface->user_network_interface = user_network_interface; if (!netif_add(&interface->netif, #if LWIP_IPV4 0, 0, 0, diff --git a/connectivity/lwipstack/source/LWIPStack.cpp b/connectivity/lwipstack/source/LWIPStack.cpp index db4adafb891..c67887e62da 100644 --- a/connectivity/lwipstack/source/LWIPStack.cpp +++ b/connectivity/lwipstack/source/LWIPStack.cpp @@ -15,10 +15,10 @@ * limitations under the License. */ #include "nsapi.h" +#include "netsocket/MsgHeader.h" #include "mbed_interface.h" #include "mbed_assert.h" #include "Semaphore.h" -#include #include #include @@ -37,6 +37,7 @@ #include "lwip/raw.h" #include "lwip/netif.h" #include "lwip/lwip_errno.h" +#include "lwip/ip_addr.h" #include "lwip-sys/arch/sys_arch.h" #include "LWIPStack.h" @@ -271,7 +272,9 @@ nsapi_error_t LWIP::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto) arena_dealloc(s); return NSAPI_ERROR_NO_SOCKET; } - +#if LWIP_NETBUF_RECVINFO + s->conn->flags &= ~NETCONN_FLAG_PKTINFO; +#endif netconn_set_nonblocking(s->conn, true); *(struct mbed_lwip_socket **)handle = s; return 0; @@ -439,24 +442,111 @@ nsapi_size_or_error_t LWIP::socket_recv(nsapi_socket_t handle, void *data, nsapi } nsapi_size_or_error_t LWIP::socket_sendto(nsapi_socket_t handle, const SocketAddress &address, const void *data, nsapi_size_t size) +{ + return socket_sendto_control(handle, address, data, size, NULL, 0); +} + +nsapi_size_or_error_t LWIP::socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *data, nsapi_size_t size) +{ + return socket_recvfrom_control(handle, address, data, size, NULL, 0); + +} + +nsapi_size_or_error_t LWIP::socket_recvfrom_control(nsapi_socket_t handle, SocketAddress *address, void *data, + nsapi_size_t size, nsapi_msghdr_t *control, + nsapi_size_t control_size) { struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; - ip_addr_t ip_addr; + struct netbuf *buf; + + err_t err = netconn_recv(s->conn, &buf); + if (err != ERR_OK) { + return err_remap(err); + } + + if (address) { + nsapi_addr_t addr; + convert_lwip_addr_to_mbed(&addr, netbuf_fromaddr(buf)); + address->set_addr(addr); + address->set_port(netbuf_fromport(buf)); + } +#if LWIP_NETBUF_RECVINFO + if ((s->conn->flags & NETCONN_FLAG_PKTINFO) && control && control_size >= sizeof(nsapi_pktinfo_t)) { + nsapi_pktinfo_t *pkt_info = reinterpret_cast(control); + memset(control, 0, control_size); + // Not optimal but sufficient. It should help the caller in not iterating over + // the control data structure + control->len = control_size; + control->level = NSAPI_SOCKET; + control->type = NSAPI_PKTINFO; + // retrieve the destination + convert_lwip_addr_to_mbed(&pkt_info->ipi_addr, netbuf_destaddr(buf)); + // retrieve the interface id + pkt_info->network_interface = default_interface->network_if_from_netif_id(buf->p->if_idx); + } +#endif + u16_t recv = netbuf_copy(buf, data, (u16_t)size); + netbuf_delete(buf); + + return recv; +} + +nsapi_size_or_error_t LWIP::socket_sendto_control(nsapi_socket_t handle, const SocketAddress &address, + const void *data, nsapi_size_t size, nsapi_msghdr_t *control, + nsapi_size_t control_size) +{ + struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; + ip_addr_t ip_addr = {}; + + // Used for backup the bound address if the packet must be sent from a specific address, + ip_addr_t bound_addr = {}; + ip_addr_t src_addr = {}; + + nsapi_pktinfo_t *pkt_info = nullptr; nsapi_addr_t addr = address.get_addr(); if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { return NSAPI_ERROR_PARAMETER; } - struct netif *netif_ = netif_get_by_index(s->conn->pcb.ip->netif_idx); + + // We try to extract the pktinfo from the header + + if (control) { + MsgHeaderIterator it(control, control_size); + while (it.has_next()) { + auto *hdr = it.next(); + if (hdr->level == NSAPI_SOCKET && hdr->type == NSAPI_PKTINFO) { + pkt_info = reinterpret_cast(hdr); + break; + } + } + } + + if (pkt_info) { + if (!convert_mbed_addr_to_lwip(&src_addr, &pkt_info->ipi_addr)) { + return NSAPI_ERROR_PARAMETER; + } + } + + struct netif *netif_ = nullptr; + + if (pkt_info) { + int index = default_interface->netif_id_from_network_if((NetworkInterface *)pkt_info->network_interface); + netif_ = netif_get_by_index(index); + } else { + netif_ = netif_get_by_index(s->conn->pcb.ip->netif_idx); + } if (!netif_) { netif_ = &default_interface->netif; } + if (netif_) { if ((addr.version == NSAPI_IPv4 && !get_ipv4_addr(netif_)) || (addr.version == NSAPI_IPv6 && !get_ipv6_addr(netif_) && !get_ipv6_link_local_addr(netif_))) { return NSAPI_ERROR_PARAMETER; } } + struct netbuf *buf = netbuf_new(); err_t err = netbuf_ref(buf, data, (u16_t)size); @@ -465,36 +555,29 @@ nsapi_size_or_error_t LWIP::socket_sendto(nsapi_socket_t handle, const SocketAdd return err_remap(err); } - err = netconn_sendto(s->conn, buf, &ip_addr, address.get_port()); - netbuf_delete(buf); - if (err != ERR_OK) { - return err_remap(err); + // handle src destination if required + if (pkt_info) { + // Backup the bound address + ip_addr_copy(bound_addr, s->conn->pcb.udp->local_ip); + // replace it with the source address + if (!ip_addr_isany(&src_addr)) { + ip_addr_copy(s->conn->pcb.udp->local_ip, src_addr); + } } - return size; -} + err = netconn_sendto(s->conn, buf, &ip_addr, address.get_port()); -nsapi_size_or_error_t LWIP::socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *data, nsapi_size_t size) -{ - struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; - struct netbuf *buf; + if (pkt_info) { + // restore bound address + ip_addr_copy(s->conn->pcb.udp->local_ip, bound_addr); + } - err_t err = netconn_recv(s->conn, &buf); + netbuf_delete(buf); if (err != ERR_OK) { return err_remap(err); } - if (address) { - nsapi_addr_t addr; - convert_lwip_addr_to_mbed(&addr, netbuf_fromaddr(buf)); - address->set_addr(addr); - address->set_port(netbuf_fromport(buf)); - } - - u16_t recv = netbuf_copy(buf, data, (u16_t)size); - netbuf_delete(buf); - - return recv; + return size; } int32_t LWIP::find_multicast_member(const struct mbed_lwip_socket *s, const nsapi_ip_mreq_t *imr) @@ -687,6 +770,19 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co } s->conn->pcb.ip->tos = (u8_t)(*(const int *)optval); return 0; + + case NSAPI_PKTINFO: +#if LWIP_NETBUF_RECVINFO + if (optlen != sizeof(int)) { + return NSAPI_ERROR_UNSUPPORTED; + } + if (*(const int *)optval) { + s->conn->flags |= NETCONN_FLAG_PKTINFO; + } else { + s->conn->flags &= ~NETCONN_FLAG_PKTINFO; + } + return 0; +#endif default: return NSAPI_ERROR_UNSUPPORTED; } diff --git a/connectivity/mbedtls/source/x509_crt.c b/connectivity/mbedtls/source/x509_crt.c index a623c57a6c1..57d5c788f31 100644 --- a/connectivity/mbedtls/source/x509_crt.c +++ b/connectivity/mbedtls/source/x509_crt.c @@ -74,7 +74,11 @@ #if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) #include #include +#if defined(__MBED__) +#include +#else #include +#endif /* __MBED__ */ #endif /* !_WIN32 || EFIX64 || EFI32 */ #endif diff --git a/connectivity/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c b/connectivity/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c index be8d31955b7..91c17e2c234 100644 --- a/connectivity/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c +++ b/connectivity/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c @@ -300,6 +300,12 @@ int mbedtls_x509_crt_parse(mbedtls_x509_crt *a, const unsigned char *b, size_t c return mbedtls_stub.expected_int; } +int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *a, const char *b) +{ + // means 5 valid certificates found + return 5; +} + int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_crt *crt) { diff --git a/connectivity/nanostack/include/nanostack-interface/Nanostack.h b/connectivity/nanostack/include/nanostack-interface/Nanostack.h index 53894a1f10b..09ffc51f1eb 100644 --- a/connectivity/nanostack/include/nanostack-interface/Nanostack.h +++ b/connectivity/nanostack/include/nanostack-interface/Nanostack.h @@ -40,11 +40,11 @@ class Nanostack : public OnboardNetworkStack, private mbed::NonCopyable(&buff); + + MsgHeaderIterator it(hdr_p, sizeof(buff)); + + it.has_next() // returns true + auto p1 = it.next() // returns pointer to el1 + auto p2 = it.next() // returns pointer to el2 + auto p3 = it.next() // returns pointer to el3 + auto p4 = it.next() // returns pointer to el4 + + it.has_next() // returns false + auto p5 = it.next() // returns nullptr + * @endcode + * + * @note More usage examples are implemented in the MsgHeaderIterator unit test + * in netsocket/tests/UNITTESTS/NetworkStack/test_MsgHeaderIterator.cpp + */ + +struct MsgHeaderIterator { + /** Create a MsgHeaderIterator over given nsapi_msghdr_t list. + * + * @param hdr Pointer to the first list element. + * @param size Size of the whole list. + */ + MsgHeaderIterator(nsapi_msghdr_t *hdr, nsapi_size_t size) : + start(hdr), + current(nullptr), + size(size) + {} + + /** Checks if the next address of the iterator is a valid list member. + * + * @retval True if the next address is a valid member. + * @retval False otherwise. + */ + bool has_next() + { + if (current == nullptr) { + if (start != nullptr && start->len <= size && start->len >= sizeof(*start)) { + return true; + } else { + return false; + } + } + + if (current->len < sizeof(*current)) { + return false; + } + + if (get_next_aligned_addr() >= (reinterpret_cast(start) + size)) { + return false; + } + + return true; + } + + /** Returns next element of the list. + * + * @retval nullptr if the list doesn't contain next element. + * @retval Pointer to the next element otherwise. + */ + nsapi_msghdr_t *next() + { + if (!has_next()) { + return nullptr; + } + + if (current == nullptr) { + current = start; + } else { + current = reinterpret_cast(get_next_aligned_addr()); + } + + return current; + } + +private: + // Get address of the next member aligned to the size of msghdr_t. + void *get_next_aligned_addr() + { + size_t remaining_size = size - (reinterpret_cast(current) - reinterpret_cast(start)); + void *next = reinterpret_cast(reinterpret_cast(current) + current->len); + + next = std::align( + alignof(nsapi_msghdr_t), + sizeof(nsapi_msghdr_t), + next, + remaining_size + ); + + return next; + } + + nsapi_msghdr_t *start; + nsapi_msghdr_t *current; + nsapi_size_t size; +}; + + +#endif + diff --git a/connectivity/netsocket/include/netsocket/NetworkStack.h b/connectivity/netsocket/include/netsocket/NetworkStack.h index 2f6bb78cbc4..6d675663677 100644 --- a/connectivity/netsocket/include/netsocket/NetworkStack.h +++ b/connectivity/netsocket/include/netsocket/NetworkStack.h @@ -395,6 +395,65 @@ class NetworkStack : public DNS { virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *buffer, nsapi_size_t size) = 0; + /** Send a packet with ancillary data over a UDP socket + * + * Sends data to the specified address. Returns the number of bytes + * sent from the buffer. + * + * This call is non-blocking. If sendto would block, + * NSAPI_ERROR_WOULD_BLOCK is returned immediately. + * + * @param handle Socket handle + * @param address The SocketAddress of the remote host + * @param data Buffer of data to send to the host + * @param size Size of the buffer in bytes + * @param control Storage for ancillary data + * @param control_size Size of ancillary data + * @return Number of sent bytes on success, negative error + * code on failure + */ + virtual nsapi_size_or_error_t socket_sendto_control(nsapi_socket_t handle, const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) + { + if (control != NULL) { + return NSAPI_ERROR_UNSUPPORTED; + } + + return socket_sendto(handle, address, data, size); + } + + /** Receive a packet with ancillary data over a UDP socket + * + * Receives data and stores the source address in address if address + * is not NULL. Returns the number of bytes received into the buffer. + * + * Additional information related to the message can be retrieved with + * the control data. + * + * This call is non-blocking. If recvfrom would block, + * NSAPI_ERROR_WOULD_BLOCK is returned immediately. + * + * @param handle Socket handle + * @param address Destination for the source address or NULL + * @param buffer Destination buffer for data received from the host + * @param size Size of the buffer in bytes + * @param control Storage for ancillary data + * @param control_size Size of ancillary data + * @return Number of received bytes on success, negative error + * code on failure + */ + virtual nsapi_size_or_error_t socket_recvfrom_control(nsapi_socket_t handle, SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) + { + if (control != NULL) { + return NSAPI_ERROR_UNSUPPORTED; + } + + return socket_recvfrom(handle, address, data, size); + } + /** Register a callback on state change of the socket * * The specified callback will be called on state changes such as when diff --git a/connectivity/netsocket/include/netsocket/OnboardNetworkStack.h b/connectivity/netsocket/include/netsocket/OnboardNetworkStack.h index 8c48c7b75fd..2c1608a7123 100644 --- a/connectivity/netsocket/include/netsocket/OnboardNetworkStack.h +++ b/connectivity/netsocket/include/netsocket/OnboardNetworkStack.h @@ -160,9 +160,10 @@ class OnboardNetworkStack : public NetworkStack { * @param[out] interface_out pointer to stack interface object controlling the EMAC * @return NSAPI_ERROR_OK on success, or error code */ - virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Interface **interface_out) = 0; + virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Interface **interface_out, NetworkInterface *user_network_interface = NULL) = 0; + + virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Interface **interface_out, const uint8_t *mac_addr, NetworkInterface *user_network_interface = NULL) - virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Interface **interface_out, const uint8_t *mac_addr) { return NSAPI_ERROR_UNSUPPORTED; } diff --git a/connectivity/netsocket/include/netsocket/Socket.h b/connectivity/netsocket/include/netsocket/Socket.h index de493c7bd6e..6ef5635ed28 100644 --- a/connectivity/netsocket/include/netsocket/Socket.h +++ b/connectivity/netsocket/include/netsocket/Socket.h @@ -157,6 +157,55 @@ class Socket { virtual nsapi_size_or_error_t recvfrom(SocketAddress *address, void *data, nsapi_size_t size) = 0; + /** Send a message on a socket. + * + * The sendto_control() function sends a message through a connection-mode or connectionless-mode socket. + * If the socket is a connectionless-mode socket, the message is sent to the address specified. + * If the socket is a connected-mode socket, address is ignored. + * + * Additional control information can be passed to the stack for specific operations. + * + * By default, sendto blocks until data is sent. If socket is set to + * non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned + * immediately. + * + * @param address Remote address + * @param data Buffer of data to send to the host + * @param size Size of the buffer in bytes + * @return Number of sent bytes on success, negative subclass-dependent error + * code on failure + */ + virtual nsapi_size_or_error_t sendto_control(const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) = 0; + + + /** Receive a data from a socket + * + * Receives a data and stores the source address in address if address + * is not NULL. Returns the number of bytes written into the buffer. + * + * If socket is connected, only packets coming from connected peer address + * are accepted. + * + * Additional information related to the message can be retrieved with the control data. + * + * @note recvfrom_control() is allowed write to address and data buffers even if error occurs. + * + * By default, recvfrom blocks until a datagram is received. If socket is set to + * non-blocking or times out with no data, NSAPI_ERROR_WOULD_BLOCK + * is returned. + * + * @param address Destination for the source address or NULL + * @param data Destination buffer for datagram received from the host + * @param size Size of the buffer in bytes + * @return Number of received bytes on success, negative subclass-dependent + * error code on failure + */ + virtual nsapi_size_or_error_t recvfrom_control(SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) = 0; + /** Bind a specific address to a socket. * * Binding a socket specifies the address and port on which to receive diff --git a/connectivity/netsocket/include/netsocket/TCPSocket.h b/connectivity/netsocket/include/netsocket/TCPSocket.h index 37897f231a0..05f1d11da08 100644 --- a/connectivity/netsocket/include/netsocket/TCPSocket.h +++ b/connectivity/netsocket/include/netsocket/TCPSocket.h @@ -145,6 +145,53 @@ class TCPSocket : public InternetSocket { nsapi_size_or_error_t recvfrom(SocketAddress *address, void *data, nsapi_size_t size) override; + /** Send data on a packet with ancillary datasocket. + * + * TCP socket is connection oriented protocol, so address is ignored. + * + * By default, sendto_control blocks until data is sent. If socket is set to + * non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned + * immediately. + * + * @param address Remote address + * @param data Buffer of data to send to the host + * @param size Size of the buffer in bytes + * @retval int Number of sent bytes on success + * @retval NSAPI_ERROR_NO_SOCKET in case socket was not created correctly + * @retval NSAPI_ERROR_WOULD_BLOCK in case non-blocking mode is enabled + * and send cannot be performed immediately + * @retval int Other negative error codes for stack-related failures. + * See @ref NetworkStack::socket_send. + */ + nsapi_size_or_error_t sendto_control(const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) override; + + /** Receive a packet with ancillary data from a socket + * + * Receives a data and stores the source address in address if address + * is not NULL. Returns the number of bytes written into the buffer. + * + * By default, recvfrom_control blocks until a data is received. If socket is set to + * non-blocking or times out with no datagram, NSAPI_ERROR_WOULD_BLOCK + * is returned. + * + * @param address Destination for the source address or NULL + * @param data Destination buffer for datagram received from the host + * @param size Size of the buffer in bytes + * @control Pointer to the control buffer + * @control_size Size of the control buffer in bytes + * @retval int Number of received bytes on success + * @retval NSAPI_ERROR_NO_SOCKET in case socket was not created correctly + * @retval NSAPI_ERROR_WOULD_BLOCK in case non-blocking mode is enabled + * and send cannot be performed immediately + * @retval int Other negative error codes for stack-related failures. + * See @ref NetworkStack::socket_recv. + */ + nsapi_size_or_error_t recvfrom_control(SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) override; + /** Accepts a connection on a socket. * * The server socket must be bound and set to listen for connections. diff --git a/connectivity/netsocket/include/netsocket/TLSSocketWrapper.h b/connectivity/netsocket/include/netsocket/TLSSocketWrapper.h index 8f6af7f8ed6..143dda3aff8 100644 --- a/connectivity/netsocket/include/netsocket/TLSSocketWrapper.h +++ b/connectivity/netsocket/include/netsocket/TLSSocketWrapper.h @@ -116,6 +116,18 @@ class TLSSocketWrapper : public Socket { */ nsapi_error_t set_root_ca_cert(const char *root_ca_pem); + /** Sets the certification of Root CA. + * + * @note Must be called before calling connect() + * + * @param root_ca Path containing Root CA Certificate files in any Mbed TLS-supported format. + * @retval NSAPI_ERROR_OK on success. + * @retval NSAPI_ERROR_NO_MEMORY in case there is not enough memory to allocate certificate. + * @retval NSAPI_ERROR_PARAMETER in case the provided root_ca parameter failed parsing. + * + */ + nsapi_error_t set_root_ca_cert_path(const char *root_ca); + /** Sets client certificate, and client private key. * * @param client_cert Client certification in PEM or DER format. @@ -185,6 +197,14 @@ class TLSSocketWrapper : public Socket { nsapi_size_or_error_t sendto(const SocketAddress &address, const void *data, nsapi_size_t size) override; nsapi_size_or_error_t recvfrom(SocketAddress *address, void *data, nsapi_size_t size) override; + + nsapi_size_or_error_t sendto_control(const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) override; + nsapi_size_or_error_t recvfrom_control(SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) override; + nsapi_error_t bind(const SocketAddress &address) override; void set_blocking(bool blocking) override; void set_timeout(int timeout) override; diff --git a/connectivity/netsocket/include/netsocket/nsapi_types.h b/connectivity/netsocket/include/netsocket/nsapi_types.h index eef8f34cc57..3b496d5087a 100644 --- a/connectivity/netsocket/include/netsocket/nsapi_types.h +++ b/connectivity/netsocket/include/netsocket/nsapi_types.h @@ -22,6 +22,8 @@ #define NSAPI_TYPES_H #include +#include +#include "mbed_toolchain.h" #ifdef __cplusplus extern "C" { @@ -318,7 +320,8 @@ typedef enum nsapi_socket_option { NSAPI_LATENCY, /*!< Read estimated latency to destination */ NSAPI_STAGGER, /*!< Read estimated stagger value to destination */ NSAPI_IPTOS, /*!< Set IP type of service to set specific precedence */ - NSAPI_BROADCAST /*!< Set broadcast flag for UDP socket */ + NSAPI_BROADCAST, /*!< Set broadcast flag for UDP socket */ + NSAPI_PKTINFO /*!< Get additional information when using sendto_control/recvfrom_control */ } nsapi_socket_option_t; typedef enum nsapi_tlssocket_level { @@ -406,6 +409,26 @@ typedef struct nsapi_stagger_req { uint16_t stagger_rand; /* [OUT] Randomized stagger value in seconds */ } nsapi_stagger_req_t; +/** nsapi_msghdr + */ +typedef struct nsapi_msghdr { + /* In C alignment can't be specified in the type declaration. + * Specifying it in the first member definition will affect whole structure. + */ + MBED_ALIGN(max_align_t) nsapi_size_t len; /* Data byte count, including header */ + int level; /* Originating protocol */ + int type; /* Protocol-specific type */ +} nsapi_msghdr_t; + +/** nsapi_pktinfo structure + */ +typedef struct nsapi_pktinfo { + nsapi_msghdr_t hdr; /* Header identifying the message control structure */ + nsapi_addr_t ipi_addr; /* Address associated with the packet */ + int ipi_ifindex; /* Interface associated with the packet */ + void *network_interface; /* Network interface pointer*/ +} nsapi_pktinfo_t; + /** nsapi_stack_api structure * * Common api structure for network stack operations. A network stack @@ -644,6 +667,17 @@ typedef struct nsapi_stack_api { nsapi_size_or_error_t (*socket_recvfrom)(nsapi_stack_t *stack, nsapi_socket_t socket, nsapi_addr_t *addr, uint16_t *port, void *buffer, nsapi_size_t size); + // TODO: Documentation + nsapi_size_or_error_t (*socket_sendto_control)(nsapi_stack_t *stack, nsapi_socket_t socket, + nsapi_addr_t addr, uint16_t port, + const void *data, nsapi_size_t size, + const nsapi_msghdr_t *control, nsapi_size_t control_size); + + nsapi_size_or_error_t (*socket_recvfrom_control)(nsapi_stack_t *stack, nsapi_socket_t socket, + nsapi_addr_t *addr, uint16_t *port, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size); + /** Register a callback on state change of the socket * * The specified callback will be called on state changes such as when diff --git a/connectivity/netsocket/source/CellularNonIPSocket.cpp b/connectivity/netsocket/source/CellularNonIPSocket.cpp index f0925f7835a..11a0786a3e4 100644 --- a/connectivity/netsocket/source/CellularNonIPSocket.cpp +++ b/connectivity/netsocket/source/CellularNonIPSocket.cpp @@ -244,12 +244,26 @@ nsapi_size_or_error_t CellularNonIPSocket::sendto(const SocketAddress &address, { return NSAPI_ERROR_UNSUPPORTED; } +nsapi_size_or_error_t CellularNonIPSocket::sendto_control(const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + nsapi_size_or_error_t CellularNonIPSocket::recvfrom(SocketAddress *address, void *data, nsapi_size_t size) { return NSAPI_ERROR_UNSUPPORTED; } +nsapi_size_or_error_t CellularNonIPSocket::recvfrom_control(SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + nsapi_error_t CellularNonIPSocket::setsockopt(int level, int optname, const void *optval, unsigned optlen) { return NSAPI_ERROR_UNSUPPORTED; diff --git a/connectivity/netsocket/source/EMACInterface.cpp b/connectivity/netsocket/source/EMACInterface.cpp index 6474b6a570e..f48bc0a185a 100644 --- a/connectivity/netsocket/source/EMACInterface.cpp +++ b/connectivity/netsocket/source/EMACInterface.cpp @@ -55,14 +55,14 @@ nsapi_error_t EMACInterface::connect() nsapi_error_t err = NSAPI_ERROR_UNSUPPORTED; if (_hw_mac_addr_set) { - err = _stack.add_ethernet_interface(_emac, true, &_interface, _hw_mac_addr); + err = _stack.add_ethernet_interface(_emac, true, &_interface, _hw_mac_addr, this); if (err == NSAPI_ERROR_UNSUPPORTED) { tr_error("Failed to set user MAC address"); } } if (err == NSAPI_ERROR_UNSUPPORTED) { - err = _stack.add_ethernet_interface(_emac, true, &_interface); + err = _stack.add_ethernet_interface(_emac, true, &_interface, this); } if (err != NSAPI_ERROR_OK) { diff --git a/connectivity/netsocket/source/InternetDatagramSocket.cpp b/connectivity/netsocket/source/InternetDatagramSocket.cpp index 4c0010de033..fdf5ad8df13 100644 --- a/connectivity/netsocket/source/InternetDatagramSocket.cpp +++ b/connectivity/netsocket/source/InternetDatagramSocket.cpp @@ -27,7 +27,9 @@ nsapi_error_t InternetDatagramSocket::connect(const SocketAddress &address) return NSAPI_ERROR_OK; } -nsapi_size_or_error_t InternetDatagramSocket::sendto(const SocketAddress &address, const void *data, nsapi_size_t size) +nsapi_size_or_error_t InternetDatagramSocket::sendto_control(const SocketAddress &address, const void *data, + nsapi_size_t size, nsapi_msghdr_t *control, + nsapi_size_t control_size) { _lock.lock(); nsapi_size_or_error_t ret; @@ -44,7 +46,8 @@ nsapi_size_or_error_t InternetDatagramSocket::sendto(const SocketAddress &addres } core_util_atomic_flag_clear(&_pending); - nsapi_size_or_error_t sent = _stack->socket_sendto(_socket, address, data, size); + nsapi_size_or_error_t sent = _stack->socket_sendto_control(_socket, address, data, size, control, + control_size); if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != sent)) { _socket_stats.stats_update_sent_bytes(this, sent); ret = sent; @@ -74,6 +77,12 @@ nsapi_size_or_error_t InternetDatagramSocket::sendto(const SocketAddress &addres return ret; } +nsapi_size_or_error_t InternetDatagramSocket::sendto(const SocketAddress &address, const void *data, nsapi_size_t size) +{ + + return sendto_control(address, data, size, NULL, 0); +} + nsapi_size_or_error_t InternetDatagramSocket::send(const void *data, nsapi_size_t size) { if (!_remote_peer) { @@ -82,7 +91,8 @@ nsapi_size_or_error_t InternetDatagramSocket::send(const void *data, nsapi_size_ return sendto(_remote_peer, data, size); } -nsapi_size_or_error_t InternetDatagramSocket::recvfrom(SocketAddress *address, void *buffer, nsapi_size_t size) +nsapi_size_or_error_t InternetDatagramSocket::recvfrom_control(SocketAddress *address, void *buffer, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) { _lock.lock(); nsapi_size_or_error_t ret; @@ -104,7 +114,8 @@ nsapi_size_or_error_t InternetDatagramSocket::recvfrom(SocketAddress *address, v } core_util_atomic_flag_clear(&_pending); - nsapi_size_or_error_t recv = _stack->socket_recvfrom(_socket, address, buffer, size); + nsapi_size_or_error_t recv = _stack->socket_recvfrom_control(_socket, address, buffer, size, control, + control_size); // Filter incomming packets using connected peer address if (recv >= 0 && _remote_peer && _remote_peer != *address) { @@ -143,6 +154,11 @@ nsapi_size_or_error_t InternetDatagramSocket::recvfrom(SocketAddress *address, v return ret; } +nsapi_size_or_error_t InternetDatagramSocket::recvfrom(SocketAddress *address, void *buffer, nsapi_size_t size) +{ + return recvfrom_control(address, buffer, size, NULL, 0); +} + nsapi_size_or_error_t InternetDatagramSocket::recv(void *buffer, nsapi_size_t size) { return recvfrom(NULL, buffer, size); diff --git a/connectivity/netsocket/source/NetworkStack.cpp b/connectivity/netsocket/source/NetworkStack.cpp index 99b17cff13a..7ece7b6e5fc 100644 --- a/connectivity/netsocket/source/NetworkStack.cpp +++ b/connectivity/netsocket/source/NetworkStack.cpp @@ -399,6 +399,50 @@ class NetworkStackWrapper : public NetworkStack { return err; } + nsapi_size_or_error_t socket_sendto_control(nsapi_socket_t socket, const SocketAddress &address, const void *data, + nsapi_size_t size, nsapi_msghdr_t *control, + nsapi_size_t control_size) override + { + if (control != NULL) { + return NSAPI_ERROR_UNSUPPORTED; + } + + if (!_stack_api()->socket_sendto_control) { + return NSAPI_ERROR_UNSUPPORTED; + } + + return _stack_api()->socket_sendto_control(_stack(), socket, address.get_addr(), address.get_port(), data, + size, control, control_size); + } + + nsapi_size_or_error_t socket_recvfrom_control(nsapi_socket_t socket, SocketAddress *address, void *data, + nsapi_size_t size, nsapi_msghdr_t *control, + nsapi_size_t control_size) override + { + if (control != NULL) { + return NSAPI_ERROR_UNSUPPORTED; + } + + if (!_stack_api()->socket_recvfrom_control) { + return NSAPI_ERROR_UNSUPPORTED; + } + + nsapi_addr_t addr = {NSAPI_IPv4, 0}; + uint16_t port = 0; + + nsapi_size_or_error_t err = _stack_api()->socket_recvfrom_control(_stack(), socket, &addr, &port, data, size, + control, control_size); + + if (address) { + address->set_addr(addr); + address->set_port(port); + } + + return err; + } + + + void socket_attach(nsapi_socket_t socket, void (*callback)(void *), void *data) override { if (!_stack_api()->socket_attach) { diff --git a/connectivity/netsocket/source/TCPSocket.cpp b/connectivity/netsocket/source/TCPSocket.cpp index a85c8eb26cd..368a2a36f11 100644 --- a/connectivity/netsocket/source/TCPSocket.cpp +++ b/connectivity/netsocket/source/TCPSocket.cpp @@ -173,6 +173,15 @@ nsapi_size_or_error_t TCPSocket::sendto(const SocketAddress &address, const void return send(data, size); } +nsapi_size_or_error_t TCPSocket::sendto_control(const SocketAddress &address, const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) +{ + if (control) { + return NSAPI_ERROR_UNSUPPORTED; + } + return sendto(address, data, size); +} + nsapi_size_or_error_t TCPSocket::recv(void *data, nsapi_size_t size) { _lock.lock(); @@ -229,6 +238,15 @@ nsapi_size_or_error_t TCPSocket::recvfrom(SocketAddress *address, void *data, ns return recv(data, size); } +nsapi_size_or_error_t TCPSocket::recvfrom_control(SocketAddress *address, void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) +{ + if (control) { + return NSAPI_ERROR_UNSUPPORTED; + } + return recvfrom(address, data, size); +} + nsapi_error_t TCPSocket::listen(int backlog) { _lock.lock(); diff --git a/connectivity/netsocket/source/TLSSocketWrapper.cpp b/connectivity/netsocket/source/TLSSocketWrapper.cpp index 9879af9e913..8202151eb7b 100644 --- a/connectivity/netsocket/source/TLSSocketWrapper.cpp +++ b/connectivity/netsocket/source/TLSSocketWrapper.cpp @@ -136,6 +136,35 @@ nsapi_error_t TLSSocketWrapper::set_root_ca_cert(const char *root_ca_pem) return set_root_ca_cert(root_ca_pem, strlen(root_ca_pem) + 1); } +nsapi_error_t TLSSocketWrapper::set_root_ca_cert_path(const char *root_ca) +{ +#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) + return NSAPI_ERROR_UNSUPPORTED; +#else + mbedtls_x509_crt *crt; + + crt = new (std::nothrow) mbedtls_x509_crt; + if (!crt) { + return NSAPI_ERROR_NO_MEMORY; + } + + mbedtls_x509_crt_init(crt); + + /* Parse CA certification */ + int ret = mbedtls_x509_crt_parse_path(crt, root_ca); + if (ret < 0) { + print_mbedtls_error("mbedtls_x509_crt_parse", ret); + mbedtls_x509_crt_free(crt); + delete crt; + return NSAPI_ERROR_PARAMETER; + } + set_ca_chain(crt); + _cacert_allocated = true; + return NSAPI_ERROR_OK; +#endif +} + + nsapi_error_t TLSSocketWrapper::set_client_cert_key(const char *client_cert_pem, const char *client_private_key_pem) { return set_client_cert_key(client_cert_pem, strlen(client_cert_pem) + 1, client_private_key_pem, strlen(client_private_key_pem) + 1); @@ -286,10 +315,10 @@ nsapi_error_t TLSSocketWrapper::continue_handshake() } if (ret < 0) { - print_mbedtls_error("mbedtls_ssl_handshake", ret); if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { return NSAPI_ERROR_ALREADY; } else { + print_mbedtls_error("mbedtls_ssl_handshake", ret); return NSAPI_ERROR_AUTH_FAILURE; } } @@ -385,6 +414,13 @@ nsapi_size_or_error_t TLSSocketWrapper::sendto(const SocketAddress &, const void return send(data, size); } +nsapi_size_or_error_t TLSSocketWrapper::sendto_control(const SocketAddress &address, const void *data, + nsapi_size_t size, nsapi_msghdr_t *control, + nsapi_size_t control_size) +{ + return sendto(address, data, size); +} + nsapi_size_or_error_t TLSSocketWrapper::recv(void *data, nsapi_size_t size) { int ret; @@ -445,6 +481,12 @@ nsapi_size_or_error_t TLSSocketWrapper::recvfrom(SocketAddress *address, void *d return recv(data, size); } +nsapi_size_or_error_t TLSSocketWrapper::recvfrom_control(SocketAddress *address, void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) +{ + return recvfrom(address, data, size); +} + void TLSSocketWrapper::print_mbedtls_error(MBED_UNUSED const char *name, MBED_UNUSED int err) { // Avoid pulling in mbedtls_strerror when trace is not enabled diff --git a/connectivity/netsocket/tests/TESTS/netsocket/tls/main.cpp b/connectivity/netsocket/tests/TESTS/netsocket/tls/main.cpp index f6489a3d736..495178d54a4 100644 --- a/connectivity/netsocket/tests/TESTS/netsocket/tls/main.cpp +++ b/connectivity/netsocket/tests/TESTS/netsocket/tls/main.cpp @@ -233,6 +233,9 @@ Case cases[] = { Case("TLSSOCKET_SEND_REPEAT", TLSSOCKET_SEND_REPEAT), Case("TLSSOCKET_SEND_TIMEOUT", TLSSOCKET_SEND_TIMEOUT), Case("TLSSOCKET_NO_CERT", TLSSOCKET_NO_CERT), +#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_FS_IO) + Case("TLSSOCKET_CERT_IN_FILESYSTEM", TLSSOCKET_CERT_IN_FILESYSTEM), +#endif // Temporarily removing this test, as TLS library consumes too much memory // and we see frequent memory allocation failures on architectures with less // RAM such as DISCO_L475VG_IOT1A and NUCLEO_F207ZG (both have 128 kB RAM) diff --git a/connectivity/netsocket/tests/TESTS/netsocket/tls/tls_tests.h b/connectivity/netsocket/tests/TESTS/netsocket/tls/tls_tests.h index f0905fa8ec3..57461683c8b 100644 --- a/connectivity/netsocket/tests/TESTS/netsocket/tls/tls_tests.h +++ b/connectivity/netsocket/tests/TESTS/netsocket/tls/tls_tests.h @@ -89,6 +89,7 @@ void TLSSOCKET_SEND_UNCONNECTED(); void TLSSOCKET_SEND_CLOSED(); void TLSSOCKET_SEND_REPEAT(); void TLSSOCKET_NO_CERT(); +void TLSSOCKET_CERT_IN_FILESYSTEM(); void TLSSOCKET_SIMULTANEOUS(); void TLSSOCKET_SEND_TIMEOUT(); diff --git a/connectivity/netsocket/tests/TESTS/netsocket/tls/tlssocket_cert_in_filesystem.cpp b/connectivity/netsocket/tests/TESTS/netsocket/tls/tlssocket_cert_in_filesystem.cpp new file mode 100644 index 00000000000..cf3dff2e932 --- /dev/null +++ b/connectivity/netsocket/tests/TESTS/netsocket/tls/tlssocket_cert_in_filesystem.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020, Arduino SA, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" +#include "TLSSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" +#include "tls_tests.h" +#include "HeapBlockDevice.h" +#include "LittleFileSystem.h" + +using namespace utest::v1; + +void TLSSOCKET_CERT_IN_FILESYSTEM() +{ + SKIP_IF_TCP_UNSUPPORTED(); + + HeapBlockDevice bd(1024 * 10); + LittleFileSystem fs("fs"); + TEST_ASSERT_EQUAL(0, fs.format(&bd)); + TEST_ASSERT_EQUAL(0, fs.mount(&bd)); + + FILE *fp = fopen("/fs/certs.pem", "wb"); + int ret = fwrite(tls_global::cert, strlen(tls_global::cert), 1, fp); + fclose(fp); + + TLSSocket sock; + TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(NetworkInterface::get_default_instance())); + TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.set_root_ca_cert_path("/fs")); + + SocketAddress a; + TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, NetworkInterface::get_default_instance()->gethostbyname(ECHO_SERVER_ADDR, &a)); + a.set_port(ECHO_SERVER_PORT_TLS); + TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.connect(a)); +} \ No newline at end of file diff --git a/connectivity/netsocket/tests/TESTS/network/emac/emac_TestNetworkStack.cpp b/connectivity/netsocket/tests/TESTS/network/emac/emac_TestNetworkStack.cpp index 6f8afc4cdd9..7a0069ad1dd 100644 --- a/connectivity/netsocket/tests/TESTS/network/emac/emac_TestNetworkStack.cpp +++ b/connectivity/netsocket/tests/TESTS/network/emac/emac_TestNetworkStack.cpp @@ -115,7 +115,7 @@ void EmacTestNetworkStack::socket_attach(nsapi_socket_t handle, void (*callback) } -nsapi_error_t EmacTestNetworkStack::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out) +nsapi_error_t EmacTestNetworkStack::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, NetworkInterface *user_network_interface) { // Test network stack supports only one interface TEST_ASSERT_MESSAGE(!m_interface, "Only one interface supported!"); diff --git a/connectivity/netsocket/tests/TESTS/network/emac/emac_TestNetworkStack.h b/connectivity/netsocket/tests/TESTS/network/emac/emac_TestNetworkStack.h index 95eba068a40..125392b7472 100644 --- a/connectivity/netsocket/tests/TESTS/network/emac/emac_TestNetworkStack.h +++ b/connectivity/netsocket/tests/TESTS/network/emac/emac_TestNetworkStack.h @@ -148,7 +148,7 @@ class EmacTestNetworkStack : public OnboardNetworkStack, private mbed::NonCopyab * @param[out] interface_out pointer to stack interface object controlling the EMAC * @return NSAPI_ERROR_OK on success, or error code */ - virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out); + virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, NetworkInterface *user_network_interface); /** Translates a hostname to an IP address with specific version * diff --git a/connectivity/netsocket/tests/TESTS/network/wifi/get_interface.cpp b/connectivity/netsocket/tests/TESTS/network/wifi/get_interface.cpp index d23e06c377b..b992f165367 100644 --- a/connectivity/netsocket/tests/TESTS/network/wifi/get_interface.cpp +++ b/connectivity/netsocket/tests/TESTS/network/wifi/get_interface.cpp @@ -15,6 +15,8 @@ * limitations under the License. */ +#include "wifi_tests.h" + #define WIFI 2 #if !defined(MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE) || \ MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE != WIFI @@ -25,7 +27,6 @@ #else #include "mbed.h" -#include "WiFiInterface.h" WiFiInterface *get_interface() { diff --git a/connectivity/netsocket/tests/TESTS/network/wifi/get_security.cpp b/connectivity/netsocket/tests/TESTS/network/wifi/get_security.cpp index ddc2771e36d..05a8c13b75d 100644 --- a/connectivity/netsocket/tests/TESTS/network/wifi/get_security.cpp +++ b/connectivity/netsocket/tests/TESTS/network/wifi/get_security.cpp @@ -47,6 +47,8 @@ nsapi_security get_security() if (strcmp(MBED_CONF_APP_WIFI_SECURE_PROTOCOL, SEC_WPA3_WPA2) == 0) { return NSAPI_SECURITY_WPA3_WPA2; } +#elif defined MBED_CONF_NSAPI_DEFAULT_WIFI_SECURITY + return MBED_CONCAT(NSAPI_SECURITY_, MBED_CONF_NSAPI_DEFAULT_WIFI_SECURITY); #endif return NSAPI_SECURITY_NONE; } diff --git a/connectivity/netsocket/tests/TESTS/network/wifi/main.cpp b/connectivity/netsocket/tests/TESTS/network/wifi/main.cpp index ac9c6c7a7d5..78c597339ee 100644 --- a/connectivity/netsocket/tests/TESTS/network/wifi/main.cpp +++ b/connectivity/netsocket/tests/TESTS/network/wifi/main.cpp @@ -27,22 +27,21 @@ #include "utest.h" #include "wifi_tests.h" +#if !defined(MBED_CONF_APP_WIFI_SECURE_SSID) +#error [NOT_SUPPORTED] Requires secure AP +#endif + // Test for parameters #if defined(MBED_CONF_APP_WIFI_SECURE_SSID) && \ - (!defined(MBED_CONF_APP_AP_MAC_SECURE) || \ - !defined(MBED_CONF_APP_MAX_SCAN_SIZE) || \ - !defined(MBED_CONF_APP_WIFI_CH_SECURE) || \ + (!defined(MBED_CONF_APP_MAX_SCAN_SIZE) || \ !defined(MBED_CONF_APP_WIFI_PASSWORD) || \ - !defined(MBED_CONF_APP_WIFI_SECURE_SSID) || \ !defined(MBED_CONF_APP_WIFI_SECURE_PROTOCOL)) #error [NOT_SUPPORTED] Requires parameters from mbed_app.json (for secure connections) #else #if defined(MBED_CONF_APP_WIFI_UNSECURE_SSID) && \ - (!defined(MBED_CONF_APP_AP_MAC_UNSECURE) || \ - !defined(MBED_CONF_APP_MAX_SCAN_SIZE) || \ - !defined(MBED_CONF_APP_WIFI_CH_UNSECURE) || \ - !defined(MBED_CONF_APP_WIFI_UNSECURE_SSID)) + (!defined(MBED_CONF_APP_MAX_SCAN_SIZE) || \ + !defined(MBED_CONF_APP_WIFI_CH_UNSECURE)) #error [NOT_SUPPORTED] Requires parameters from mbed_app.json (for unsecure connections) #else diff --git a/connectivity/netsocket/tests/TESTS/network/wifi/template_mbed_app.txt b/connectivity/netsocket/tests/TESTS/network/wifi/template_mbed_app.txt index 686a83b30c3..482143c6352 100644 --- a/connectivity/netsocket/tests/TESTS/network/wifi/template_mbed_app.txt +++ b/connectivity/netsocket/tests/TESTS/network/wifi/template_mbed_app.txt @@ -1,39 +1,35 @@ { "config": { "wifi-secure-ssid": { - "help": "WiFi SSID for WPA2 secured network", + "help": "WiFi SSID for secure network", + "optional_parameter": "if value is null, MBED_CONF_NSAPI_DEFAULT_WIFI_SSID is used", "value": "\"SSID-SECURE\"" }, "wifi-unsecure-ssid": { - "help": "WiFi SSID for unsecure netwrok", + "help": "WiFi SSID for unsecure network", + "optional_parameter": "if value is null, non-secure tests are skipped", "value": "\"SSID-UNSECURE\"" }, "wifi-password": { "help": "WiFi Password", + "optional_parameter": "if value is null, MBED_CONF_NSAPI_DEFAULT_WIFI_PASSWORD is used", "value": "\"PASSWORD\"" }, "wifi-secure-protocol": { "help": "WiFi security protocol, valid values are WEP, WPA, WPA2, WPA/WPA2", - "value": "\"WPA/WPA2\"" + "optional_parameter": "if value is null, MBED_CONF_NSAPI_DEFAULT_WIFI_SECURITY is used", + "value": "\"WPA2\"" }, "wifi-ch-secure": { - "help": "Channel number of secure SSID", + "help": "Channel number of secure SSID (if set_channel() is supported)", "value": 1 }, "wifi-ch-unsecure": { - "help": "Channel number of unsecure SSID", + "help": "Channel number of unsecure SSID (if set_channel() is supported)", "value": 2 }, - "ap-mac-secure": { - "help": "BSSID of secure AP in form of AA:BB:CC:DD:EE:FF", - "value": "\"AA:AA:AA:AA:AA:AA\"" - }, - "ap-mac-unsecure": { - "help": "BSSID of unsecure AP in form of \"AA:BB:CC:DD:EE:FF\"", - "value": "\"BB:BB:BB:BB:BB:BB\"" - }, "max-scan-size": { - "help": "How many networks may appear in Wifi scan result", + "help": "How many networks may appear in Wifi scan result (default is 10)", "value": 10 } }, diff --git a/connectivity/netsocket/tests/TESTS/network/wifi/wifi_connect_disconnect_repeat.cpp b/connectivity/netsocket/tests/TESTS/network/wifi/wifi_connect_disconnect_repeat.cpp index 4f8e53ed5c4..de24fa53130 100644 --- a/connectivity/netsocket/tests/TESTS/network/wifi/wifi_connect_disconnect_repeat.cpp +++ b/connectivity/netsocket/tests/TESTS/network/wifi/wifi_connect_disconnect_repeat.cpp @@ -34,8 +34,10 @@ void wifi_connect_disconnect_repeat(void) TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, error); for (int i = 0; i < 10; i++) { + printf("#%u connecting...\n", i); error = wifi->connect(); TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, error); + printf("#%u diconnecting...\n", i); error = wifi->disconnect(); TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, error); } diff --git a/connectivity/netsocket/tests/TESTS/network/wifi/wifi_connect_secure_fail.cpp b/connectivity/netsocket/tests/TESTS/network/wifi/wifi_connect_secure_fail.cpp index 47898de809c..72da4c03404 100644 --- a/connectivity/netsocket/tests/TESTS/network/wifi/wifi_connect_secure_fail.cpp +++ b/connectivity/netsocket/tests/TESTS/network/wifi/wifi_connect_secure_fail.cpp @@ -31,7 +31,9 @@ void wifi_connect_secure_fail(void) TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->set_credentials(MBED_CONF_APP_WIFI_SECURE_SSID, "aaaaaaaa", get_security())); nsapi_error_t error; + printf("Wifi connection with wrong password\n"); error = wifi->connect(); + printf("=> %d => Wifi disconnection\n", error); wifi->disconnect(); TEST_ASSERT(error == NSAPI_ERROR_AUTH_FAILURE || error == NSAPI_ERROR_CONNECTION_TIMEOUT || diff --git a/connectivity/netsocket/tests/TESTS/network/wifi/wifi_scan.cpp b/connectivity/netsocket/tests/TESTS/network/wifi/wifi_scan.cpp index 202a33181cd..cfa86355b6e 100644 --- a/connectivity/netsocket/tests/TESTS/network/wifi/wifi_scan.cpp +++ b/connectivity/netsocket/tests/TESTS/network/wifi/wifi_scan.cpp @@ -31,21 +31,17 @@ void wifi_scan(void) WiFiAccessPoint ap[MBED_CONF_APP_MAX_SCAN_SIZE]; int size = wifi->scan(ap, MBED_CONF_APP_MAX_SCAN_SIZE); + printf("Scanned %u AP\n", size); TEST_ASSERT(size >= 1); bool secure_found = false; bool unsecure_found = false; - char secure_bssid[6]; - char unsecure_bssid[6]; - const char *coversion_string = "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"; - TEST_ASSERT_EQUAL_INT_MESSAGE(6, sscanf(MBED_CONF_APP_AP_MAC_SECURE, coversion_string, &secure_bssid[0], &secure_bssid[1], &secure_bssid[2], &secure_bssid[3], &secure_bssid[4], &secure_bssid[5]), "Failed to convert ap-mac-secure from mbed_app.json"); - TEST_ASSERT_EQUAL_INT_MESSAGE(6, sscanf(MBED_CONF_APP_AP_MAC_UNSECURE, coversion_string, &unsecure_bssid[0], &unsecure_bssid[1], &unsecure_bssid[2], &unsecure_bssid[3], &unsecure_bssid[4], &unsecure_bssid[5]), "Failed to convert ap-mac-unsecure from mbed_app.json"); - for (int i = 0; i < size; i++) { const char *ssid = ap[i].get_ssid(); nsapi_security_t security = ap[i].get_security(); int8_t rssi = ap[i].get_rssi(); + printf("AP %u ssid %s security %u rssi %d\n", i, ssid, security, rssi); TEST_ASSERT_INT8_WITHIN(-10, -100, rssi); #if defined(MBED_CONF_APP_WIFI_SECURE_SSID) if (strcmp(MBED_CONF_APP_WIFI_SECURE_SSID, ssid) == 0) { diff --git a/connectivity/netsocket/tests/TESTS/network/wifi/wifi_tests.h b/connectivity/netsocket/tests/TESTS/network/wifi/wifi_tests.h index 37df86c4f2e..60de5b6e774 100644 --- a/connectivity/netsocket/tests/TESTS/network/wifi/wifi_tests.h +++ b/connectivity/netsocket/tests/TESTS/network/wifi/wifi_tests.h @@ -17,8 +17,29 @@ #ifndef WIFI_TESTS_H #define WIFI_TESTS_H +#ifdef MBED_CONF_NSAPI_PRESENT #include "WiFiInterface.h" +#if !defined(MBED_CONF_APP_WIFI_SECURE_SSID) +#define MBED_CONF_APP_WIFI_SECURE_SSID MBED_CONF_NSAPI_DEFAULT_WIFI_SSID +#endif + +#if !defined(MBED_CONF_APP_WIFI_PASSWORD) +#define MBED_CONF_APP_WIFI_PASSWORD MBED_CONF_NSAPI_DEFAULT_WIFI_PASSWORD +#endif + +#if !defined(MBED_CONF_APP_WIFI_SECURE_PROTOCOL) +#define MBED_CONF_APP_WIFI_SECURE_PROTOCOL MBED_CONF_NSAPI_DEFAULT_WIFI_SECURITY +#endif + +#if !defined(MBED_CONF_APP_WIFI_CH_SECURE) +#define MBED_CONF_APP_WIFI_CH_SECURE 1 +#endif + +#if !defined(MBED_CONF_APP_MAX_SCAN_SIZE) +#define MBED_CONF_APP_MAX_SCAN_SIZE 10 +#endif + /** Get WiFiInterface based on provided * app_json. */ WiFiInterface *get_interface(void); @@ -82,3 +103,4 @@ void wifi_scan_null(void); void wifi_scan(void); #endif //WIFI_TESTS_H +#endif // MBED_CONF_NSAPI_PRESENT diff --git a/connectivity/netsocket/tests/UNITTESTS/doubles/NetworkStack_stub.cpp b/connectivity/netsocket/tests/UNITTESTS/doubles/NetworkStack_stub.cpp index 7d6331a4d9c..877bfc7db71 100644 --- a/connectivity/netsocket/tests/UNITTESTS/doubles/NetworkStack_stub.cpp +++ b/connectivity/netsocket/tests/UNITTESTS/doubles/NetworkStack_stub.cpp @@ -17,7 +17,6 @@ #include "netsocket/NetworkStack.h" #include "netsocket/nsapi_dns.h" -#include "mbed.h" #include "stddef.h" #include diff --git a/connectivity/netsocket/tests/UNITTESTS/doubles/NetworkStack_stub.h b/connectivity/netsocket/tests/UNITTESTS/doubles/NetworkStack_stub.h index d6b630a1d80..0c2d9bc7dbf 100644 --- a/connectivity/netsocket/tests/UNITTESTS/doubles/NetworkStack_stub.h +++ b/connectivity/netsocket/tests/UNITTESTS/doubles/NetworkStack_stub.h @@ -136,6 +136,12 @@ class NetworkStackstub : public NetworkStack { { return return_value; }; + virtual nsapi_size_or_error_t socket_sendto_control(nsapi_socket_t handle, const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) override + { + return return_value; + }; virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *buffer, nsapi_size_t size) { @@ -149,6 +155,16 @@ class NetworkStackstub : public NetworkStack { } return return_value; }; + virtual nsapi_size_or_error_t socket_recvfrom_control(nsapi_socket_t handle, SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) override + { + if (control != NULL) { + return NSAPI_ERROR_UNSUPPORTED; + } + + return socket_recvfrom(handle, address, data, size); + }; virtual void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data) {}; private: diff --git a/connectivity/netsocket/tests/UNITTESTS/doubles/OnboardNetworkStack_mock.h b/connectivity/netsocket/tests/UNITTESTS/doubles/OnboardNetworkStack_mock.h index 24d15f59425..79c3b3ffe1c 100644 --- a/connectivity/netsocket/tests/UNITTESTS/doubles/OnboardNetworkStack_mock.h +++ b/connectivity/netsocket/tests/UNITTESTS/doubles/OnboardNetworkStack_mock.h @@ -47,9 +47,18 @@ class OnboardNetworkStackMock : public OnboardNetworkStack { MOCK_METHOD5(setsockopt, nsapi_error_t(nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen)); MOCK_METHOD5(getsockopt, nsapi_error_t(nsapi_socket_t handle, int level, int optname, const void *optval, unsigned *optlen)); // MOCK_METHOD3(socket_attach, void(nsapi_socket_t handle, void (*callback)(void *), void *data)); - MOCK_METHOD3(add_ethernet_interface, nsapi_error_t(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out)); MOCK_METHOD3(add_ppp_interface, nsapi_error_t(PPP &ppp, bool default_if, OnboardNetworkStack::Interface **interface_out)); MOCK_METHOD1(set_default_interface, void (OnboardNetworkStack::Interface *interface)); + MOCK_METHOD4(add_ethernet_interface_mock, nsapi_error_t(EMAC &emac, bool default_if, + OnboardNetworkStack::Interface **interface_out, + NetworkInterface *user_network_interface)); + + // Wrapper written to handle function with the default argument in the gmock. + nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Interface **interface_out, NetworkInterface *user_network_interface = NULL) + { + return add_ethernet_interface_mock(emac, default_if, interface_out, user_network_interface); + } + void *socket_cb; // No need to mock socket_attach really. void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data) @@ -57,7 +66,6 @@ class OnboardNetworkStackMock : public OnboardNetworkStack { socket_cb = data; }; - static OnboardNetworkStackMock &get_instance() { static OnboardNetworkStackMock stackMock1; diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/CellularNonIPSocket/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/CellularNonIPSocket/CMakeLists.txt index 98da637f74f..9605ff2d0eb 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/CellularNonIPSocket/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/CellularNonIPSocket/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-cellular-nonip-socket-unittest) add_executable(${TEST_NAME}) @@ -22,7 +24,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-drivers + mbed-headers-rtos mbed-headers-netsocket mbed-headers-cellular mbed-stubs @@ -32,6 +36,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/DTLSSocket/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/DTLSSocket/CMakeLists.txt index 311aa7918fe..52bce8266f0 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/DTLSSocket/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/DTLSSocket/CMakeLists.txt @@ -1,36 +1,33 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-dtls-socket-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} - PRIVATE + PRIVATE MBED_CONF_NSAPI_DNS_ADDRESSES_LIMIT=10 ) target_sources(${TEST_NAME} PRIVATE - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/SocketAddress.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkStack.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/InternetSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/InternetDatagramSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/UDPSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/DTLSSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/DTLSSocketWrapper.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/TLSSocketWrapper.cpp - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/ip4tos.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/ip6tos.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c test_DTLSSocket.cpp ) target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-drivers + mbed-headers-rtos mbed-headers-nanostack-libservice mbed-headers-mbedtls mbed-headers-netsocket @@ -47,6 +44,4 @@ set_source_files_properties(${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/ set_source_files_properties(${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/DTLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) set_source_files_properties(${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/TLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/DTLSSocketWrapper/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/DTLSSocketWrapper/CMakeLists.txt index ce9bc9dc5ea..0ace1fd7ac7 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/DTLSSocketWrapper/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/DTLSSocketWrapper/CMakeLists.txt @@ -1,35 +1,32 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-dtls-socket-wrapper-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} - PRIVATE + PRIVATE MBED_CONF_NSAPI_DNS_ADDRESSES_LIMIT=10 ) target_sources(${TEST_NAME} PRIVATE - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/SocketAddress.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkStack.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/InternetSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/InternetDatagramSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/UDPSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/DTLSSocketWrapper.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/TLSSocketWrapper.cpp - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/ip4tos.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/ip6tos.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c test_DTLSSocketWrapper.cpp ) target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-drivers + mbed-headers-rtos mbed-headers-nanostack-libservice mbed-headers-mbedtls mbed-headers-netsocket @@ -46,6 +43,4 @@ set_source_files_properties(${mbed-os_SOURCE_DIR}/connectivity/netsocket/tests/U set_source_files_properties(${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/DTLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) set_source_files_properties(${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/TLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/EthernetInterface/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/EthernetInterface/CMakeLists.txt index 356e869d887..c5964c23dcb 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/EthernetInterface/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/EthernetInterface/CMakeLists.txt @@ -1,12 +1,14 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-ethernet-interface-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} - PRIVATE + PRIVATE MBED_CONF_NSAPI_DNS_ADDRESSES_LIMIT=10 ) @@ -15,29 +17,25 @@ target_sources(${TEST_NAME} ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/SocketAddress.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/EthernetInterface.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/EMACInterface.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkInterface.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkStack.cpp ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/ip4tos.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/ip6tos.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libList/ns_list.c test_EthernetInterface.cpp ) target_link_libraries(${TEST_NAME} PRIVATE + mbed-headers-drivers + mbed-headers-rtos mbed-headers-nanostack-libservice mbed-headers-mbedtls mbed-headers-netsocket - mbed-headers mbed-stubs mbed-stubs-headers mbed-stubs-netsocket gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/EthernetInterface/test_EthernetInterface.cpp b/connectivity/netsocket/tests/UNITTESTS/netsocket/EthernetInterface/test_EthernetInterface.cpp index 8db41166ab2..1b0851f4395 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/EthernetInterface/test_EthernetInterface.cpp +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/EthernetInterface/test_EthernetInterface.cpp @@ -68,7 +68,7 @@ class TestEthernetInterface: public testing::Test { /* Enclose the heavily-used connection procedure to improve code redability */ void doConnect(bool dhcp = true, bool blocking = true) { - EXPECT_CALL(*stackMock, add_ethernet_interface(testing::Ref(*emacMock), true, _)) + EXPECT_CALL(*stackMock, add_ethernet_interface_mock(testing::Ref(*emacMock), true, _, _)) .Times(1) .WillOnce(DoAll(SetArgPointee<2>(netStackIface), Return(NSAPI_ERROR_OK))); EXPECT_CALL(*netStackIface, attach(_)) @@ -113,7 +113,7 @@ TEST_F(TestEthernetInterface, connect) TEST_F(TestEthernetInterface, connect_failure) { - EXPECT_CALL(*stackMock, add_ethernet_interface(testing::Ref(*emacMock), true, _)) + EXPECT_CALL(*stackMock, add_ethernet_interface_mock(testing::Ref(*emacMock), true, _, _)) .Times(1) .WillOnce(DoAll(SetArgPointee<2>(netStackIface), Return(NSAPI_ERROR_NO_MEMORY))); EXPECT_EQ(NSAPI_ERROR_NO_MEMORY, iface->connect()); @@ -158,7 +158,7 @@ TEST_F(TestEthernetInterface, set_network) EXPECT_EQ(NSAPI_ERROR_OK, iface->set_network(ipAddress, netmask, gateway)); // Now the bringup should have different arguments. We can't use doConnect method. - EXPECT_CALL(*stackMock, add_ethernet_interface(testing::Ref(*emacMock), true, _)) + EXPECT_CALL(*stackMock, add_ethernet_interface_mock(testing::Ref(*emacMock), true, _, _)) .Times(1) .WillOnce(DoAll(SetArgPointee<2>(netStackIface), Return(NSAPI_ERROR_OK))); EXPECT_CALL(*netStackIface, attach(_)) diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/IfaceDnsSocket/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/IfaceDnsSocket/CMakeLists.txt index d658c702dc3..5e4ae2f991d 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/IfaceDnsSocket/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/IfaceDnsSocket/CMakeLists.txt @@ -1,12 +1,14 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-iface-dns-socket-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} - PRIVATE + PRIVATE MBED_CONF_NSAPI_DNS_ADDRESSES_LIMIT=10 DEVICE_EMAC MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE=ETHERNET @@ -20,13 +22,10 @@ target_sources(${TEST_NAME} PRIVATE ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/SocketAddress.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkInterface.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkInterfaceDefaults.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkStack.cpp #nsapi_create_stack ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/InternetSocket.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/TCPSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/InternetDatagramSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/UDPSocket.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/SocketStats.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/EthernetInterface.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/EMACInterface.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/nsapi_dns.cpp @@ -35,14 +34,15 @@ target_sources(${TEST_NAME} ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libList/ns_list.c moduletest.cpp ) target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-drivers + mbed-headers-rtos mbed-headers-nanostack-libservice mbed-headers-mbedtls mbed-headers-netsocket @@ -52,6 +52,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/InternetSocket/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/InternetSocket/CMakeLists.txt index 53daa2164cb..075df08ed06 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/InternetSocket/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/InternetSocket/CMakeLists.txt @@ -1,23 +1,22 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-internet-socket-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} - PRIVATE + PRIVATE MBED_CONF_NSAPI_DNS_ADDRESSES_LIMIT=10 ) target_sources(${TEST_NAME} PRIVATE ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/SocketAddress.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkStack.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/InternetSocket.cpp - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/ip4tos.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/ip6tos.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c test_InternetSocket.cpp @@ -25,15 +24,15 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-drivers + mbed-headers-rtos mbed-headers-nanostack-libservice mbed-headers-netsocket mbed-stubs mbed-stubs-headers mbed-stubs-netsocket + mbed-stubs-nanostack-libservice gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/InternetSocket/test_InternetSocket.cpp b/connectivity/netsocket/tests/UNITTESTS/netsocket/InternetSocket/test_InternetSocket.cpp index 9375aa9686a..54ef26ac11c 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/InternetSocket/test_InternetSocket.cpp +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/InternetSocket/test_InternetSocket.cpp @@ -56,6 +56,16 @@ class stubInternetSocket : public InternetSocket { { return return_value; } + virtual nsapi_size_or_error_t sendto_control(const SocketAddress &address, const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) + { + return return_value; + } + virtual nsapi_size_or_error_t recvfrom_control(SocketAddress *address, void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) + { + return return_value; + } virtual Socket *accept(nsapi_error_t *error = NULL) { return NULL; diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkInterface/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkInterface/CMakeLists.txt index 7f03ae21062..de0378bdf4c 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkInterface/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkInterface/CMakeLists.txt @@ -1,34 +1,28 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-network-interface-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} - PRIVATE + PRIVATE MBED_CONF_PLATFORM_CALLBACK_COMPARABLE MBED_CONF_NSAPI_DNS_ADDRESSES_LIMIT=10 - + ) target_sources(${TEST_NAME} PRIVATE - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/SocketAddress.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkStack.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkInterface.cpp - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/ip4tos.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/ip6tos.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libList/ns_list.c test_NetworkInterface.cpp ) target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers mbed-headers-nanostack-libservice mbed-headers-netsocket mbed-stubs @@ -37,6 +31,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkStack/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkStack/CMakeLists.txt index b6ac2bffef3..83c805e500d 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkStack/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkStack/CMakeLists.txt @@ -1,30 +1,33 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-network-stack-unittest) add_executable(${TEST_NAME}) target_compile_definitions(${TEST_NAME} PRIVATE - MBED_CONF_NSAPI_DNS_ADDRESSES_LIMIT=10 + MBED_CONF_NSAPI_DNS_ADDRESSES_LIMIT=10 ) target_sources(${TEST_NAME} PRIVATE ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/SocketAddress.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkStack.cpp + ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkStack.cpp ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/ip4tos.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/ip6tos.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c + ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c test_NetworkStack.cpp + test_MsgHeaderIterator.cpp ) target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events mbed-headers-nanostack-libservice mbed-headers-netsocket mbed-stubs @@ -33,6 +36,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkStack/test_MsgHeaderIterator.cpp b/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkStack/test_MsgHeaderIterator.cpp new file mode 100644 index 00000000000..5ed061ea9cf --- /dev/null +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkStack/test_MsgHeaderIterator.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021, Arm Limited and affiliates + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gtest/gtest.h" +#include "netsocket/MsgHeader.h" +#include "netsocket/nsapi_types.h" + +struct custom_type_t { + nsapi_msghdr_t hdr; + uint64_t custom_field1; + uint64_t custom_field2; + uint64_t custom_field3; + uint64_t custom_field4; +}; + +struct pktinfo_buffer_t { + pktinfo_buffer_t() + { + pkt_info_1.hdr.len = sizeof(nsapi_pktinfo_t); + pkt_info_2.hdr.len = sizeof(nsapi_pktinfo_t); + } + nsapi_pktinfo_t pkt_info_1; + nsapi_pktinfo_t pkt_info_2; +}; + +struct custom_buffer_t { + custom_buffer_t() + { + pkt_info.hdr.len = sizeof(nsapi_pktinfo_t); + msg_hdr.len = sizeof(nsapi_msghdr_t); + custom.hdr.len = sizeof(custom_type_t); + } + nsapi_pktinfo_t pkt_info; + nsapi_msghdr_t msg_hdr; + custom_type_t custom; +}; + +class TestMsgHeaderIterator : public testing::Test { +protected: + pktinfo_buffer_t p_buff; + custom_buffer_t c_buff; + + virtual void SetUp() {} + + virtual void TearDown() {} +}; + +TEST_F(TestMsgHeaderIterator, pktinfo_list) +{ + nsapi_msghdr_t *hdr = reinterpret_cast(&p_buff); + MsgHeaderIterator it(hdr, sizeof(p_buff)); + + EXPECT_EQ(it.next(), &p_buff.pkt_info_1.hdr); + EXPECT_EQ(it.next(), &p_buff.pkt_info_2.hdr); + EXPECT_TRUE(it.next() == nullptr); +} + +TEST_F(TestMsgHeaderIterator, custom_list) +{ + nsapi_msghdr_t *hdr_c = reinterpret_cast(&c_buff); + MsgHeaderIterator it(hdr_c, sizeof(c_buff)); + + EXPECT_EQ(it.next(), &c_buff.pkt_info.hdr); + EXPECT_EQ(it.next(), &c_buff.msg_hdr); + EXPECT_EQ(it.next(), &c_buff.custom.hdr); + EXPECT_TRUE(it.next() == nullptr); +} + +TEST_F(TestMsgHeaderIterator, null_list) +{ + MsgHeaderIterator it(nullptr, sizeof(p_buff)); + + EXPECT_TRUE(it.next() == nullptr); +} + +TEST_F(TestMsgHeaderIterator, wrong_list_size) +{ + nsapi_msghdr_t *hdr = reinterpret_cast(&p_buff); + MsgHeaderIterator it(hdr, 0); + + EXPECT_TRUE(it.next() == nullptr); +} + +TEST_F(TestMsgHeaderIterator, wrong_member_len) +{ + nsapi_msghdr_t *hdr = reinterpret_cast(&p_buff); + MsgHeaderIterator it(hdr, sizeof(p_buff)); + p_buff.pkt_info_1.hdr.len = 0; + + EXPECT_TRUE(it.next() == nullptr); +} diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/PPPInterface/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/PPPInterface/CMakeLists.txt index 2fc21800523..0b118f8e0bf 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/PPPInterface/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/PPPInterface/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-ppp-interface-unittest) add_executable(${TEST_NAME}) @@ -14,21 +16,18 @@ target_sources(${TEST_NAME} PRIVATE ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/SocketAddress.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/PPPInterface.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/EMACInterface.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkInterface.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkStack.cpp ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/ip4tos.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/ip6tos.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libList/ns_list.c test_PPPInterface.cpp ) target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-drivers + mbed-headers-rtos mbed-headers-nanostack-libservice mbed-headers-mbedtls mbed-headers-netsocket @@ -38,6 +37,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/SocketAddress/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/SocketAddress/CMakeLists.txt index 3cad0d68f4a..d03fc3e41ac 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/SocketAddress/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/SocketAddress/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-socket-address-unittest) add_executable(${TEST_NAME}) @@ -12,13 +14,12 @@ target_sources(${TEST_NAME} ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/ip6tos.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c + ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c test_SocketAddress.cpp ) target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers mbed-headers-nanostack-libservice mbed-headers-netsocket mbed-stubs @@ -26,6 +27,4 @@ target_link_libraries(${TEST_NAME} gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/TCPSocket/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/TCPSocket/CMakeLists.txt index 8e54e741647..451b9ade803 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/TCPSocket/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/TCPSocket/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-tcp-socket-unittest) add_executable(${TEST_NAME}) @@ -13,12 +15,9 @@ target_compile_definitions(${TEST_NAME} target_sources(${TEST_NAME} PRIVATE ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/SocketAddress.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkStack.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/InternetSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/TCPSocket.cpp - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/ip4tos.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/ip6tos.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c test_TCPSocket.cpp @@ -26,15 +25,15 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-drivers + mbed-headers-rtos mbed-headers-nanostack-libservice mbed-headers-netsocket mbed-stubs mbed-stubs-headers mbed-stubs-netsocket + mbed-stubs-nanostack-libservice gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocket/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocket/CMakeLists.txt index 996a83f2162..0e7806ea5be 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocket/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocket/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-tls-socket-unittest) add_executable(${TEST_NAME}) @@ -12,23 +14,18 @@ target_compile_definitions(${TEST_NAME} target_sources(${TEST_NAME} PRIVATE - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/SocketAddress.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkStack.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/InternetSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/TCPSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/TLSSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/TLSSocketWrapper.cpp - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/ip4tos.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/ip6tos.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c test_TLSSocket.cpp ) target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-drivers + mbed-headers-rtos mbed-headers-nanostack-libservice mbed-headers-mbedtls mbed-headers-netsocket @@ -44,6 +41,4 @@ set_source_files_properties(${CMAKE_CURRENT_LIST_DIR}/test_TLSSocket.cpp PROPERT set_source_files_properties(${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/TLSSocket.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) set_source_files_properties(${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/TLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/CMakeLists.txt index 963806da5dc..ada78a89d36 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-tls-socket-wrapper-unittest) add_executable(${TEST_NAME}) @@ -13,13 +15,10 @@ target_compile_definitions(${TEST_NAME} target_sources(${TEST_NAME} PRIVATE ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/SocketAddress.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkStack.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/InternetSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/TCPSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/TLSSocketWrapper.cpp - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/ip4tos.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/ip6tos.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c test_TLSSocketWrapper.cpp @@ -27,7 +26,9 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-events + mbed-headers-drivers + mbed-headers-rtos mbed-headers-nanostack-libservice mbed-headers-mbedtls mbed-headers-netsocket @@ -35,6 +36,7 @@ target_link_libraries(${TEST_NAME} mbed-stubs-headers mbed-stubs-mbedtls mbed-stubs-netsocket + mbed-stubs-nanostack-libservice gmock_main ) @@ -42,6 +44,4 @@ set(MBEDTLS_USER_CONFIG_FILE_PATH "\"${mbed-os_SOURCE_DIR}/connectivity/netsocke set_source_files_properties(${mbed-os_SOURCE_DIR}/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) set_source_files_properties(${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/TLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp b/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp index b0e473a401e..6ba24218175 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp @@ -399,6 +399,12 @@ TEST_F(TestTLSSocketWrapper, set_root_ca_cert_invalid) EXPECT_EQ(wrapper->set_root_ca_cert(cert, strlen(cert)), NSAPI_ERROR_PARAMETER); } +TEST_F(TestTLSSocketWrapper, set_root_ca_cert_path) +{ + EXPECT_EQ(transport->open(&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->set_root_ca_cert_path("/"), NSAPI_ERROR_OK); +} + TEST_F(TestTLSSocketWrapper, set_client_cert_key) { EXPECT_EQ(wrapper->get_own_cert(), static_cast(NULL)); diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/tls_test_config.h b/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/tls_test_config.h index 4f9ce6b96c5..ad2d3d8d44c 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/tls_test_config.h +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/tls_test_config.h @@ -19,6 +19,6 @@ #define UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ #define MBEDTLS_SSL_CLI_C - +#define MBEDTLS_FS_IO #endif /* UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ */ diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/UDPSocket/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/UDPSocket/CMakeLists.txt index f79024d2572..f0a1a62e2ba 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/UDPSocket/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/UDPSocket/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-udp-socket-unittest) add_executable(${TEST_NAME}) @@ -13,13 +15,10 @@ target_compile_definitions(${TEST_NAME} target_sources(${TEST_NAME} PRIVATE ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/SocketAddress.cpp - ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/NetworkStack.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/InternetSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/InternetDatagramSocket.cpp ${mbed-os_SOURCE_DIR}/connectivity/netsocket/source/UDPSocket.cpp - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/ip4tos.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/ip6tos.c - ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c ${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c test_UDPSocket.cpp @@ -27,15 +26,15 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers + mbed-headers-drivers + mbed-headers-rtos mbed-headers-nanostack-libservice mbed-headers-netsocket mbed-stubs mbed-stubs-headers mbed-stubs-netsocket + mbed-stubs-nanostack-libservice gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/WiFiAccessPoint/CMakeLists.txt b/connectivity/netsocket/tests/UNITTESTS/netsocket/WiFiAccessPoint/CMakeLists.txt index f6a5ef1832a..6100efdc920 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/WiFiAccessPoint/CMakeLists.txt +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/WiFiAccessPoint/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include(GoogleTest) + set(TEST_NAME netsocket-wifi-access-point-unittest) add_executable(${TEST_NAME}) @@ -13,13 +15,10 @@ target_sources(${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE - mbed-headers mbed-headers-netsocket mbed-stubs mbed-stubs-headers gmock_main ) -add_test(NAME "${TEST_NAME}" COMMAND ${TEST_NAME}) - -set_tests_properties(${TEST_NAME} PROPERTIES LABELS "netsocket") +gtest_discover_tests(${TEST_NAME} PROPERTIES LABELS "netsocket") diff --git a/docker_images/mbed-os-env/Dockerfile b/docker_images/mbed-os-env/Dockerfile new file mode 100644 index 00000000000..942a2b72ce4 --- /dev/null +++ b/docker_images/mbed-os-env/Dockerfile @@ -0,0 +1,98 @@ +# ------------------------------------------------------------------------------ +# Pull base image +FROM ubuntu:20.04 + +# ------------------------------------------------------------------------------ +# set locale +ENV LANG C.UTF-8 +ENV LC_ALL C.UTF-8 + +# ------------------------------------------------------------------------------ +# Arguments +ARG WORKDIR=/root + +# ------------------------------------------------------------------------------ +# Install tools via apt +ENV DEBIAN_FRONTEND=noninteractive +RUN set -x \ + && apt -y update \ + && apt -y install \ + git \ + wget \ + python3 \ + python3-dev \ + python3-setuptools \ + python3-pip \ + build-essential \ + astyle \ + mercurial \ + ninja-build \ + libssl-dev \ + cargo \ + flex \ + bison \ + doxygen \ + aspell \ + ccache \ + gcovr \ + && apt clean && rm -rf /var/lib/apt/lists \ + && update-alternatives --install /usr/bin/python python /usr/bin/python3.8 1 \ + && : # last line + +RUN set -x \ + && pip3 install -U cmake + +# Set up Mbed environment +WORKDIR /tmp/ +COPY requirements.txt . +RUN set -x \ + && pip3 install -r requirements.txt \ + && : # last line + +COPY tools/cmake/requirements.txt . +RUN set -x \ + && pip3 install -r requirements.txt \ + && : # last line + + +# ------------------------------------------------------------------------------ +# Install Python modules (which are not included in requirements.txt) +RUN set -x \ + && pip3 install -U \ + mbed-cli \ + mbed-tools \ + && : # last line + +# ------------------------------------------------------------------------------ +# Install arm-none-eabi-gcc +WORKDIR /opt/mbed-os-toolchain +RUN set -x \ + && [ "$(uname -m)" = "aarch64" ] && \ + TARBALL="gcc-arm-none-eabi-10.3-2021.07-aarch64-linux.tar.bz2" || \ + TARBALL="gcc-arm-none-eabi-10.3-2021.07-x86_64-linux.tar.bz2" \ + && wget -q https://developer.arm.com/-/media/Files/downloads/gnu-rm/10.3-2021.07/${TARBALL} \ + && tar -xjf ${TARBALL} \ + && rm ${TARBALL} \ + && : # last line + +# ------------------------------------------------------------------------------ +# Configure environment variables +ENV MBED_GCC_ARM_PATH=/opt/mbed-os-toolchain/gcc-arm-none-eabi-10.3-2021.07/bin/ +ENV PATH="${PATH}:${MBED_GCC_ARM_PATH}" + +# ------------------------------------------------------------------------------ +# Display, check and save environment settings +# NOTE: using bash instead of Ubuntu default bash due to unsupport for pipefail +# Pipefail is crucial here, if the tools didn't install properly, docker build should not pass because of piping +RUN /bin/bash -c \ + "set -x -o pipefail \ + && arm-none-eabi-gcc --version | grep arm-none-eabi-gcc | tee env_settings \ + && cmake --version | grep version | tee -a env_settings \ + && python --version 2>&1 | tee -a env_settings \ + && (echo -n 'mbed-cli ' && mbed --version) | tee -a env_settings \ + && (echo -n 'mbed-greentea ' && mbedgt --version | grep ^[0-9]) | tee -a env_settings \ + && (echo -n 'mbed-host-tests ' && mbedhtrun --version) | tee -a env_settings \ + && (echo -n 'mbed-tools ' && mbed-tools --version) | tee -a env_settings \ + && : # LAST LINE" + +WORKDIR /root diff --git a/docker_images/mbed-os-env/README.md b/docker_images/mbed-os-env/README.md new file mode 100644 index 00000000000..54ced8ca8f1 --- /dev/null +++ b/docker_images/mbed-os-env/README.md @@ -0,0 +1,50 @@ +# Mbed OS development environment Docker image + +This Docker image is the official Mbed OS development environment. + +* It is based on Ubuntu 20.04 +* Python and CMake are installed +* Arm-none-eabi-gcc toolchain is installed +* Latest released version of mbed-cli and mbed-greentea are installed +* All other Mbed OS dependency tools are installed. + +# How to use the Docker image: + +## Pull the Docker image +```bash +docker pull ghcr.io/armmbed/mbed-os-env: